two sources of information:
Useful operations for understanding:
- Announce / Approve / Listen / Sign / Publish
Re: your question is there is no reason why you cannot have multiple listeners. Or you can subscribe to n routing routes with one listener per โexchangeโ.
** re: non-blocking **
A typical listener consumes messages one at a time. You can remove them from the queue, or they will automatically be placed next to the consumer in the "window" mode (determined using the qos quality of service parameters). The beauty of the approach is that a lot of hard work is being done for you (re: reliability, guaranteed delivery, etc.).
A key feature of RabbitMQ is that when an error occurs in processing, the message is again added to the queue (fault tolerance function).
You need to know more about your situation.
Often, if you publish the list mentioned above, you can get one of RabbitMQ employees. They are very helpful.
Hope this helps. It is very important to plunge into the head first, but it is worth continuing.
Q & A
see http://www.rabbitmq.com/faq.html
Q. Can you subscribe to multiple queues using the new subscription (channel, queueName)?
Yes. You use a binding key, for example. abc. *. hij or abc. #. hij, or you attach some bindings. The first assumes that you have developed routing keys around a principle that makes sense to you (see Routing Keys in the FAQ). For the latter, you need to bind to multiple queues.
Implementing n-bindings manually. see http://hg.rabbitmq.com/rabbitmq-dotnet-client/file/default/projects/client/RabbitMQ.Client/src/client/messagepatterns/Subscription.cs
there is not much code for this template, so you can collapse your own subscription template if there are not enough wildcards. you can inherit this class and add another method for additional bindings ... maybe this will work or something close to this (unchecked).
The AQMP specification says that multiple manual binding is possible: http://www.rabbitmq.com/amqp-0-9-1-reference.html#queue.bind
Q. And if so, how can I go through all the signed queues and return a message (null when there are no messages)?
With a subscriber, you receive a notification when a message is available. Otherwise, what you are describing is the pull interface, where you pull the message on demand. If there are no messages, you will get zero as you wish. By the way: the Notify method is probably more convenient.
Q. Oh, and remember that I have all these operations in different methods. I will edit my post to reflect the code
Live Code:
this version should use wild cards to subscribe to multiple routing keys
n manual routing keys using a subscription remain as an exercise for the reader. ;-) I think you were inclined towards the push interface anyway. btw: pull interfaces are less efficient than notifications.
using (Subscription sub = new Subscription(ch, QueueNme)) { foreach (BasicDeliverEventArgs ev in sub) { Process(ev.Body); ...
Note: foreach uses IEnumerable, and IEnumerable wraps the event when a new message arrives through the yield statement. Effectively this is an infinite loop.
--- UPDATE
AMQP was designed with the fact that the number of TCP connections does not exceed the number of applications, so you can have many channels for each connection.
the code in this question (edit 3) is trying to use two subscribers with one channel, while it should (I believe) be one subscriber per channel in the stream to avoid blocking problems. Sugestion: Use a wildcard routing key. You can subscribe to several queue names with a java client, but the .net client, as far as I know, has not implemented this in the subscriber assistant class.
If you really need two different queue names in the same subscription stream, then for .net: {/ p>
using (IModel ch = conn.CreateModel()) { // btw: no reason to close the channel afterwards IMO conn.AutoClose = true; // no reason to closs the connection either. Here for completeness. ch.QueueDeclare(queueName); BasicGetResult result = ch.BasicGet(queueName, false); if (result == null) { Console.WriteLine("No message available."); } else { ch.BasicAck(result.DeliveryTag, false); Console.WriteLine("Message:"); } return 0; }
- UPDATE 2:
from the RabbitMQ list:
"suppose element.Next () blocks one of the signatures. You can receive deliveries from each subscription with a timeout before read it. Alternatively, you can configure one queue to receive all dimensions and receive messages from it with one subscription " (Emile)
This means that when the first queue is empty, .Next () blocks waiting for the next message to appear. that is, the subscriber has a built-in wait-for-next message.
- UPDATE 3:
in .net, use QueueingBasicConsumer to consume from multiple queues.
Actually there is a thread about this to get an idea of โโusage:
Wait for one RabbitMQ message with timeout
- UPDATE4:
Learn more about .QueueingBasicConsumer
Here is a sample code here.
http://www.rabbitmq.com/releases/rabbitmq-dotnet-client/v1.4.0/rabbitmq-dotnet-client-1.4.0-net-2.0-htmldoc/type-RabbitMQ.Client.QueueingBasicConsumer.html
The example is copied in response with several modifications (see // <-----).
IModel channel = ...; QueueingBasicConsumer consumer = new QueueingBasicConsumer(channel); channel.BasicConsume(queueName, false, null, consumer); //<----- channel.BasicConsume(queueName2, false, null, consumer); //<----- // etc. channel.BasicConsume(queueNameN, false, null, consumer); //<----- // At this point, messages will be being asynchronously delivered, // and will be queueing up in consumer.Queue. while (true) { try { BasicDeliverEventArgs e = (BasicDeliverEventArgs) consumer.Queue.Dequeue(); // ... handle the delivery ... channel.BasicAck(e.DeliveryTag, false); } catch (EndOfStreamException ex) { // The consumer was cancelled, the model closed, or the // connection went away. break; } }
- UPDATE 5: a simple get that will work in any queue (a slower, but sometimes more convenient method).
ch.QueueDeclare(queueName); BasicGetResult result = ch.BasicGet(queueName, false); if (result == null) { Console.WriteLine("No message available."); } else { ch.BasicAck(result.DeliveryTag, false); Console.WriteLine("Message:"); // deserialize body and display extra info here. }