RabbitMQ(二)AMQP协议mandatory和immediate标志位区别

mandatory和immediate是AMQP协议中basic.pulish方法中的两个标志位,它们都有当消息传递过程中不可达目的地时将消息返回给生产者的功能。具体区别在于:

1. mandatory标志位

当mandatory标志位设置为true时,如果exchange根据自身类型和消息routeKey无法找到一个符合条件的queue,那么会调用basic.return方法将消息返还给生产者;当mandatory设为false时,出现上述情形broker会直接将消息扔掉。

2. immediate标志位

当immediate标志位设置为true时,如果exchange在将消息route到queue(s)时发现对应的queue上没有消费者,那么这条消息不会放入队列中。当与消息routeKey关联的所有queue(一个或多个)都没有消费者时,该消息会通过basic.return方法返还给生产者。


概括来说,mandatory标志告诉服务器至少将该消息route到一个队列中,否则将消息返还给生产者;immediate标志告诉服务器如果该消息关联的queue上有消费者,则马上将消息投递给它,如果所有queue都没有消费者,直接把消息返还给生产者,不用将消息入队列等待消费者了。


用前一篇中的程序amqp_sendstring来测试这两个标志位情况如下

设置了mandatory,路由不到队列的情况:

    die_on_error(amqp_basic_publish(conn,
                                    1,
                                    amqp_cstring_bytes(exchange),
                                    amqp_cstring_bytes(routingkey),
                                    1,   //mandatory标志位,消息不能到达队列则返回basic.return
                                    0,   //immediate标志位,消息不能到达消费者返回basic.return
                                    &props,
                                    amqp_cstring_bytes(messagebody)),
                 "Publishing");

./amqp_sendstring localhost 5672 amq.direct jfy test
method.id=003C0032,method.name=AMQP_BASIC_RETURN_METHOD
Return.reply_code=312
Return.reply_text=NO_ROUTE
Return.message=test

返回"NO_ROUTE"

设置了immediate,路由不到队列的情况:

    die_on_error(amqp_basic_publish(conn,
                                    1,
                                    amqp_cstring_bytes(exchange),
                                    amqp_cstring_bytes(routingkey),
                                    0,   //mandatory标志位,消息不能到达队列则返回basic.return
                                    1,   //immediate标志位,消息不能到达消费者返回basic.return
                                    &props,
                                    amqp_cstring_bytes(messagebody)),
                 "Publishing");

./amqp_sendstring localhost 5672 amq.direct jfy test
method.id=003C0032,method.name=AMQP_BASIC_RETURN_METHOD
Return.reply_code=313
Return.reply_text=NO_CONSUMERS
Return.message=test

返回"NO_CONSUMERS"

注意:在RabbitMQ3.0以后的版本里,去掉了immediate参数支持,发送带immediate标记的publish会返回如下错误:

“{amqp_error,not_implemented,"immediate=true",'basic.publish'}”


为什么移除immediate标记,参见如下版本变化描述:

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.

这段解释的大概意思就是:immediate标记会影响镜像队列性能,增加代码复杂性,并建议采用"设置消息TTL"和"DLX"等方式替代。


阅读更多
想对作者说点什么?

博主推荐

换一批

没有更多推荐了,返回首页