文档章节

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

摩云飞
 摩云飞
发布于 2015/03/10 19:09
字数 1402
阅读 596
收藏 1


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

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

在 RabbitMQ 3.0.0 版本的 README 中如是说:
...
feature removal
23896 remove support for AMQP's "immediate" publish mode
...
另外一篇 文章 中也对该变更进行了说明
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 方法的说明
...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 上关于上述两个属性的讨论
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)


© 著作权归作者所有

摩云飞
粉丝 375
博文 534
码字总数 952694
作品 0
徐汇
程序员
私信 提问
【原创】RabbitMQ之PublisherConfirm实战问题总结

如何理解Publisher Confirm机制 Publisher Confirm机制(又称为Confirms或Publisher Acknowledgements)是作为解决事务机制性能开销大(导致吞吐量下降)而提出的另外一种保证消息不会丢失的...

摩云飞
2015/03/30
2.5K
12
【攻克RabbitMQ】常见问题

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/zlt995768025/article/details/81938449 消息什么情况下会丢失?配合mandatory参数或备份交换器来提高程序的健...

周丽同
2018/08/22
0
0
RabbitMQ-C客户端使用说明

rabbitmq-c是一个用于C语言的,与AMQP server进行交互的client库,AMQP协议为版本0-9-1。rabbitmq-c与server进行交互前需要首先进行login操作,在操作后,可以根据AMQP协议规范,执行一系列操...

龙鸟
2012/09/20
5.1K
0
[RabbitMQ]RabbitMQ深入理解(一)进阶/管理/配置

本文源于朱忠华的《RabbitMQ实战指南》 RabbitMQ简介 消息队列中间件有两种传递模式:点对点 和 发布/订阅 点对点依靠队列的原理;发布/订阅则可以用于一对多的广播 消息中间件的作用:解耦、...

morpheusWB
2018/10/16
589
0
三、RabbitMQ如何实现AMQ协议(读书笔记)

AMQP作为一种RPC传输机制 RabbitMQ作为一种AMPQ代理服务器,提供了一套严格的通信方式,核心部分的通信几乎都使用了RPC(远程过程调用)模式。 启动会话 AMQP协议定义,当客户端要与RabbitM...

XuePeng77
03/12
77
0

没有更多内容

加载失败,请刷新页面

加载更多

Google Guava 笔记

一、引言 Guava 是 google 几个java核心类库的集合,包括集合 [collections] 、缓存 [caching] 、原生类型支持 [primitives support] 、并发库 [concurrency libraries] 、通用注解 [common ...

SuShine
28分钟前
7
0
SpringBoot中使用@Value为静态变量赋值并测试是否成功

今天想像普通变量一样如下采用写法取配置的,但取到的是个null。。。 @Value("${test.appKey}")private static String appKey; 才发现不能通过这种方式取配置来给static变量赋值 在网上搜索...

SilentSong
28分钟前
5
0
ECMAScript语句之with 语句

ECMAScript with 语句,用于设置代码在特定对象中的作用域(with运行缓慢,设置了属性值时更加缓慢,最好避免使用with语句) 一、with 语句用于字符串(配合toUpperCase()方法) var a = "C...

专注的阿熊
29分钟前
4
0
Apache Flink 进阶(一):Runtime 核心机制剖析

1. 综述 本文主要介绍 Flink Runtime 的作业执行的核心机制。首先介绍 Flink Runtime 的整体架构以及 Job 的基本执行流程,然后介绍在这个过程,Flink 是怎么进行资源管理、作业调度以及错误...

大涛学长
36分钟前
4
0
7. 整数反转

给出一个 32 位的有符号整数,你需要将这个整数中每位上的数字进行反转。 示例 1: 输入: 123 输出: 321 示例 2: 输入: -123 输出: -321 示例 3: 输入: 120 输出: 21 注意: 假设我们的环境只能...

苏坡吴
36分钟前
5
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部