0

我正在调用:

GetResponse response = channel.basicGet("some.queue", false); // no auto-ack
....
channel.basicAck(deliveryTag, ...);

但是,当我调用 时basicGet,队列中的消息停留在“就绪”状态,而不是“未确认”状态。我希望它们处于未确认状态,以便我可以要么basic.ack它们(从而将它们从队列中丢弃),要么basic.nack它们

4

2 回答 2

4

我正在执行以下操作来模仿延迟 ack

消费时

  1. 从初始队列中获取(使用)消息。
  2. 创建一个“PendingAck_123456”队列。
    123456 是消息的唯一 ID。
    设置以下属性
    • x-message-ttl(超时后重新排队)
    • x-expires(确保临时队列将被删除)
    • x-dead-letter-exchangex-deal-letter-routing-key在 TTL 到期时重新排队到初始队列。
  3. 将消息 Pending ack 发布到此“PendingAck_123456”队列
  4. 确认消息以将其从初始队列中删除

在确认时间

  1. 根据消息 ID 计算队列名称并从“PendingAck_123456”队列中获取
  2. 确认(无需调用.getBody())。
    这将从这个挂起的队列中删除它,防止 TTL 重新排队

评论

  • 一个只有 1 条消息的队列。如果有很多这样的队列,这是一个问题吗?
  • 重新排队的消息将在队列输入端发送......而不是在队列输出端(就像真正的确认一样)......对消息顺序有影响。
  • 消息由应用程序复制到 Pending Queue。这是一个额外的步骤,可能会影响整体性能。
  • To mimic a Nack/Reject, you you may want to Copy the message to the Initial Queue, and Ack it from the PendingAck queue. By default, the TTL would do it (later).
于 2014-01-13T08:39:43.630 回答
2

当它工作正常ack后立即执行get。但是,就我而言,它们是由请求分开的。Spring 的模板在每次执行时都会关闭通道和连接。所以有三种选择:

  • 在应用程序的整个生命周期中保持一个通道和连接打开
  • 有某种对话范围(或最坏情况:使用会话)来存储相同的频道并重用它。
  • 每个请求使用一个通道,立即确认收到,并将消息存储在内存中。

在前两种情况下,你不能用spring的RabbitTemplate

于 2011-10-24T11:38:11.233 回答