日韩黑丝制服一区视频播放|日韩欧美人妻丝袜视频在线观看|九九影院一级蜜桃|亚洲中文在线导航|青草草视频在线观看|婷婷五月色伊人网站|日本一区二区在线|国产AV一二三四区毛片|正在播放久草视频|亚洲色图精品一区

分享

RabbitMQ消息隊列(九):Publisher的消息確認機制

 Aske5rqhg680oe 2017-05-25

   在前面的文章中提到了queue和consumer之間的消息確認機制:通過設置ack。那么Publisher能不到知道他post的Message有沒有到達queue,甚至更近一步,是否被某個Consumer處理呢?畢竟對于一些非常重要的數(shù)據(jù),可能Publisher需要確認某個消息已經(jīng)被正確處理。

      在我們的系統(tǒng)中,我們沒有是實現(xiàn)這種確認,也就是說,不管Message是否被Consume了,Publisher不會去care。他只是將自己的狀態(tài)publish給上層,由上層的邏輯去處理。如果Message沒有被正確處理,可能會導致某些狀態(tài)丟失。但是由于提供了其他強制刷新全部狀態(tài)的機制,因此這種異常情況的影響也就可以忽略不計了。

     對于某些異步操作,比如客戶端需要創(chuàng)建一個FileSystem,這個可能需要比較長的時間,甚至要數(shù)秒鐘。這時候通過RPC可以解決這個問題。因此也就不存在Publisher端的確認機制了。

     那么,有沒有一種機制能保證Publisher能夠感知它的Message有沒有被處理的?答案肯定的。在這里感謝笑天居士同學:他在我的《RabbitMQ消息隊列(三):任務分發(fā)機制》文后留言一起討論了問題,而且也查找了一些資料。在這里我整理了一下他轉(zhuǎn)載和一篇文章和原創(chuàng)的一篇文章。銜接已經(jīng)附后。

 

1. 事務機制 VS Publisher Confirm

       如果采用標準的 AMQP 協(xié)議,則唯一能夠保證消息不會丟失的方式是利用事務機制 — 令 channel 處于 transactional 模式、向其 publish 消息、執(zhí)行 commit 動作。在這種方式下,事務機制會帶來大量的多余開銷,并會導致吞吐量下降 250% 。為了補救事務帶來的問題,引入了 confirmation 機制(即 Publisher Confirm)。

     為了使能 confirm 機制,client 首先要發(fā)送 confirm.select 方法幀。取決于是否設置了 no-wait 屬性,broker 會相應的判定是否以 confirm.select-ok 進行應答。一旦在 channel 上使用 confirm.select方法,channel 就將處于 confirm 模式。處于 transactional 模式的 channel 不能再被設置成 confirm 模式,反之亦然。
    一旦 channel 處于 confirm 模式,broker 和 client 都將啟動消息計數(shù)(以 confirm.select 為基礎從 1 開始計數(shù))。broker 會在處理完消息后,在當前 channel 上通過發(fā)送 basic.ack 的方式對其進行 confirm 。delivery-tag 域的值標識了被 confirm 消息的序列號。broker 也可以通過設置 basic.ack 中的 multiple 域來表明到指定序列號為止的所有消息都已被 broker 正確的處理了。

       在異常情況中,broker 將無法成功處理相應的消息,此時 broker 將發(fā)送 basic.nack 來代替 basic.ack 。在這個情形下,basic.nack 中各域值的含義與 basic.ack 中相應各域含義是相同的,同時 requeue 域的值應該被忽略。通過 nack 一或多條消息,broker 表明自身無法對相應消息完成處理,并拒絕為這些消息的處理負責。在這種情況下,client 可以選擇將消息 re-publish 。

      在 channel 被設置成 confirm 模式之后,所有被 publish 的后續(xù)消息都將被 confirm(即 ack) 或者被 nack 一次。但是沒有對消息被 confirm 的快慢做任何保證,并且同一條消息不會既被 confirm 又被 nack 。

 

2. 消息在什么時候確認

broker 將在下面的情況中對消息進行 confirm :

  • broker 發(fā)現(xiàn)當前消息無法被路由到指定的 queues 中(如果設置了 mandatory 屬性,則 broker 會先發(fā)送 basic.return)
  • 非持久屬性的消息到達了其所應該到達的所有 queue 中(和鏡像 queue 中)
  • 持久消息到達了其所應該到達的所有 queue 中(和鏡像 queue 中),并被持久化到了磁盤(被 fsync)
  • 持久消息從其所在的所有 queue 中被 consume 了(如果必要則會被 acknowledge)

broker 會丟失持久化消息,如果 broker 在將上述消息寫入磁盤前異常。在一定條件下,這種情況會導致 broker 以一種奇怪的方式運行。例如,考慮下述情景:

   1.  一個 client 將持久消息 publish 到持久 queue 中
2.  另一個 client 從 queue 中 consume 消息(注意:該消息具有持久屬性,并且 queue 是持久化的),當尚未對其進行 ack
3.  broker 異常重啟
4.  client 重連并開始 consume 消息

   在上述情景下,client 有理由認為消息需要被(broker)重新 deliver 。但這并非事實:重啟(有可能)會令 broker 丟失消息。為了確保持久性,client 應該使用 confirm 機制。如果 publisher 使用的 channel 被設置為 confirm 模式,publisher 將不會收到已丟失消息的 ack(這是因為 consumer 沒有對消息進行 ack ,同時該消息也未被寫入磁盤)。

3. 編程實現(xiàn)

首先要區(qū)別AMQP協(xié)議mandatory和immediate標志位的作用。

mandatory和immediate是AMQP協(xié)議中basic.pulish方法中的兩個標志位,它們都有當消息傳遞過程中不可達目的地時將消息返回給生產(chǎn)者的功能。具體區(qū)別在于:
1. mandatory標志位
當mandatory標志位設置為true時,如果exchange根據(jù)自身類型和消息routeKey無法找到一個符合條件的queue,那么會調(diào)用basic.return方法將消息返還給生產(chǎn)者;當mandatory設為false時,出現(xiàn)上述情形broker會直接將消息扔掉。
2. immediate標志位
當immediate標志位設置為true時,如果exchange在將消息route到queue(s)時發(fā)現(xiàn)對應的queue上沒有消費者,那么這條消息不會放入隊列中。當與消息routeKey關聯(lián)的所有queue(一個或多個)都沒有消費者時,該消息會通過basic.return方法返還給生產(chǎn)者。

具體的代碼參考請參考參考資料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

    本站是提供個人知識管理的網(wǎng)絡存儲空間,所有內(nèi)容均由用戶發(fā)布,不代表本站觀點。請注意甄別內(nèi)容中的聯(lián)系方式、誘導購買等信息,謹防詐騙。如發(fā)現(xiàn)有害或侵權內(nèi)容,請點擊一鍵舉報。
    轉(zhuǎn)藏 分享 獻花(0

    0條評論

    發(fā)表

    請遵守用戶 評論公約

    類似文章 更多