死信队列

https://blueprints.launchpad.net/zaqar/+spec/dead-letter-queue

问题描述

目前,如果消息被多次声明但仍然无法成功处理,Zaqar 无法采取任何措施。如果 Zaqar 可以提供死信队列支持,让用户为队列 B 提供一个现有的队列 A 作为死信队列,那将会很好。死信队列存储这些消息,允许开发者查找常见模式和潜在的软件问题。

提议的变更

1. 在队列的元数据中添加三个新的保留属性:_max_claim_count_dead_letter_queue

_max_claim_count 是消息可以被声明的最大次数。通常,这意味着消息无法成功处理。此属性没有默认值。如果未设置,则表示当前队列未启用此功能。

_dead_letter_queue 是消息在达到最大声明次数后将被移动到的目标。不支持将队列 C 作为队列 B 的死信队列,而队列 B 又被设置为队列 A 的死信队列。这不是本规范要解决的问题。从技术上讲,即使用户可以将队列 C 设置为队列 B 的死信队列(当队列 B 是队列 A 的死信队列时),由于移动是由声明触发的,因此如果用户不显式声明队列 B 中的消息,则不会发生任何事情。

_dead_letter_queue_messages_ttl 是将消息移动到 DLQ 后的新 TTL 设置。如果未设置,则保留当前的 TTL。

2. 为了获得更好的性能,在进行验证时,确保 DLQ 和当前队列位于同一个池中。

3. 在数据库中的消息中添加一个新字段,用于保存声明计数。

  1. 声明创建的变更

    4.1. 从消息中获取当前的声明计数,并通过加一更新声明计数。

    4.2. 检查声明计数是否超过队列元数据中定义的最大声明计数。如果未超过 _max_claim_count,则执行正常的声明。

    4.3. 如果声明计数超过 _max_claim_count,则直接将消息移动到死信队列。考虑到 DLQ 的目标,我们希望保留消息的声明信息。因此,取决于存储后端,"移动"可能会引入限制。例如,对于 MongoDB 后端,我们可能需要通过直接更改队列名称将消息从源队列移动到 DLQ。这意味着两者必须在同一个存储池中创建。

    移动消息后,Zaqar 将不会对死信队列中的这些消息采取任何操作。用户可以使用/将使用这些消息来调试为什么这些消息无法成功处理。换句话说,允许开发者从这些消息中查找常见模式和潜在的软件问题。

    4.4. 移动到 DLQ 的消息将根据设置 _dead_letter_queue_messages_ttl 更新它们的 TTL。如果未设置,则保留消息的当前 TTL。

缺点

基于当前设计,由于技术权衡,我们可能存在一个限制。将消息从源队列移动到死信队列时,最好保留声明信息,但如果我们要这样做,则必须确保这两个队列位于同一个存储池中。不同后端上的实现可能不同。

备选方案

实现

负责人

主要负责人

flwang <flwang@catalyst.net.nz>

里程碑

完成目标里程碑

Pike-3

工作项

  1. 在队列元数据中添加 _max_claim_count 和 _dead_letter_queue 作为保留属性

  2. 添加对新保留属性的验证

  3. 添加一个新字段来计算消息的声明次数,这需要针对 maongoDB、swift 和 redis 进行。

  4. 添加声明创建中的变更,该变更将为消息添加声明计数,并检查计数是否超过队列元数据中定义的最大声明计数。如果超过,则将消息移动到死信队列。

  5. 添加此功能的发布说明

  6. 更新 API 参考

  7. 添加此功能的开发者文档

  8. 相应地更改单元测试、功能测试和 tempest 测试。

依赖项

注意

本作品采用知识共享署名 3.0 非移植许可协议授权。 http://creativecommons.org/licenses/by/3.0/legalcode