[rabbitmq-discuss] Using Subscriptions in different ways (was Re: Multiple consumers)

Tony Garnock-Jones tonyg at lshift.net
Tue Jul 28 12:19:32 BST 2009


Hi Adriana,

Adriana Rodean wrote:
> When i publish message 1 subscriber receives the message. After i
> close this subscriber the other one receives the message.
> I want both subscribers to receive the message when they are open.
> What am i doing wrong?
> Please help!

Here is a schematic of what the code you posted sets up:

    exchange "{27}{47}{System}"
      |
      |
      V
    queue "{27}{47}{System}"
      |
      +-----+
      |     |
      V     V
      s1    s2

In AMQP, queues perform *round-robin* distribution of messages to 
consumers (a.k.a subscribers), meaning that only *one* subscriber to a 
queue will get each message. (See also Matthew's explanation of 
acknowledgements.) AMQP's *exchanges*, on the other hand, perform 
message *broadcasting*, copying messages onto all (matching) bound queues.

So to get your example of a single publication arriving at two different 
subscribers/consumers simultaneously, you would want something like the 
following:

    exchange "{27}{47}{System}"
      |
      +----------------------+
      |                      |
      V                      V
    queue 1                queue 2
      |                      |
      |                      |
      V                      V
      s1                     s2

Each subscriber should declare an auto-delete, private, uniquely-named 
queue for themselves. Here's how to do that with the .NET client:

   Subscription sub = new Subscription(channel,
                                       "{27}{47}{System}",
                                       ExchangeType.Topic,
                                       "System");
   foreach (BasicDeliverEventArgs e in sub) {
     Console.WriteLine(Encoding.UTF8.GetString(e.Body));
   }

Notice how a queue name is not mentioned: the Subscription calls 
channel.QueueDeclare() for you and uses the resulting private, 
uniquely-named, autodelete queue to bind and consume from.

Matthew wrote about acknowledgements: it's important to call sub.Ack(e) 
after your program successfully processes each message, otherwise the 
server will attempt to redeliver the messages later on, because it isn't 
being told that it's safe to remove them from its queues.

(As an aside, the Subscription generally takes care of declaring 
exchange and queue resources for you -- you don't generally need to call 
ExchangeDeclare, QueueDeclare, QueueBind if you're using Subscription.)

Regards,
   Tony





More information about the rabbitmq-discuss mailing list