繁体   English   中英

基本.Nack未处理

[英]basic.Nack not being processed

这是我正在尝试做的事情:

  1. 出消息
  2. 对消息进行操作
  3. 如果操作失败,则将消息放回队列
  4. 如果操作成功,请确认消息

我现在的问题是,如果操作失败,则不会重新排队该消息,而是保持未确认状态。 如果我进入RabbitMQ Web配置界面,即使basic.Nack已被跳过,我也会看到消息被标记为未确认。

var delivery = subscription.Next();

var messageBody = delivery.Body;

try
{
   action.Invoke(messageBody);
   subscription.Ack(delivery);
}
catch (Exception ex)
{
   subscription.Model.BasicNack(delivery.DeliveryTag, false, true);
   throw ex;
}

更新:

因此,我注意到消息从“就绪”变为“未确认”的速度非常快。 比我实际上打电话给Subscriber.Next()的速度要快得多,就好像.Net客户端将所有消息缓存在内存中(我的应用程序的内存占用量实际上增长得非常快),并从内存中处理这些消息并随后发送Ack(),取消标记来自未确认的消息。

更新2:

好像排空队列真的很快,是因为我没有在Model上设置BasicQos。 以下内容修复了所有问题。 Basic.Nack()似乎仍然无法工作:

Model.BasicQos(0,1,假)

我怀疑您正在使用:
channel.BasicConsume(your_queue_name, false, consumer); 检索消息。

我使用RabbitMQ 3.2.4服务器和客户端运行了多个测试。 我无法使channel.BasickAck(...)channel.BasicNack(...)都能按预期工作。

也就是说,我能够获得预期的Ack | 使用时出现小问题:
BasicGetResult result = channel.BasicGet(your_queue_name, false);

因此,您可能需要考虑使用其他检索方法来获取消息。 我认识到Consume&Dequeue是“首选”方法,但在我的情况下它们不起作用。 我想一次公平的,一次确认的派遣。 使用BasicGet是实现此目标的唯一方法。

这种方法的缺点是,您可能会失去与subscription.Next()一起使用的客户端事件迭代器。


如果我不得不大胆猜测,我认为有关本地Queue集合的某些事情会破坏该通道提供确认的能力。 值得指出的是,使用new QueueingBasicConsumer(channel);创建使用者new QueueingBasicConsumer(channel); 触发调用以从服务器队列中预提取事件。 使用者的队列只是SharedQueue<RabbitMQ.Client.Events.BasicDeliverEventArgs>而SharedQueue只是IEnumerable的扩展。

还请记住,提取消息的相同通道也需要提供Ack | NACK。 您不能确认| 取消来自其他渠道的消息 或者至少我还没有弄清楚该怎么做,也没有其他人。 这是一个问题,如果您将RabbitMQ对象包装在using语句中(这样就不会留下网络资源), 并且您需要经过很长的流程才能安全地进行确认。

该《 解答》列出了一个体面的工作流程,以解决可能的现实情况,即您的提货渠道将不再是发送Ack的渠道。 NACK。 诀窍是设置TTL,而不会打扰发送Nack-只让新消息过期并自动重新排队。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM