在前面的文章中提到了queue和consumer之間的消息確認(rèn)機(jī)制:通過設(shè)置ack。那么Publisher能不到知道他post的Message有沒有到達(dá)queue,甚至更近一步,是否被某個(gè)Consumer處理呢?畢竟對于一些非常重要的數(shù)據(jù),可能Publisher需要確認(rèn)某個(gè)消息已經(jīng)被正確處理。 在我們的系統(tǒng)中,我們沒有是實(shí)現(xiàn)這種確認(rèn),也就是說,不管Message是否被Consume了,Publisher不會(huì)去care。他只是將自己的狀態(tài)publish給上層,由上層的邏輯去處理。如果Message沒有被正確處理,可能會(huì)導(dǎo)致某些狀態(tài)丟失。但是由于提供了其他強(qiáng)制刷新全部狀態(tài)的機(jī)制,因此這種異常情況的影響也就可以忽略不計(jì)了。 對于某些異步操作,比如客戶端需要?jiǎng)?chuàng)建一個(gè)FileSystem,這個(gè)可能需要比較長的時(shí)間,甚至要數(shù)秒鐘。這時(shí)候通過RPC可以解決這個(gè)問題。因此也就不存在Publisher端的確認(rèn)機(jī)制了。 那么,有沒有一種機(jī)制能保證Publisher能夠感知它的Message有沒有被處理的?答案肯定的。在這里感謝笑天居士同學(xué):他在我的《RabbitMQ消息隊(duì)列(三):任務(wù)分發(fā)機(jī)制》文后留言一起討論了問題,而且也查找了一些資料。在這里我整理了一下他轉(zhuǎn)載和一篇文章和原創(chuàng)的一篇文章。銜接已經(jīng)附后。
1. 事務(wù)機(jī)制 VS Publisher Confirm如果采用標(biāo)準(zhǔn)的 AMQP 協(xié)議,則唯一能夠保證消息不會(huì)丟失的方式是利用事務(wù)機(jī)制 — 令 channel 處于 transactional 模式、向其 publish 消息、執(zhí)行 commit 動(dòng)作。在這種方式下,事務(wù)機(jī)制會(huì)帶來大量的多余開銷,并會(huì)導(dǎo)致吞吐量下降 250% 。為了補(bǔ)救事務(wù)帶來的問題,引入了 confirmation 機(jī)制(即 Publisher Confirm)。 為了使能 confirm 機(jī)制,client 首先要發(fā)送 confirm.select 方法幀。取決于是否設(shè)置了 no-wait 屬性,broker 會(huì)相應(yīng)的判定是否以 confirm.select-ok 進(jìn)行應(yīng)答。一旦在 channel 上使用 confirm.select方法,channel 就將處于 confirm 模式。處于 transactional 模式的 channel 不能再被設(shè)置成 confirm 模式,反之亦然。 在異常情況中,broker 將無法成功處理相應(yīng)的消息,此時(shí) broker 將發(fā)送 basic.nack 來代替 basic.ack 。在這個(gè)情形下,basic.nack 中各域值的含義與 basic.ack 中相應(yīng)各域含義是相同的,同時(shí) requeue 域的值應(yīng)該被忽略。通過 nack 一或多條消息,broker 表明自身無法對相應(yīng)消息完成處理,并拒絕為這些消息的處理負(fù)責(zé)。在這種情況下,client 可以選擇將消息 re-publish 。 在 channel 被設(shè)置成 confirm 模式之后,所有被 publish 的后續(xù)消息都將被 confirm(即 ack) 或者被 nack 一次。但是沒有對消息被 confirm 的快慢做任何保證,并且同一條消息不會(huì)既被 confirm 又被 nack 。
2. 消息在什么時(shí)候確認(rèn)broker 將在下面的情況中對消息進(jìn)行 confirm :
broker 會(huì)丟失持久化消息,如果 broker 在將上述消息寫入磁盤前異常。在一定條件下,這種情況會(huì)導(dǎo)致 broker 以一種奇怪的方式運(yùn)行。例如,考慮下述情景: 1. 一個(gè) client 將持久消息 publish 到持久 queue 中 在上述情景下,client 有理由認(rèn)為消息需要被(broker)重新 deliver 。但這并非事實(shí):重啟(有可能)會(huì)令 broker 丟失消息。為了確保持久性,client 應(yīng)該使用 confirm 機(jī)制。如果 publisher 使用的 channel 被設(shè)置為 confirm 模式,publisher 將不會(huì)收到已丟失消息的 ack(這是因?yàn)?consumer 沒有對消息進(jìn)行 ack ,同時(shí)該消息也未被寫入磁盤)。 3. 編程實(shí)現(xiàn)首先要區(qū)別AMQP協(xié)議mandatory和immediate標(biāo)志位的作用。 mandatory和immediate是AMQP協(xié)議中basic.pulish方法中的兩個(gè)標(biāo)志位,它們都有當(dāng)消息傳遞過程中不可達(dá)目的地時(shí)將消息返回給生產(chǎn)者的功能。具體區(qū)別在于: 具體的代碼參考請參考參考資料1.
參考資料: 1. http://blog.csdn.net/jiao_fuyou/article/details/21594205 2. http://blog.csdn.net/jiao_fuyou/article/details/21594947 3. http://my.oschina.net/moooofly/blog/142095 |
|