How synchronous is basic.get?

60 views
Skip to first unread message

Emiel Bruijntjes

unread,
Aug 1, 2014, 3:57:29 AM8/1/14
to rabbitm...@googlegroups.com
Hi,

We do not yet have support for the "basic.get" function in the AMQP-CPP library, so we're adding that just now. But while implementing it, I have some questions.

As far as I understand, "basic.get" is a synchronous call, which means that our client MUST wait for an answer, before it can send a next frame over the same channel to the RabbitMQ server. It is thus not permitted to send multiple instructions right after the basic.get frame, if no answer has yet been received (am I right on this?)

The answer to the "basic.get" frame is either a "basic.get-ok" or "basic.get-empty" frame. Is it allowed to send the next instruction to RabbitMQ immediately after we've received either of these two frames (and even before the entire body has been received), or should we (in case of a "basic.get-ok" frame) also wait for all the "body" frames to be received before we can proceed with sending further frames?

Thanx,

Emiel Bruijntjes

Michael Klishin

unread,
Aug 1, 2014, 4:21:09 AM8/1/14
to rabbitm...@googlegroups.com, Emiel Bruijntjes
 On 1 August 2014 at 11:57:34, Emiel Bruijntjes (emiel.br...@gmail.com) wrote:
> > As far as I understand, "basic.get" is a synchronous call, which
> means that our client MUST wait for an answer, before it can send
> a next frame over the same channel to the RabbitMQ server. It is
> thus not permitted to send multiple instructions right after
> the basic.get frame, if no answer has yet been received (am I right
> on this?)
>
> The answer to the "basic.get" frame is either a "basic.get-ok"
> or "basic.get-empty" frame. Is it allowed to send the next instruction
> to RabbitMQ immediately after we've received either of these
> two frames (and even before the entire body has been received),
> or should we (in case of a "basic.get-ok" frame) also wait for
> all the "body" frames to be received before we can proceed with
> sending further frames?

Sections 2.2.2, 3.2.1, and 4.7 in [1] leave interpretation largely up to the reader ;)

My understanding of this (and how Java, .NET, Ruby clients work):
after sending basic.get, the client enter a "continuation" and may receive either an async method (e.g. basic.deliver, channel.close,
or, in case of RabbitMQ, basic.[n]ack if publisher confirms are enabled). Those are
dispatched as usual. Response methods (basic.get-ok, basic.get-empty) release the continuation,
as does TCP connection failure or channel error. Such client API won't let you issue e.g. a
queue.declare right after basic.get w/o receiving a response (unless you share a channel between
threads, which is problematic in many ways). This is also how it works for all
synchronous methods, e.g. queue.declare.

basic.get-ok carries a body, so content header
and 0 or more body frames will always follow it and must be considered a part of the method.

As the spec mentions, methods used in performance sensitive
cases (e.g. publishing) are usually asynchronous, and our experience with multiple clients
suggest that in practice this blocking continuations approach works well.

I hope this answers your question.

1. http://www.rabbitmq.com/resources/specs/amqp0-9-1.pdf
--
MK

Staff Software Engineer, Pivotal/RabbitMQ

Emiel Bruijntjes

unread,
Aug 1, 2014, 4:49:40 AM8/1/14
to rabbitm...@googlegroups.com, emiel.br...@gmail.com
Hi Michael,

Thanx for your quick response. That is well appreciated.

Just to be sure: is my conclusion correct that receiving the basic.get-ok frame should _not_ release the continuation state - but that we have to wait for the full body?

basic.get-empty: release continuation
basic.get-ok: keep continuation
basic.header: release continuation if and only if body size == 0 AND this is a header that comes with a basic.get call (not a basic.consume)
body: release continuation if and only if this was the last body frame AND this is a body that comes with a basic.get call (not a basic.consume)

In our initial implementation we released the continuation state when the first basic.get-ok frame was released, without waiting for the body, and that seemed to work well. Was this just a matter of luck because of our small test environment that could break in production on heavier loads?

Emiel

Michael Klishin

unread,
Aug 1, 2014, 4:59:22 AM8/1/14
to rabbitm...@googlegroups.com, Emiel Bruijntjes
 On 1 August 2014 at 12:49:45, Emiel Bruijntjes (emiel.br...@gmail.com) wrote:
> > Just to be sure: is my conclusion correct that receiving the
> basic.get-ok frame should _not_ release the continuation state
> - but that we have to wait for the full body?

You must read content header and body frames before you can consider basic.get
fully parsed. That's how all clients do it for methods that carry content
(basic.get-ok, basic.deliver, basic.return).

> In our initial implementation we released the continuation
> state when the first basic.get-ok frame was released, without
> waiting for the body, and that seemed to work well. Was this just
> a matter of luck because of our small test environment that could
> break in production on heavier loads?

Yes, try publishing messages of 200-300 MBs in size, that will get a lot of body frames.
Reply all
Reply to author
Forward
0 new messages