天天看點

rabbitmq雜談

rabbitmq中的consumerTag和deliveryTag分别是幹啥的,有什麼用?

同一個會話, consumerTag 是固定的 可以做此會話的名字, deliveryTag 每次接收消息+1,可以做此消息處理通道的名字。

是以 deliveryTag 可以用來回傳告訴 rabbitmq 這個消息處理成功 清除此消息(basicAck方法)。

Delivery Tag:

當我們需要确認一條消息已經被消費時,我們調用的 basicAck 方法的第一個參數是 Delivery Tag。

Delivery Tag 用來辨別信道中投遞的消息。RabbitMQ 推送消息給 Consumer 時,會附帶一個 Delivery Tag,以便 Consumer 可以在消息确認時告訴 RabbitMQ 到底是哪條消息被确認了。

RabbitMQ 保證在每個信道中,每條消息的 Delivery Tag 從 1 開始遞增。

basicAck 方法的第二個參數 multiple 取值為 false 時,表示通知 RabbitMQ 目前消息被确認;如果為 true,則額外将比第一個參數指定的 delivery tag 小的消息一并确認。(批量确認針對的是整個信道,參考gordon.study.rabbitmq.ack.TestBatchAckInOneChannel.java。)

對同一消息的重複确認,或者對不存在的消息的确認,會産生 IO 異常,導緻信道關閉。

B. 忘了确認會怎樣

如果我們注釋掉22行,讓 consumerChannel1 不再确認消息,世界會怎樣?

rabbitmq雜談

隻要程式還在運作,這3條消息就一直是 Unacked 狀态,無法被 RabbitMQ 重新投遞。更厲害的是,RabbitMQ 消息消費并沒有逾時機制,也就是說,程式不重新開機,消息就永遠是 Unacked 狀态。處理運維事件時不要忘了這些 Unacked 狀态的消息。

當程式關閉時(實際隻要 Consumer 關閉就行),這3條消息會恢複為 Ready 狀态。

C. 取消确認

當消費消息出現異常時,我們需要取消确認,這時我們可以使用 Channel 的 basicReject 方法。

$message->delivery_info['channel']->basic_nack($message->delivery_info['delivery_tag'],false,true);      

第一個參數指定 delivery tag,第三個參數說明如何處理這個失敗消息。requeue 值為 true 表示該消息重新放回隊列頭,值為 false 表示放棄這條消息。