Are there any flaws in using channel.Get () over a channel. Consume ()?

I am using the streadway amqp library to connect to the rabbitmq server. The library provides a channel.Consume () function that returns " <- chan Delivery ". It also provides a channel.Get () function that returns " Delivery " by the way.

I have to implement pop () functionality, and I use channel.Get () . However, the documentation says:

"In almost all cases, using Channel.Consume will be preferred." 

Are the preferred recommendations recommended here? Are there any flaws in using channel.Get () over a channel. Consume ()? If so, how to use channel.Consume () to implement the Pop () function?

+6
source share
2 answers

As far as I can tell from the docs, yes, "preferred" means "recommended."

It seems that channel.Get() does not provide as many functions as channel.Consume() , and is also more easily used in parallel code due to the fact that it returns chan of Delivery , unlike each individual Delivery separately.

Additional functions: exclusive , noLocal and noWait , as well as the optional Table arguments "which have certain semantics for the queue or server."

To implement the Pop() function using channel.Consume() , you could link some code snippets to the amqp example example , create using the Consume() function, create a function for processing the chan Delivery that actually implements your Pop() functionality Pop() and then disables the handle() function in goroutine .

The key to this is that the channel (in a related example) will be blocked during sending if it does not receive anything. In this example, the handle() function func uses range to process the entire channel until it is empty. The Pop() function can be better served by a function that just gets the last value from chan and returns it. Each time it starts, it returns the last Delivery .

EDIT: example, to get the last value from the channel and do things with it (this may not work for your use case, it may be more useful if the function sent Delivery to another chan to another function that needs to be processed. In addition, I do not tested the code below, it may be filled with errors)

 func handle(deliveries <-chan amqp.Delivery, done chan error) { select { case d = <-deliveries: // Do stuff with the delivery // Send any errors down the done chan. for example: // done <- err default: done <- nil } } 
+5
source

It really depends on what you are trying to do. If you want to receive only one message from the queue (first), you should probably use basic.get if you plan to process all incoming messages from the queue - basic.consume is what you want.

This is probably not a platform or library issue, but a protocol understanding issue.

UPD

I am not familiar with this, I am fluent in the language, so I will try to give you a brief description of AMQP and describe the use cases.

You may have problems and sometimes problems with basic.consume :

With basic.consume , you have a workflow like this:

  • Send the basic.consume method to notify the broker that you want to receive messages
    • while this is a synchronous method, wait for the basic.consume-ok message from the broker
  • Start listening to basic.deliver message from the server
    • This is an asynchronous method, and you should take care of situations where there are no messages on the server, for example. reading time limit

With basic.get , you have a workflow like this:

  • send synchronous basic.get method basic.get broker
    • Wait for the basic.get-ok method, which contains messages or basic.empty methods that indicate that there are no messages on the server

Note about synchronous and asynchronous methods: it is expected that the synchronous response will have some kind of answer: asynchronous not

Note in the basic.qos method the prefetch-count property: it is ignored when the no-ack property is set to basic.consume or basic.get .

Spec has a note on basic.get : "this method provides direct access to messages in a queue using a synchronous dialog that is designed for certain types of applications where synchronous functionality is more important than performance", which is used for continuous messages.

My personal tests show that receiving messages in line 1000 using basic.get (0.38659715652466) is faster than receiving 1000 messages from basic.consume one at a time (0.47398710250854) on RabbitMQ 3.0.1, Erlang R14B04 is on average more than 15% .

If you consume only one message in the main thread, this is your case - perhaps you need to use basic.get .

You can still use only one message asynchronously, for example, in a separate thread or use some kind of event mechanism. Sometimes it would be better for you to decide the resource of the machine, but you need to take care of the situation when there are no messages in the queue.

If you need to process the message one by one, it is obvious that basic.consume should be used, I think

+3
source

Source: https://habr.com/ru/post/947528/


All Articles