一文搞懂RabbitMQ的ack與nack

  點擊上方“JavaEdge”,關注公衆號

設爲“星標”,好文章不錯過!


使用 MQ 時,需要注意保證消息不會丟失且被準確消費。

connection = factory.newConnection();      final Channel channel = connection.createChannel();channel.queueDeclare("隊列名", true, false, false, null);
//第二個參數設爲true爲自動應答,false爲手動ackchannel.basicConsume("隊列名", true, new DefaultConsumer(channel){ @Override public void handleDelivery(String consumerTag, Envelope envelope, AMQP.BasicProperties properties, byte[] body) throws IOException { try { Thread.sleep(10000); System.out.println(new String(body, "UTF-8")); //模擬異常 int i = 1/0; //手動ack //channel.basicAck(envelope.getDeliveryTag(), false); } catch (Exception e) { //重新放入隊列 //channel.basicNack(envelope.getDeliveryTag(), false, true); //拋棄此條消息 //channel.basicNack(envelope.getDeliveryTag(), false, false); e.printStackTrace();
}finally { } }});

handleDelivery是回調方法,如果隊列中有消息就會執行這個方法,參數中的body就是消息內容。
channel.basicConsume 方法中第二個參數爲boolean 類型,意思是消息的ack 需要自動(true)還是手動(false)。

ack機制爲自動



不管 try 中有沒有異常,消息管理界面上隊列裏的消息都被消費了,沒有了(ready和unacked狀態欄都沒有了),下面是管理界面, 隊列中的未被消費的消息有多少條都會在ready狀態欄下,分發到消費端後,消費端沒有回發ack的消息會在unacked狀態欄中。

手動ack應答(channel.basicAck方法)



這樣做的目的是保證消息在正確消費後給回饋,說明我正確消費了。這時隊列就可以把這條消息刪除了,如果消費端接收了消息,但是沒有給返回ack應答,那麼這條消息會繼續存在unacked狀態下,佔據隊列的空間,等到空間滿了,就會出現接下來的消息不能被消費的情況。

正確的消息被ack了,那麼在消費過程中發生異常怎麼辦?該條消費肯定不能返回ack應答了,這時就需要channel.basicNack,該方法解決了消費異常情況下該條消息怎麼處理,有兩種辦法:

  1. 這條消息重新放回隊列,重新消費

  2. 拋棄此條消息

具體使用哪個方法,這種情況下,建議捕捉異常類型,判斷是哪種異常,再做具體處理。






目前交流羣已有 800+人,旨在促進技術交流,可關注公衆號添加筆者微信邀請進羣


喜歡文章,點個“在看、點贊、分享”素質三連支持一下~

本文分享自微信公衆號 - JavaEdge(Java-Edge)。
如有侵權,請聯繫 [email protected] 刪除。
本文參與“OSC源創計劃”,歡迎正在閱讀的你也加入,一起分享。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章