RabbitMQ 的基本概念
RabbitMQ 是一種消息隊列帘瞭,用于程序間的通信。形象地說 : MQ就像一個郵局,發(fā)送者將消息寫入 MQ,MQ 負責(zé)把消息發(fā)送給接收者窒悔。RabbitMQ 可支持
Java
,PHP
,Python
,Go
,JavaScript
,Ruby
等多種語言。本文主要介紹 RabbitMQ 的基本概念和模型敌买。
術(shù)語
- 生產(chǎn)者( producer )
在圖中為 P简珠,表示消息的發(fā)送者。
- 交換機( exchanges )
在圖中為 X, 生產(chǎn)者發(fā)過來的消息需要經(jīng)過交換機虹钮,交換機將決定將消息放到哪些隊列當中聋庵。
- 隊列(queue)
隊列在圖 1 中由紅色矩形陣列表示,負責(zé)保存消息和發(fā)放消息芙粱。
- 消費者(consumer)
在圖中為 C祭玉,代表等待接收消息的程序。
信息流
- 消息是怎么從生產(chǎn)者傳遞到消費者的呢春畔?
首先脱货,生產(chǎn)者發(fā)送消息到交換機岛都,同時發(fā)送一個 key
,通過這個 key
蹭劈,交換機就知道該把消息發(fā)到哪個隊列疗绣。隨后交換機把消息發(fā)送到相應(yīng)的隊列中线召。由隊列將消息發(fā)送給消費者铺韧。消費者監(jiān)聽某些隊列,當有消息過來時缓淹,就立即處理消息哈打。
- 提問
- 交換機是如何根據(jù) key 來分配消息到隊列?
- 隊列怎樣將消息發(fā)送給消費者讯壶?
第一個問題
RabbitMQ 的交換機有四種類型:
direct
,topic
,headers
,fanout
fanout
fanout 交換機就跟廣播一樣料仗,對消息不作選擇地發(fā)給所有綁定的隊列。以圖 1 為例伏蚊,兩個隊列都將收到消息立轧。
- direct
圖 2 direct
在 direct
模式里,交換機和隊列之間綁定了一個 key
躏吊,只有消息的 key
與綁定了的 key
相同時氛改,交換機才會把消息發(fā)給該隊列。如圖 2 所示比伏,消息的 key
為 orange
時胜卤,消息將進入隊列 Q1
; key
為 black
或者 green
時,消息將進入隊列 Q2
赁项。若消息的 key
是其他字符串葛躏,被交換機直接遺棄。
圖 3 多重綁定
同時悠菜,交換機支持多重綁定舰攒,多個隊列可以以相同的 key
與交換機綁定。如圖 3 所示悔醋,當消息的 key
為 black
時摩窃,消息將進入 Q1
和 Q2
- topic
topic
模式可以理解為主題模式,當 key
包涵某個主題時篙顺,即可進入該主題的隊列偶芍。topic
模式的 key
必須具有固定的格式:以 .
作為間隔的一串單詞;比如:quick.orange.rabbit
德玫,key
最多不能超過 255byte
匪蟀。
交換機和隊列的key可以以類似正則表達式的方式存在,有兩種語法:
- ** "*" 可以替代一個單詞 **
- "#" 可以替代 0 個或多個單詞
圖4 topic
圖 4宰僧。圖中材彪,Q1
與交換機綁定的 kye
為:“*.orange.*”
,故當消息的 key
為三個單詞,且中間的單詞為 orange
時段化,消息將進入 Q1
嘁捷。Q2
與exchange
綁定的 key
為 ”rabbit.#”
,當消息的 key
以 rabbit
開頭時显熏,消息將進入 Q2
雄嚣。
- headers
官網(wǎng)沒介紹這個模式呀,大概不常用吧喘蟆。
第二個問題
圖5 Round-robin Dispatching
- 循環(huán)發(fā)放(Round-robin dispatching)
隊列分發(fā)消息給消費者的方式采用循環(huán)發(fā)放缓升。舉例來說,若隊列里有四個消息 w, x, y, z
蕴轨,則 C1
將得到消息 z
和 x
, C2
將得到消息 y
和 w
港谊。即每個消費者按順序每人發(fā)一個消息。
注意橙弱,在這種分配方式下歧寺,消息其實在剛進入隊列的時候就已經(jīng)內(nèi)定好將要被分發(fā)的消費者。即 z, x
一定是給 C1
. y, w
一定是給 C2
棘脐。
這種方式存在一些隱患斜筐,如果 z
和 x
都是耗時的命令、y
, z
都是簡單的命令荆残,C1
將不停地工作奴艾,而 C2
就比較空閑,造成資源浪費内斯。
- 公平發(fā)放(fair dispatching)
公平發(fā)放解決了上述問題蕴潦。這種方式下,隊列只會把消息給空閑的消費者俘闯。如果它看到某個消費者正忙潭苞,就查找下一個空閑消費者。
- 消息的確認(Message acknowledgment)
若沒有特別設(shè)定真朗,消息一旦被隊列分發(fā)給消費者此疹,就被 Rabbitmq
從內(nèi)存中刪除。
在這種情況下遮婶,如果將一個正在處理消息的消費者強行關(guān)閉蝗碎,那么,消息將未被完全處理旗扑,且 RabbitMQ
完全不知情蹦骑。
為了解決上述問題,可以配置使得消息處理完后臀防,向 RabbitMQ
返回一個 Acknowledgment
眠菇。RabbitMQ
直到收到Acknowledgment
后边败,才將消息刪除。
當消費者死亡時(its channel is closed, connection is closed, or TCP connection is lost)捎废,RabbitMQ
會知道這個消費者發(fā)生問題了笑窜,將重新發(fā)送消息給空閑的消費者。
消息沒有 TimeOut
登疗,即使消費者處理很長很長時間排截,乃至無窮無盡,RabbmitMQ
也認為消費者正在處理谜叹。
其實匾寝,消息的確認是默認開啟的,不需要特地設(shè)置荷腊。