为什么要使用死信队列?

5
我正在考虑为一组服务之间的队列实现死信队列。这与解决未处理消息的问题有关。
我认为,消息可能无法在以下两种情况下之一被处理:
1. 消息本身由于某些与消息本身固有的原因(例如格式不正确)而无法处理。 2. 接收消息的应用程序没有处理它的能力。
在第一种情况下,将消息保留在死信队列中是没有意义的,因为应用程序仍然无法处理它。
在第二种情况下,应用程序需要以某种方式处理来自死信队列的消息。但是,如果它没有处理主队列中的消息的能力,那么为什么会有能力从第二个队列中接收工作呢?
我肯定还漏掉了一些东西。
1个回答

9
死信队列的目的不是将其视为同一订阅者读取的辅助队列。相反,它是一个用于发送无法预期处理的消息的地方。这种情况有两个主要原因:
1. 发布消息中存在错误(您的场景#1) 2. 订阅者的行为发生了变化,现在无法处理以前可以处理的消息。
理想情况下,当设置死信队列时,还应基于已发布到该队列的消息设置警报。然后,在某个单独的过程中,通过订阅死信主题上的订阅来查看消息,以确定为什么无法处理它们。如果消息不正确,则订阅者的所有者可以联系发布者的所有者修复消息(如果需要)。
如果消息是正确的,但订阅者存在 bug 阻止了它们被处理,那么可以修复订阅者。修复后,可以将消息重新发布到原始主题,以便被修复的订阅者捕获,或者可以使用 seek 重播消息。
由于处理能力不足而导致消息传递到死信队列(因此正在否定它们或让 ack 截止日期过期)类似于 #2,并意味着需要增加订阅者的容量,并可能将 flow control 设置为与订阅者可以处理的水平相一致。然后,可以重新发布或使用 seek 再次获取消息。

鉴于消息应仅存储在一个死信队列中,并在进一步(人工)检查之前不进行移动,为什么不保持简单并将消息存储在数据库中,而不是为其设置专用的消息队列呢? - Maurits Moeys
有几个原因:
  1. 如果可能是一些短暂问题,你可能不想在第一次失败后将其移动到数据库中。在这种情况下,你会想要计算失败的次数。然而,这将需要使用数据库本身,因为你不能确定重新发送的消息会传递给相同的订阅客户端。
  2. 如果某条消息以某种方式格式错误,并导致订阅者崩溃,你将没有机会将其写入数据库。
- Kamal Aboul-Hosn
谢谢回复!我还有点困惑。1 => 通常情况下,消息在常规队列中会尝试多次重传,直到被标记为“毒药”/"死信"并转移到死信队列(DLQ),所以DLQ不是用来重试临时错误的吗?2 => 无论写了什么样的备用逻辑,能将一个格式错误、导致崩溃的消息放入DLQ的逻辑同样可以将其存储到数据库中,对吗? - Maurits Moeys
当然,您可以使用数据库。但是许多人喜欢DLQ所带来的简单性,它在保护他们的订阅者方面具有临时和永久故障的优势。 - Kamal Aboul-Hosn

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接