SQS 队列中的确认消息
Posted
技术标签:
【中文标题】SQS 队列中的确认消息【英文标题】:Acknowledge message in SQS queue 【发布时间】:2018-04-02 11:52:41 【问题描述】:我将 Amazon SQS 与 Amazon SQS-JMS java 库与 Java EE 7 一起使用。我想要实现的是在收到消息后,具体取决于业务逻辑应用程序要么确认(使用)消息,要么再次将其重新发送到队列,并在 3 次重试失败后将其移至 DLQ。
我想在 JMS 中使用 CLIENT_Acknowledge 模式并且只确认成功处理的消息,但这是来自他们的官方文档:
在此模式下,当消息被确认时,在此消息之前收到的所有消息也会被隐式确认。例如,如果收到了 10 条消息,并且只有第 10 条消息被确认(按照收到消息的顺序),那么之前的 9 条消息也都被确认。
这个例子似乎也证实了这一点:http://docs.aws.amazon.com/AWSSimpleQueueService/latest/SQSDeveloperGuide/code-examples.html#example-synchronous-receiver-client-acknowledge-mode。
对我来说,这是一种奇怪的行为,与我对 client_acknowledge 的期望相反。这里有比仅仅根据进程状态手动将整个代码中的消息发送到主 SQS 队列或 DLQ 更优雅的解决方案吗?
【问题讨论】:
为什么要向队列重新发送消息?一条消息应该被消费和删除,或者不理会。您希望通过“确认”消息来实现什么目标? @JohnRotenstein 由于我第一次收到事件 B 时的业务逻辑,而不是 A,我想在处理事件 A 后将 B 返回到队列并处理它。另外我想使用重试计数和移动消息在 3 失败后到 DLQ,所以返回消息到队列是有意义的。 SQS 可以提供自己的 DLQ 逻辑。此外,如果您使用 SQS FIFO 队列,它可以保证排序。鉴于这些内置功能,我建议您不要重新处理消息 - 只需将它们拉出,处理它们,然后删除它们。 【参考方案1】:要处理这种情况,您可以为您创建的 DLQ 使用 RedrivePolicy
属性。这种情况的解决方案可以是:
my_q
和 my_q_dl
(后一个用于 DLQ)
使用RedrivePolicy
将DLQ my_q_dl
设置为my_q
的DLQ。
在这里,应注意指定deadLetterTargetArn
和maxReceiveCount
。 maxReceiveCount
是在将任何消息发送到 DLQ 之前,您希望在不确认的情况下处理任何消息的次数。如果您设置maxReceiveCount
=3,则消息将保留在my_q
中,直到消费者第三次拉动而没有确认。
这里有2个案例:
正常情况:收到确认后立即删除 msg。
如果该消息第三次没有确认(消息删除),则该消息将从my_q
中删除并推送到
my_q_dl
自己。
*RedrivePolicy - 包含源队列的死信队列功能参数的字符串。
deadLetterTargetArn - Amazon SQS 在值之后将消息移动到的死信队列的 Amazon 资源名称 (ARN) 超过了 maxReceiveCount。
maxReceiveCount - 消息在被移动到死信队列之前被传递到源队列的次数。
注意 FIFO队列的死信队列也必须是FIFO队列。同样,标准队列的死信队列也必须是 标准队列。*
【讨论】:
那么当它是多个属性时,如何将 RedrivePolicy 格式化为字符串?作为 JSON 字符串。 SetQueueAttributesRequest 请求 = 新 SetQueueAttributesRequest() .withQueueUrl(src_queue_url) .addAttributesEntry("RedrivePolicy", "\"maxReceiveCount\":\"5\", \"deadLetterTargetArn\":\"" + dl_queue_arn + "\"" );【参考方案2】:你可以使用:
UNORDERED_ACKNOWLEDGE
SQSSession.UNORDERED_ACKNOWLEDGE
来自 'com.amazon.sqs.javamessaging;'正如它在文档中所述,它是 Client_Acknowledge 的一种变体,它只确认调用它的消息。
/**
* Non standard acknowledge mode. This is a variation of CLIENT_ACKNOWLEDGE
* where Clients need to remember to call acknowledge on message. Difference
* is that calling acknowledge on a message only acknowledge the message
* being called.
*/
依赖示例: “com.amazonaws:amazon-sqs-java-messaging-lib:1.0.3”
【讨论】:
非常感谢,一个更好的名字会节省很多时间。以上是关于SQS 队列中的确认消息的主要内容,如果未能解决你的问题,请参考以下文章