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

Unni, Monish munni at etrade.com
Tue May 8 02:33:21 BST 2012

this is super cool, Alan! thanks for the great pointers!

we also found for rabbitmq, we could use "alternate-exchange" (extension), since, we are mostly calling services that are built in-house.
this seems to be a very generic way to handle "non-routable" calls.
the restriction seems to be this  exchange cannot be built on "amq.direct" as an "alternate-exchange" needs to be specified at the time of creation - is this right?

for "no-consumers" i am not sure if we have any "broker" level setting except using "dead-letter-messages" as given : http://www.rabbitmq.com/extensions.html#dead-letter-messages
[also, we are loosely-coupled, i.e we really don't want "transaction-level" broker semantics, so "confirmation" is not an option...]

am i right? are there any other settings we can make use of?


On May 7, 2012, at 9:18 AM, Alan Antonuk wrote:


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.


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<mailto: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,

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<mailto:rabbitmq-discuss at lists.rabbitmq.com>

More information about the rabbitmq-discuss mailing list