[rabbitmq-discuss] immediate, mandatory flag with no consumers

Alan Antonuk alan.antonuk at gmail.com
Mon May 7 17:18:10 BST 2012


Monish;

As a short answer: there the rabbitmq-c does not provide an easy-to-use
interface to deal with basic.return messages from the broker.

The long answer: it is possible, with a bit of work:

The easy part: reading a basic.return message from the broker, its almost
the same as a basic.deliver of a message:
- Read the method (1 frame), only instead of a basic.deliver, you get a
basic.return method
- Read the message header (1 frame)
- Read message body (1+ frames)

Example code:
https://github.com/alanxz/rabbitmq-c/blob/master/examples/amqp_consumer.c#L75
Note that line 83 will need to compare against AMQP_BASIC_RETURN_METHOD
instead of AMQP_BASIC_DELIVER_METHOD

That's the easy part, the hard part requires a bit more explanation:

As you can already tell the rabbitmq-c client works a bit differently from
the Java and C# clients in that it doesn't have its own internal event loop
that deals the the asynchronous bits of AMQP, so using the library forces
you to think about how you're going to handle these asynchronous messages
from the broker.

The first thing to note is that basic.publish method is an asynchronous[1]
AMQP method: a client sends a basic.publish on a channel, and does wait for
the broker to respond before continuing.  In fact: if all you're doing is
publishing messages to the broker, the broker won't send anything to the
client unless something goes wrong (this is part of what makes AMQP a
high-performance messaging protocol).  Whats more: since the basic.publish
is asynchronous, if something goes wrong on the broker, you won't know
immediately after publishing (e.g., calling the rabbitmq-c
amqp_basic_publish(...) function ). The failure is transmitted as an AMQP
method 'at some point in the future' meaning, likely you'll get an error
pretty quickly, but you have to be able to deal with the case that it might
happen a bit later.

Since rabbitmq-c doesn't have its own thread sitting there dealing with
error messages, and the amqp_basic_publish(...) doesn't do any sort of read
on the socket from the broker (the return value only indicates an error if
there was a failure writing the message to the socket to the broker), you
have to check periodically for methods from the broker.

You do this by using amqp_simple_wait_frame().  However this can block on a
read() on the socket if the broker hasn't sent anything.  The way to get
around this is to use amqp_get_sockfd() on the connection object, then use
something like select(), amqp_frames_enqueued(), and amqp_data_in_buffer()
to detect there is potentially a frame to be read from the broker.

An example of a library that does this is SimpleAmqpClient:
https://github.com/alanxz/SimpleAmqpClient/blob/master/src/Channel.cpp#L283 .
It uses publisher-confirms to make the basic.publish method a synchronous
process.  If you sift through the ChannelImpl::GetMethodOnChannel()
implementation, you can see what needs to be done to poll the socket for
frames.

[1] The AMQP basic.publish method can be made synchronous by enabling
publisher-confirms. However, this does come at a performance cost: there is
a full network round-trip for each basic.publish.

HTH
-Alan

As a personal plug the SimpleAmqpClient library can be found:
https://github.com/alanxz/SimpleAmqpClient. It wraps the rabbitmq-c library
in a (hopefully) easy-to-use synchronous c++ interface.  Since it uses
publisher-confirms and waits for a confirmation before allowing another
message to be sent, it won't have the best message publish through-put (I
can get 3-4k-msg/s, whereas using unconfirmed messages I've seen as high as
20-25k-msg/s over a single connection).

On Fri, May 4, 2012 at 3:43 PM, Unni, Monish <munni at etrade.com> wrote:

> Thanks for your replies Emile!
>
> the only thing close to the c-client for basic.return i found this :
> https://groups.google.com/forum/#!msg/rabbitmq-discuss/fHL9tQHj4s0/FxCQxx4khKQJ
> not sure if it does the same thing as java-api.
>
> or if you could link me to github for this functionality.
>
> kind regards,
> -monish
>
> On May 4, 2012, at 2:33 AM, Emile Joubert wrote:
>
> > Hi,
> >
> > On 04/05/12 05:19, Unni, Monish wrote:
> >> * is it okay to pair request-reply channels and use the same
> >> connection to provide "maximum" concurrency?
> >
> > It is okay to send and receive messages on the same connection. Bear in
> > mind that if the broker decides to block the connection then all
> > channels in that connection will be affected. I'm not sure you will
> > achieve higher concurrency this way.
> >
> >> * how can we get this feature working for "C" clients ( C- api ) ?
> >
> > Have you taken a look at the C client examples?
> >
> >> * and last : is my understanding right ( from observation ) that the
> >> request channel and reply-channels have to share the same connection
> >> for this feature to work?
> >
> > In general requests and their corresponding replies do not have to share
> > a connection, but for basic.return to work the return handler must share
> > a channel with the publisher.
> >
> > -Emile
> >
>
> _______________________________________________
> rabbitmq-discuss mailing list
> rabbitmq-discuss at lists.rabbitmq.com
> https://lists.rabbitmq.com/cgi-bin/mailman/listinfo/rabbitmq-discuss
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.rabbitmq.com/pipermail/rabbitmq-discuss/attachments/20120507/5e189b69/attachment.htm>


More information about the rabbitmq-discuss mailing list