【原创】RabbitMQ 之 Dead Letter Exchanges(翻译)


Dead Letter Exchanges

Messages from a queue can be 'dead-lettered'; that is, republished to another exchange when any of the following events occur:
queue 中的消息可能成为“死信”;也就是说,会在下面任何一种情况发生时,重新 publish 消息到另外的 exchange 中:
  • The message is rejected (basic.reject or basic.nack) with requeue=false,
    消息被拒绝了(通过 basic.reject 方法或 basic.nack 方法),同时设置了 requeue=false 参数,
  • The TTL for the message expires; or
    消息本身设置了 TTL ,且达到了过期时间;或者
  • The queue length limit is exceeded.queue
    可持有消息数量达到了上限
Dead letter exchanges (DLXs) are normal exchanges. They can be any of the usual types and are declared as usual.
死信 exchang(DLXs)就是普通的 exchange 。其如普通 exchange 一样具有各种类型,也具有一样的声明方式。

For any given queue, a DLX can be defined by clients using the queue's arguments, or in the server using policies. In the case where both policy and arguments specify a DLX, the one specified in arguments overrules the one specified in policy.
对于任何给定的 queue ,客户端可以通过 queue 的 argument 参数指定 DLX ,或者直接在服务器侧 通过 policy 创建。如果出现同时使用两种方式创建了 DLX 的情况,则通过 argument 指定的 DLX 优先采用

Configuration using arguments
通过 argument 方式进行配置

To set the dead letter exchange for a queue, set the x-dead-letter-exchange argument to the name of the exchange:
如果要为某个 queue 设置 DLX ,则需要将 argument x-dead-letter-exchange 设置为 exchange 的名字:
channel.exchangeDeclare("some.exchange.name", "direct");

Map<String, Object> args = new HashMap<String, Object>();
args.put("x-dead-letter-exchange", "some.exchange.name");
channel.queueDeclare("myqueue", false, false, false, args);
The code above declares a new exchange called some.exchange.name and sets this new exchange as the dead letter exchange for a newly created queue. Note that the exchange does not have to be declared when the queue is declared, but it should exist by the time messages need to be dead-lettered; if it is missing then, the messages will be silently dropped.
上述代码声明了一个新的名为 some.exchange.name 的 exchange ,并且将该 exchange 设置成一个新创建 queue 的 DLX 。值得注意的是,当 queue 被声明的时候,该 exchange 并不要求已经被声明完成,但是当消息需要被当做“死信”处理的时候,该 exchange 必须已经存在。如果仍旧未存在,此时消息将被悄悄的丢掉(blackholed)。

You may also specify a routing key to be used when dead-lettering messages. If this is not set, the message's own routing keys will be used.
你同样可以指定一个 routing key 用于 DLX 分发消息。如果没有指定,那么消息本身使用的 routing key 将被使用。
args.put("x-dead-letter-routing-key", "some-routing-key");
When a dead letter exchange has been specified, in addition to the usual configure permissions on the declared queue, the user needs to have read permissions on that queue and write permissions on the dead letter exchange. Permissions are verified at the time of queue declaration.
当 DLX 被指定好后,对于被声明的 queue 而言,除了通常所需的 configure 权限,用户还需要具有对于该 queue 的 read 权限,和对于 DLX 的 write 权限。相应权限会在 queue 声明的时候被验证。

Configuration using policy
通过 policy 进行配置

To specify a DLX using policy, add the key "dead-letter-exchange" to a policy definition. For example:
通过 policy 来指定 DLX ,则需要在 policy 定义中添加 dead-letter-exchange 这个 key 值。例如:
rabbitmqctl
rabbitmqctl set_policy DLX ".*" '{"dead-letter-exchange":"my-dlx"}' --apply-to queues
rabbitmqctl (Windows)
rabbitmqctl set_policy DLX ".*" "{""dead-letter-exchange"":""my-dlx""}" --apply-to queues

This applies the DLX "my-dlx" to all queues.
上述配置将 DLX "my-dlx" 设置给所有 queue 。

Similarly, an explicit routing key can be specified by adding the key "dead-letter-routing-key" to the policy.
同样地,可以通过添加 key 值 dead-letter-routing-key 到 policy 中以显式指定 routing key 。

Policies can also be defined using the management plugin, see the policy documentation for more details.
policy 还可以通过管理插件进行定义,详情请 参考 policy 文档

Routing Dead-Lettered Messages
死信消息的路由

Dead-lettered messages are routed to their dead letter exchange either:
死信消息将会按照下面的方式被路由到其对应的 DLX 中:
  • with the routing key specified for the queue they were on; or, if this was not set,
    如果设置 DLX 时指定了 routing key ,则使用该 key 进行路由;
  • with the same routing keys they were originally published with.
    如果设置 DLX 时没有指定 routing key ,则使用消息被 publish 时采用的 key 。
For example, if you publish a message to an exchange with routing key foo, and that message is dead-lettered, it will be published to its dead letter exchange with routing key foo. If the queue the message originally landed on had been declared with x-dead-letter-routing-key set to bar, then the message will be published to its dead letter exchange with routing key bar.
例如,如果你使用 foo 作为 routing key 去 publish 了一条消息,并且发生了“死信”,那么该消息将被 publish 到其对应的 DLX 中将 foo 作为 routing key 进行路由。如果消息的目标 queue 在声明的时候设置了 x-dead-letter-routing-key 为 bar 到 argument 中,那么消息最终会使用 bar 作为 routing key 将消息发送到 DLX 中。

Note that, if a specific routing key was not set for the queue, messages on it are dead-lettered with all their original routing keys. This includes routing keys added by the CC and BCC headers (see Sender-selected distribution for details on these two headers).
值得注意的是,如果没有为 queue 设置特定的 routing key ,那么发送到该 queue 的消息在发生“死信”情况时,将分别使用其相应的 routing key 。这些 routing key 包括由 CC 和 BCC 头添加的那些( 详情参考 Sender-selected distribution 中对这两个头的说明)

Dead-lettered messages are re-published with publisher confirms turned on internally so, the dead-letter queues the messages eventually land on must confirm the messages before they are removed from the original queue. In other words, the publishing queue will not remove messages before the dead-letter queues acknowledge receiving them (see Confirms for details on the guarantees made). Note that, in the event of an unclean broker shutdown, the same message may be duplicated on both the original queue and on the dead-letter queues.
死信消息被重新 publish 时默认使用了 publisher confirm 机制,也就是说,保存死信的 queue 需要对这些消息进行 confirm ,才能使得消息被原始 queue 移除。换句话说,publish 到目标 queue 中的消息,在出现死信情况后,只有在死信 queue 对重新 publish 的消息进行了 confirm 之后,才会将消息移除(详情参 Confirms 的说明)。值得注意的是,如果处于 unclean 状态中的 broker 发生了 shutdown ,那么原始 queue 和死信 queue 中均可能出现重复的消息。

It is possible to form a cycle of dead-letter queues. For instance, this can happen when a queue dead-letters messages to the default exchange without specifiying a dead-letter routing key. Messages in such cycles (i.e. messages that reach the same queue twice) will be dropped if the entire cycle is due to message expiry.
利用死信 queue 构成一个循环结构是可能的一种使用情况。例如,当原始 queue 将消息按照死信处理,将其发送到默认 exchange 上,并且没有指定死信 routing key 的情况。在这个循环结构中的消息(也就是说,消息将会到达同一个 queue 两次)将会在消息自身设置的过期时间到达后被丢弃。

Dead-Lettered Messages
死信消息

Dead-lettering a message modifies its headers:
将消息处理为死信后,将会对其头部做如下修改:
  • the exchange name is replaced with that of the latest dead-letter exchange,
    exchange 名被替换成最新设置的 DLX 值,
  • the routing key may be replaced with that specified in a dead letter queue,
    routing key 可能被替换成声明死信 queue 时指定的值,
  • if the above happens, the CC header will also be removed, and
    如果上述情况发生了,CC 头将被移除,并且
  • the BCC header will be removed as per Sender-selected distribution.
    BCC 头将按照 Sender-selected distribution 中的要求被移除。
The dead-lettering process adds an array to the header of each dead-lettered message named x-death. This array contains an entry for each time the message was dead-lettered. Each such entry is a table that consists of several fields:
死信处理进程将会在每一条死信消息的头部添加一个名为 x-death 的数组。该数组中包含每一次消息被处理为死信时的 entry 。每一个这样的 entry 都是一个由下面各域构成的表:

  • queue - the name of the queue the message was in before it was dead-lettered, 
                  消息被作为死信处理前,应该进入的 queue 的名字,
  • reason - see below,
  • time - the date and time the message was dead lettered as a 64-bit AMQP format timestamp, 
              消息被处理为死信的日期和时间,表示为 64-bit 的 AMQP 格式时间戳,
  • exchange - the exchange the message was published to (note that this will be a dead letter exchange if the message is dead lettered multiple times), and 
                       消息应该 publish 到的 exchange 名(值得注意的是,该值在消息作为死信处理多次的情况下将会变为 DLX 的名字)
  • routing-keys - the routing keys (including CC keys but excluding BCC ones) the message was published with. 
                            消息被 publish 时使用的 routing key 值(包括 CC key 但不包括 BCC 值)。
  • original-expiration (if the message was dead-letterered due to per-message TTL) - the original expiration property of the message. The expiration property is removed from the message on dead-lettering in order to prevent it from expiring again in any queues it is routed to.
    初始过期时间(由于消息自身 TTL 到期而变为死信的情况) - 消息的原始过期时间属性。过期属性将会在消息被处理为死信时移除,以方式消息在死信 queue 中再次过期。
The reason is a name describing why the message was dead-lettered and is one of the following:
上面没有说明的 reason 值,实际上是一个描述为何消息作为死信处理的字段,可能为以下的值:
  • rejected - the message was rejected with requeue=false, 
                    消息被带有 requeue=false 的信令所拒绝,
  • expired - the TTL of the message expired; or 
                    消息 的 TTL 到期;或者
  • maxlen - the maximum allowed queue length was exceeded. 
                   保存消息的 queue 的长度达到了上限。
Note that the array is sorted most-recent-first, so the most recent dead-lettering will be recorded in the first entry.
值得注意的是,上面提到的数组是按照 most-recent-first 来排序的,故最新的死信消息将会被记录到第一个 entry 中。

转载于:https://my.oschina.net/moooofly/blog/382387

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值