簡體   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