【整理】RabbitMQ publish方法中的immediate和mandatory属性

      鉴于在 RabbitMQ 的使用过程中,很多同学搞不清楚 basic.publish 接口中 mandatory 和 immediate 的背后含义,特搜集整理网上相关文章,以便彻底理解该问题。

===== 我是三体分隔线 ===== 

在 RabbitMQ 3.0.0 版本的 README 中如是说: 

?


1

2

3

4

...

feature removal

23896 remove support for AMQP's "immediate" publish mode

...

另外一篇 文章 中也对该变更进行了说明 

?


1

2

3

4

5

6

7

8

9

10

11

12

Removal of "immediate" flag

What changed? We removed support for the rarely-used "immediate" flag on AMQP's basic.publish.

 

Why on earth did you do that? Support for "immediate" made many parts of the codebase more complex,

particularly around mirrored queues. It also stood in the way of our being able to deliver

substantial performance improvements in mirrored queues.

 

What do I need to do? If you just want to be able to publish messages that will be dropped if they

are not consumed immediately, you can publish to a queue with a TTL of 0.

 

If you also need your publisher to be able to determine that this has happened, you can also use the

DLX feature to route such messages to another queue, from which the publisher can consume them.

RabbitMQ 官网上针对 AMQP-0-9-1 协议中 basic.publish 方法的说明。 

?


1

2

3

4

5

6

7

8

9

10

11

12

13

14

...publish(short reserved-1, exchange-name exchange, shortstr routing-key, bit mandatory, bit immediate)

...

bit mandatory

This flag tells the server how to react if the message cannot be routed to a queue. If this flag is set,

the server will return an unroutable message with a Return method. If this flag is zero, the server

silently drops the message.

The server SHOULD implement the mandatory flag.

 

bit immediate

This flag tells the server how to react if the message cannot be routed to a queue consumer immediately.

If this flag is set, the server will return an undeliverable message with a Return method. If this flag

is zero, the server will queue the message, but with no guarantee that it will ever be consumed.

The server SHOULD implement the immediate flag.

...

下面是网上找到的 关于 mandatory 和 immediate 两个属性的讨论 。 

AMQP's basic.publish method has two flags - mandatory and immediate - that trigger checks at the server and result in messages getting returned to clients with basic.return when the necessary conditions aren't met. See http://www.rabbitmq.com/amqp-0-9-1-reference.html#basic.publish for the details. I can just about see why 'mandatory' may be useful, but 'immediate' has always struck me as a bizarre and I fear that anybody using it may well do so w/o fully understanding the semantics - can't blame them, it *is* bizarre. Because of that, and since it complicates the code in many places, we are considering dropping support for 'immediate'. So is anybody actually using the 'immediate' flag?

I'd support this move. Have never used "immediate".

Just curious, are there any benefits for removing it -- is it preventing / complicating support for other features?

Yes. It accounts for a fair bit logic scattered across the code base and we've just found another case where in order to significantly improve performance of mirrored queues we'd have to make yet more code aware of the 'immediate' flag.

Well, the specific thing that we've bumped into in this case is that support for immediate is greatly slowing down HA queues. We could be smarter about this, at the cost of tangling the code further. So if we want to make HA queues faster (and we do!) we can either keep immediate and add a bunch of code at the same time, or remove immediate and delete a bunch of code. There are quite a number of places where we have notably greater complexity just to support this weird feature that (we suspect) no-one uses. It just feels very disproportionate.

Matthias / Simon, thanks for the background. I'm not using the immediate flag, but I've considered using it.  Admittedly, I'm not fully aware of exactly how it works. It would be helpful to have a better understanding of the semantics. Can you explain what the publisher is notified of (if anything?) when there are 10 queues bound to an exchange named HighPriority, a message with immediate flag true is published to HighPriority, and 7 out of the 10 queues have the message consumed immediately.

No notification is sent to the publisher in that case. A basic.return is only sent if *no* queues were able to send the message to a consumer immediately.

Here are a few more warts about 'immediate':

- while a message might get sent out to a consumer straight away, there is of course no guarantee that such a message will reach the consumer, get processed and ack'ed. If any of these steps go wrong the message will end up in the queue (unless the consuming happened with no-ack, in which case it is simply lost), even though supposedly it was delivered immediately.

- a queue can have a consumer and yet 'immediate' delivery may fail (and a basic.return issued) because: a) the consumer isn't quick enough and a backlog of messages has built up, b) the consumer has configured a 'basic.qos' prefetch count and that the limit has been reached

- the interaction with transactions is not at all obvious. This does apply to 'mandatory' too though. See http://www.rabbitmq.com/semantics.html#tx

Matthias, thanks for the explanation. Considering your points below, I now have a better understanding on your thought that the actual use-cases and practicality to publish messages with the immediate flag are minimal. In light of the details, I won't be using it -- faster mirrored queues sounds better to me. :o)

Couldn't it be possible emulate immediate by delivering to a TTL'ed queue, then having a dead-letter queue that the publisher consumes from to be notified that a message has not been consumed?

Yes. It's not an exact emulation, but arguably more flexible, e.g. it gives greater control over how the 'returned' messages are dealt with.

Plus 1 for faster HA queues and less complexity in the code base.

下面是  stackoverflow 上关于上述两个属性的讨论。 

?


1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

The immediate and mandatory fields are part of the AMQP specification, and are also covered in the

RabbitMQ FAQ to clarify how its implementers interpreted their meaning:

 

Mandatory

This flag tells the server how to react if a message cannot be routed to a queue. Specifically, if

mandatory is set and after running the bindings the message was placed on zero queues then the message

is returned to the sender (with a basic.return). If mandatory had not been set under the same

circumstances the server would silently drop the message.

 

Or in my words, "Put this message on at least one queue. If you can't, send it back to me."

 

Immediate

For a message published with immediate set, if a matching queue has ready consumers then one of them

will have the message routed to it. If the lucky consumer crashes before ack'ing receipt the message

will be requeued and/or delivered to other consumers on that queue (if there's no crash the messaged

is ack'ed and it's all done as per normal). If, however, a matching queue has zero ready consumers the

message will not be enqueued for subsequent redelivery on from that queue. Only if all of the matching

queues have no ready consumers that the message is returned to the sender (via basic.return).

 

Or in my words, "If there is at least one consumer connected to my queue that can take delivery of a

message right this moment, deliver this message to them immediately. If there are no consumers connected

then there's no point in having my message consumed later and they'll never see it. They snooze, they lose."

最后给出两篇中文说明,可以帮助理解: 

RabbitMQ(二)AMQP协议mandatory和immediate标志位区别 
RabbitMQ(四)RabbitMQ死信邮箱(DLX) 

时间: 2024-09-09 01:59:52

【整理】RabbitMQ publish方法中的immediate和mandatory属性的相关文章

java-[Java]关于重载方法中的可变参数列表

问题描述 [Java]关于重载方法中的可变参数列表 <Thinking in Java>第105页有一句话不理解 如何理解你应该总是只在重载方法的一个版本上使用可变参数列表,或者压根就不是用它 解决方案 就是当重载一个方法时,选择其中的一个重载使用可变参数,其他的避免使用,否则编译的时候容易出问题.具体的参看http://www.cnblogs.com/lanxuezaipiao/p/3190673.html 解决方案二: 这个道理很简单,比如说你有foo(int x int ... args

为何不能在viewDidLoad方法中显示其他视图

大熊猫猪·侯佩原创或翻译作品.欢迎转载,转载请注明出处. 如果觉得写的不好请多提意见,如果觉得不错请多多支持点赞.谢谢! hopy ;) 你可以使得当视图控制器(view controller)显示自身的时候显示分享选项控制器.你视图控制器的viewDidAppear方法将在它显示在屏幕上的时候被调用,并且在你App中的所有继承体系中的视图都是如此.这意味着你可以用这个机会在你的视图控制器视图上面显示其他视图. 不要试图在你的视图控制器的viewDidLoad方法中显示活动视图控制器(activ

泛型T 如何在扩展方法中使用?

问题描述 泛型T 如何在扩展方法中使用? 本来想了解一下扩展方法,但是看到文库中的实例明显有问题,特来提问 泛型对象T 如何使用Length 属性? 可以像类中一样加继承于某某类的约束吗? http://wenku.baidu.com/link?url=Vz-Cjrq24tvblbk0l1I4IPYYfZ82jkGpzGBoNBDhi6qSCJko9hSTcrKGWrunO91TqTgyqB0AMvueHUP1or-mi8ktWMejceDW6Y-OphMnBh7 public static c

关于在同控制器中方法中调用没有权限的方法的提问

问题描述 关于在同控制器中方法中调用没有权限的方法的提问 Index 控制器中,我写了一个有权限的A方法,然后我又写了一个我没有权限B方法,当我在A方法中用 $this->B(); 时,居然在A方法中能够接收到 B中 return 出来的值 跪求解答 解决方案 YII 如何在控制器里调用 model 方法YII 如何在控制器里调用 model 方法

android-如何从其它的方法中删除对话框?

问题描述 如何从其它的方法中删除对话框? 我创建一个对话框,按照下面的代码,提供一个标题和消息,这个对话框可以在任何地方被调用. public void alertbox(String title, String mymessage) { new AlertDialog.Builder(this) .setTitle(title) .setMessage(mymessage) .setNeutralButton(android.R.string.cancel, new DialogInterfa

C#方法中的参数

C#中方法的参数有四种类型: ●值参数,不含任何修饰符. ●引用型参数,以ref修饰符声明. ●输出参数,以out修饰符声明. ●数组型参数,以params修饰符声明. 11.2.1 值参数 当利用值向方法传递参数时,编译程序给实参的值做一份拷贝,并且将此拷贝传递给该方法.被调用的方法不传经修改内存中实参的值,所以使用值参数时,可以保证实际值是安全的.在调用方法时,如果形式化参数的类型是值参数的话,调用的实参的值必须保证是正确的值表达式.在下面的例子中,程序员并没有实现他希望交换值的目的: 程序

c#方法中调用参数的值传递方式和引用传递方式以及ref与out的区别深入解析

以下是对c#方法中调用参数的值传递方式和引用传递方式,以及ref与out的区进行了详细的分析介绍,需要的朋友可以过来参考下   复制代码 代码如下: #define Test using System; namespace Wrox.ProCSharp.ParameterTestSample ...{  class ParemeterTest  ...{     static void TestInt(int[] ints,int i)     ...{         ints[0] = 10

在JS方法中返回多个值的方法汇总

  本文给大家汇总了在javascript方法中返回多个值的方法,都是在个人项目中检验过的,这里推荐给大家,有需要的小伙伴可以参考下. 在使用JS编程中,有时需要在一个方法返回两个个或两个以上的数据,用下面的几种方法都可以实现: 1 使用数组的方式,如下: ? 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 <html> <head> <title>JS函数返回多个值</title> <

浅析jquery ajax异步调用方法中不能给全局变量赋值的原因及解决方法

 本篇文章主要是对jquery ajax异步调用方法中不能给全局变量赋值的原因及解决方法进行了详细的分析介绍,需要的朋友可以过来参考下,希望对大家有所帮助 在调用一个jquery的ajax方法时我们有时会需要该方法返回一个值或者给某个全局变量赋值,可是我们发现程序执行完后并没有获取到我们想要的值,这时很有可能是因为你用的是ajax的异步调用async:true(默认情况),如:    代码如下: function ManageCommentText(text) { var result = te