Rabbitmq How to read data at once without while loop - rabbitmq

I'm reading data from RabbitMQ (java client) in this way.
while(true)
{
QueueingConsumer.Delivery delivery = consumer.nextDelivery();
String message = new String(delivery.getBody());
System.out.println(message);
}
Can I read all the data in the queue without while loop?

Have you read the tutorials on the RabbitMQ website?
this looks like the basic java code for consuming messages:
Consumer consumer = new DefaultConsumer(channel) {
#Override
public void handleDelivery(String consumerTag, Envelope envelope, AMQP.BasicProperties properties, byte[] body)
throws IOException {
String message = new String(body, "UTF-8");
System.out.println(" [x] Received '" + message + "'");
}
};
channel.basicConsume(QUEUE_NAME, true, consumer);
this should send all messages to the specified consumer.

Related

RabbitMQ queue declare never ends

I'm just trying to make a simple test for RabbitMQ, and I have Erlang installed as well as RabbitMQ running.
My receiver:
private final static String QUEUE_NAME = "hello";
public static void main(String[] argv) throws Exception {
ConnectionFactory factory = new ConnectionFactory();
factory.setHost("localhost");
Connection connection = factory.newConnection();
Channel channel = connection.createChannel();
channel.queueDeclare(QUEUE_NAME, false, false, false, null);
System.out.println(" [*] Waiting for messages. To exit press CTRL+C");
Consumer consumer = new DefaultConsumer(channel) {
#Override
public void handleDelivery(String consumerTag, Envelope envelope,
BasicProperties properties, byte[] body) throws IOException
{
// TODO Auto-generated method stub
String message = new String(body, "UTF-8");
System.out.println(" [x] Received '" + message + "'");
}
};
channel.basicConsume(QUEUE_NAME, true, consumer);
}
It never prints out the first sysout, because it gets stuck declaring the queue on "channel.queueDeclare" line.
Rabbit log says it is accepting AMQP connection and user guest gets authenticated and granted access to vhost.
Any help would be appreciated.
I just copied/pasted your code with no problems...
[*] Waiting for messages. To exit press CTRL+C
[x] Received 'foo'
I suggest you enable the management plugin and explore the admin UI.
Why did you add the spring-amqp spring-rabbitmq tags since this question has nothing to do with Spring and you are using the native client directly?

How can I know where does a message in rabbitMQ send from?

When we using rabbitMQ topic exchange, We can send a message at everywhere. And our project is very large, when I receive a message, and we found there is a problem in the message and we want to modify the message at where it was sent. But it is hardly be found where the message was sent.
Is there a method or a command tool in rabbitMQ to find out where that message sent from.
there are a few information that you can take using the envelop, as exchange, delivery_tag, routing_key :
Consumer consumer_a = new DefaultConsumer(channel) {
#Override
public void handleDelivery(String consumerTag, Envelope envelope, AMQP.BasicProperties properties, byte[] body)
throws IOException {
String message = new String(body, "UTF-8");
long delivery_tag = envelope.getDeliveryTag();
String exchange_from = envelope.getExchange();
String routing_key = envelope.getRoutingKey();
}
};
if you need more info you can use the headers to add custom information as:
var properties = new BasicProperties();
properties.Headers = new Dictionary<string, object>();
properties.Headers.Add("mysender_user", "my_server");
properties.Headers.Add("my_custom_info", "my_info");
channel.BasicPublish(ExchangeName, "", properties, message);

Rabbitmq - how to listen to messages on an exchange

I have a program in Java that sends messages to RabbitMQ. All I know is the exchange name. No queues, bindings, and so on.
My question is this: how can I see if the program sends these successfully, knowing only the exchange name?
Thanks.
Regards,
Serban
You can enable publisher confirmation with RabbitMQ. It's like having a send-transaction, where RabbitMQ will tell you whether or not the message was sent successfully.
Assume that we have RabbitMQ Exchange we need to create an queue to push the message to the exchange and consume it from the queue as following
private static final String EXCHANGE_NAME = "2022";
private static final String QUEUE_NAME = "2022";
private final static boolean durable = true;
// now we need to create a connection to rabbitmq server //
ConnectionFactory factory = new ConnectionFactory();
factory.setUsername("guest");
factory.setPassword("guest");
factory.setVirtualHost("/");
factory.setHost("127.0.0.1");
factory.setPort(5672);
Connection conn = factory.newConnection();
// create rabbitmq connection chaneel
Channel channel = conn.createChannel();
//Declare Exchange //
channel.exchangeDeclare(EXCHANGE_NAME, "topic", true);
// push message to rabbitmq exchange
channel.basicPublish(EXCHANGE_NAME, "routingkey", null, yourmessage.getBytes());
the above work as producer now we need to create queue consumer
private static final String EXCHANGE_NAME = "2022";
private static final String QUEUE_NAME = "2022";
private final static boolean durable = true;
// now we need to create a connection to rabbitmq server //
ConnectionFactory factory = new ConnectionFactory();
factory.setUsername("guest");
factory.setPassword("guest");
factory.setVirtualHost("/");
factory.setHost("127.0.0.1");
factory.setPort(5672);
Connection conn = factory.newConnection();
// create rabbitmq connection chaneel
Channel channel = conn.createChannel();
channel.exchangeDeclare(EXCHANGE_NAME, "topic", true);
//Queue Declare //
channel.queueDeclare(QUEUE_NAME, true, false, false, null);
//Queue bind //
channel.queueBind(QUEUE_NAME, EXCHANGE_NAME, "routingkey");
// Queue Consume //
QueueingConsumer consumer = new QueueingConsumer(channel);
while (true)
{
QueueingConsumer.Delivery delivery = consumer.nextDelivery();
String message = new String(delivery.getBody());
System.out.println(" [x] Received '" + message + "'");
}
Please look here: https://www.rabbitmq.com/tutorials/tutorial-three-java.html
String queueName = channel.queueDeclare().getQueue();
channel.queueBind(queueName, "EXCHANGE_NAME", "");
System.out.println(" [*] Waiting for messages. To exit press CTRL+C");
Consumer consumer = new DefaultConsumer(channel) {
#Override
public void handleDelivery(String consumerTag,
Envelope envelope,
AMQP.BasicProperties properties,
byte[] body) throws IOException
{
String message = new String(body, "UTF-8");
System.out.println(" [x] Received '" + message + "'");
}
};
channel.basicConsume(queueName, true, consumer);
In a few words, you have to:
create a queue, in this case anonymous queue
bind the queue to your exchange
It is important to know what kind of the exchange you have since the binding can change, between fanout or topic or direct
In this example is fanout

Timeout of basicPublish when server is outofspace

My case is rabbitmq server got out of space, just as below
Filesystem 1K-blocks Used Available Use% Mounted on
/dev/mapper/ramonubuntu--vg-root 6299376 5956336 0 100% /
The producer publishes message to server(the message needs to be persisted), and then will be blocked forever, it will keeping waiting the response of publishing. Sure we should avoid the situation of server out of space, but is there any timeout mechanism to let producer quit the waiting?
I have tried heartbeat and SO_TIMEOUT, they both don't work, as the network works fine. Below is my producer.
protected void publish(byte[] message) throws Exception {
// ConnectionFactory can be reused between threads.
ConnectionFactory factory = new SoTimeoutConnectionFactory();
factory.setHost(this.getHost());
factory.setVirtualHost("te");
factory.setPort(5672);
factory.setUsername("amqp");
factory.setPassword("amqp");
factory.setConnectionTimeout(10 * 1000);
// doesn't help if server got out of space
factory.setRequestedHeartbeat(1);
final Connection connection = factory.newConnection();
Channel channel = connection.createChannel();
// declare a 'topic' type of exchange
channel.exchangeDeclare(this.exchangeName, "topic", true);
channel.addReturnListener(new ReturnListener() {
#Override
public void handleReturn(int replyCode, String replyText, String exchange, String routingKey,
AMQP.BasicProperties properties, byte[] body) throws IOException {
logger.warn("[X]Returned message(replyCode:" + replyCode + ",replyText:" + replyText
+ ",exchange:" + exchange + ",routingKey:" + routingKey + ",body:" + new String(body));
}
});
channel.confirmSelect();
channel.addConfirmListener(new ConfirmListener() {
#Override
public void handleAck(long deliveryTag, boolean multiple) throws IOException {
logger.info("Ack: " + deliveryTag);
// RabbitMessagePublishMain.this.release(connection);
}
#Override
public void handleNack(long deliveryTag, boolean multiple) throws IOException {
logger.info("Nack: " + deliveryTag);
// RabbitMessagePublishMain.this.release(connection);
}
});
channel.basicPublish(this.exchangeName, RabbitMessageConsumerMain.EXCHANGE_NAME + ".-1", true,
MessageProperties.PERSISTENT_BASIC, message);
channel.waitForConfirmsOrDie(10*1000);
// now we can close connection
connection.close();
}
It will block at 'channel.waitForConfirmsOrDie(10*1000);', and the SotimeoutConnectionFactory,
public class SoTimeoutConnectionFactory extends ConnectionFactory {
#Override
protected void configureSocket(Socket socket) throws IOException {
super.configureSocket(socket);
socket.setSoTimeout(10 * 1000);
}
}
Also I captured the network between producer and rabbimq,
Please help.
You need to implement Connection Block/Unblocked.
This is basically a way of notifying the publisher that the server is running out of resources. The advantage with this is that the publisher will also be notified once it is safe to publish again.
I would recommend that you take a look at this article. A simple way of implementing this is to have a flag that indicates if it is safe to publish, if it is not wait until it is.
As an example you can take a look on how I implemented this in one of my Python examples.

Sending a broadcast notification with Google Cloud Messaging

I am using Google Cloud Messaging to provide push notifications. I may need to send a broadcast notification to around 10.000 users. However, I read that a Multicast message can contain a list with 1000 registration ids, maximun.
So, do I need to send ten multicast messages? Is there any way to send a broadcast to all the clients without generating the lists with all the ids?
thanks in advace.
Since Play Services 7.5, it's now also possible to achieve this through topics:
https://developers.google.com/cloud-messaging/topic-messaging
After registering, you would have to send the GCM server a message over HTTP:
https://gcm-http.googleapis.com/gcm/send
Content-Type:application/json
Authorization:key=AIzaSyZ-1u...0GBYzPu7Udno5aA
{
"to": "/topics/foo-bar",
"data": {
"message": "This is a GCM Topic Message!",
}
}
E.g.:
JSONObject jGcmData = new JSONObject();
JSONObject jData = new JSONObject();
jData.put("message", "This is a GCM Topic Message!");
// Where to send GCM message.
jGcmData.put("to", "/topics/foo-bar");
// What to send in GCM message.
jGcmData.put("data", jData);
// Create connection to send GCM Message request.
URL url = new URL("https://android.googleapis.com/gcm/send");
HttpURLConnection conn = (HttpURLConnection) url.openConnection();
conn.setRequestProperty("Authorization", "key=" + API_KEY);
conn.setRequestProperty("Content-Type", "application/json");
conn.setRequestMethod("POST");
conn.setDoOutput(true);
// Send GCM message content.
OutputStream outputStream = conn.getOutputStream();
outputStream.write(jGcmData.toString().getBytes());
And your clients should subscribe to /topics/foo-bar :
public void subscribe() {
GcmPubSub pubSub = GcmPubSub.getInstance(this);
pubSub.subscribe(token, "/topics/foo-bar", null);
}
#Override
public void onMessageReceived(String from, Bundle data) {
String message = data.getString("message");
Log.d(TAG, "From: " + from);
Log.d(TAG, "Message: " + message);
// Handle received message here.
}
You have no choice but splitting your broadcast in chunks of maximum 1000 regIds.
You can then send your multicast messages in separate threads.
//regIdList max size is 1000
MulticastResult multicastResult;
try {
multicastResult = sender.send(message, regIdList, retryTimes);
} catch (IOException e) {
logger.error("Error posting messages", e);
return;
}