RabbitMQ訊息分發輪詢和Message Acknowledgment
一、訊息分發
RabbitMQ中的訊息都只能儲存在Queue中,生產者(中的P)生產訊息並最終投遞到Queue中,消費者(中的C)可以從Queue中擷取訊息並消費。
多個消費者可以訂閱同一個Queue,這時Queue中的訊息會被平均分攤給多個消費者進行處理,而不是每個消費者都收到所有的訊息並處理。
啟動3個消費者
生產者依次產生3條訊息
可見3條訊息分別被3個消費者擷取,所以RabbitMQ是採用輪詢機制將訊息佇列Queue中的訊息依次發給不同的消費者
二、訊息確認(Message Acknowledgment)
在實際應用中,可能會發生消費者收到Queue中的訊息,但沒有處理完成就宕機(或出現其他意外)的情況,這種情況下就可能會導致訊息丟失。為了避免這種情況發生,我們可以要求消費者在消費完訊息後發送一個回執給RabbitMQ,RabbitMQ收到訊息回執(Message acknowledgment)後才將該訊息從Queue中移除;如果RabbitMQ沒有收到回執並檢測到消費者的RabbitMQ串連斷開,則RabbitMQ會將該訊息發送給其他消費者(如果存在多個消費者)進行處理。這裡不存在timeout概念,一個消費者處理訊息時間再長也不會導致該訊息被發送給其他消費者,除非它的RabbitMQ串連斷開。
如何來實現呢?只需要將consumer消費者端中 no_ack = True去掉就行了
no_ack 就 no acknowlegment的意思,這個參數會導致RabbitMQ並不關心消費者有沒有處理完成,可能在消費者擷取訊息後就將該訊息從Queue中移除。去掉這個參數,如果在消費者執行過程當初出現了意外(宕機),RabbitMQ沒有收到訊息回執,就會發送給其他消費者執行。
修改consumer端
def callback(ch, method, properties, body): print('--->>', ch, '\n', method, '\n', properties) time.sleep(30) # 讓消費者處理的時間長一點,可以用來類比運行中斷開的情況 print(" [x] Received %r" % body) ch.basic_ack(delivery_tag=method.delivery_tag) # 確認訊息被執行完畢,主動告知rabbitMQ# ch: 聲明的管道channel對象記憶體位址 # channel.basic_consume(callback, # 如果收到訊息就調用callback函數來處理訊息 queue='hello', # no_ack=True )
運行3個消費者,接收生產者的資料,依次關閉消費者1和消費者2,最後RabbitMQ中的訊息還是會被消費者3處理。
CentOS 7.2 下 RabbitMQ 叢集搭建
CentOS7環境安裝使用專業的訊息佇列產品RabbitMQ
RabbitMQ入門教程
在CentOS7上安裝RabbitMQ 詳解
NServiceBus 結合 RabbitMQ 使用教程
CentOS 7下RabbitMQ叢集安裝配置
RabbitMQ實戰:高效部署分布式訊息佇列 中文PDF掃描版
CentOS7上RabbitMQ安裝詳述
RabbitMQ分布式叢集架構和高可用性(HA)
RabbitMQ 的詳細介紹:請點這裡
RabbitMQ 的:請點這裡