RabbitMQ下的生产消费者模式与订阅发布模式
所謂模式,就是在某種場景下,一類問題及其解決方案的總結(jié)歸納。生產(chǎn)消費(fèi)者模式與訂閱發(fā)布模式是使用消息中間件時常用的兩種模式,用于功能解耦和分布式系統(tǒng)間的消息通信,以下面兩種場景為例:
-
數(shù)據(jù)接入?
??假設(shè)有一個用戶行為采集系統(tǒng),負(fù)責(zé)從App端采集用戶點擊行為數(shù)據(jù)。通常會將數(shù)據(jù)上報和數(shù)據(jù)處理分離開,即App端通過REST API上報數(shù)據(jù),后端拿到數(shù)據(jù)后放入隊列中就立刻返回,而數(shù)據(jù)處理則另外使用Worker從隊列中取出數(shù)據(jù)來做,如下圖所示。
??這樣做的好處有:第一,功能分離,上報的API接口不關(guān)心數(shù)據(jù)處理功能,只負(fù)責(zé)接入數(shù)據(jù);第二,數(shù)據(jù)緩沖,數(shù)據(jù)上報的速率是不可控的,取決于用戶使用頻率,采用該模式可以一定程度地緩沖數(shù)據(jù);第三,易于擴(kuò)展,在數(shù)據(jù)量大時,通過增加數(shù)據(jù)處理Worker來擴(kuò)展,提高處理速率。這便是典型的生產(chǎn)消費(fèi)者模式,數(shù)據(jù)上報為生產(chǎn)者,數(shù)據(jù)處理為消費(fèi)者。 -
事件分發(fā)?
??假設(shè)有一個電商系統(tǒng),那么,用戶“收藏”、“下單”、“付款”等行為都是非常重要的事件,通常后端服務(wù)在完成相應(yīng)的功能處理外,還需要在這些事件點上做很多其他處理動作,比如發(fā)送短信通知、記錄用戶積分等等。我們可以將這些額外的處理動作放到每個模塊中,但這并不是優(yōu)雅的實現(xiàn),不利于功能解耦和代碼維護(hù)。?
??我們需要的是一個事件分發(fā)系統(tǒng),在各個功能模塊中將對應(yīng)的事件發(fā)布出來,由對其感興趣的處理者進(jìn)行處理。這里涉及兩個角色:A對B感興趣,A是處理者,B是事件,由事件處理器完成二者的綁定,并向消息中心訂閱事件。服務(wù)模塊是后端的業(yè)務(wù)邏輯服務(wù),在不同的事件點發(fā)布事件,事件經(jīng)過消息中心分發(fā)給事件處理器對應(yīng)的處理者。整個流程如下圖所示。這邊是典型的訂閱發(fā)布模式。
??可以看到,生產(chǎn)消費(fèi)者模式與訂閱發(fā)布模式都離不開消息中間件來作為消息中轉(zhuǎn)站,開源的消息中間件有很多,各有優(yōu)劣。本文將重點探討RabbitMQ的特性,以及如何實現(xiàn)上述的兩種場景。
RabbitMQ核心概念
??如果你只是想使用一下RabbitMQ,那么參考官方教程修改一下就可以跑起來了,很簡單。如果你有一些概念上的疑惑,不妨與筆者一起來總結(jié)一下RabbitMQ的核心概念。
-
通信方式?
??RabbitMQ是基于AMQP協(xié)議來實現(xiàn)的消息中間件。AMQP,類似于HTTP協(xié)議,也是一個應(yīng)用層的協(xié)議,網(wǎng)絡(luò)層使用TCP來通信。因此,RabbitMQ也是典型的C-S模型,準(zhǔn)確地說是C-S-C模型,因為伴隨著RabbitMQ的使用,總是會有Producer與Consumer兩個Client和一個Broker Server。
??Client要與Server進(jìn)行通信,就必須先建立連接,RabbitMQ中有Connection與Channel兩個概念,前者就是一個TCP連接,后者是在這個連接上的虛擬概念,負(fù)責(zé)邏輯上的數(shù)據(jù)傳遞,因此,為了節(jié)省資源,一般在一個客戶端中建立一個Connection,每次使用時再分配一個Channel即可。 -
消息體?
??Message是RabbitMQ中的消息體概念。類似HTTP傳輸中,有header和body兩部分?jǐn)?shù)據(jù),Message中也有Attributes和Payload兩部分?jǐn)?shù)據(jù),前者是一些元信息,后者是傳遞的消息數(shù)據(jù)實體。 -
消息投遞?
??Exchange、Queue與Routing Key三個概念是理解RabbitMQ消息投遞的關(guān)鍵。RabbitMQ中一個核心的原則是,消息不能直接投遞到Queue中。Producer只能將自己的消息投遞到Exchange中,由Exchange按照routing_key投遞到對應(yīng)的Queue中,具體的架構(gòu)參見下圖。細(xì)細(xì)品味就會體會到這樣設(shè)計的精妙之處。
??那么,具體實現(xiàn)時,如何完成這三者關(guān)系的綁定?總結(jié)起來是兩點:第一,在Consumer Worker中,聲明自己對哪個Exchange感興趣,并將自己的Queue綁定到自己感興趣的一組routing_key上,建立相應(yīng)的映射關(guān)系;第二,在Producer中,將消息投遞一個Exchange中,并指明它的routing_key。由此可見,Queue這個概念只是對Consumer可見,Producer并不關(guān)心消息被投遞到哪個Queue中。?
??看過RabbitMQ的”Hello World”教程的童鞋可能會發(fā)現(xiàn)在那里面的圖中并沒有看到Exchange和routing_key的蹤跡,但這并不意味著RabbitMQ可以支持直接將消息投遞到Queue中,而是在內(nèi)部使用了默認(rèn)的Exchange和routing_key了。默認(rèn)情況下,RabbitMQ使用名稱為“amq.direct”的Direct Exchange,routing_key默認(rèn)名字與Queue保持一致。?
??搞清楚上述概念,就不難理解Exchange的四種類型了。Direct、Fanout、Topic、Headers,區(qū)別在于如何將消息從Exchange投遞到Queue中。Direct使用具體的routing_key來投遞;Fanout則忽略routing_key,直接廣播給所有的Queue;Topic是使用模糊匹配來對一組routing_key進(jìn)行投遞;Headers也是忽略routing_key,使用消息中的Headers信息來投遞。 -
消息可靠性?
??不同于HTTP的同步訪問,RabbitMQ中,Producer并不知道消息是否被可靠地投遞到了Consumer中處理。那么,RabbitMQ是如何保證消息的可靠投遞?主要是兩點:第一,消息確認(rèn)機(jī)制。Consumer處理完消息后,需要發(fā)送確認(rèn)消息給Broker Server,可以選擇“確認(rèn)接收”、“丟棄”、“重新投遞”三種方式。如果Consumer在Broker Server收到確認(rèn)消息之前掛了,Broker Server便會重新投遞該消息。第二,可以選擇數(shù)據(jù)持久化,這樣即使RabbitMQ重啟,也不會丟失消息。
生產(chǎn)消費(fèi)者模式
??搞清楚了RabbitMQ的核心概念,要針對特定的場景來設(shè)計使用方案就很簡單了,基本上就是上述RabbitMQ架構(gòu)圖的變遷。讓我們先來看看文章開頭提到的“數(shù)據(jù)接入”場景,如何實現(xiàn)生產(chǎn)消費(fèi)者模式。?
??這里增加了一下場景復(fù)雜度:對于上報的數(shù)據(jù),如果是special的行為,需要優(yōu)先處理。從上圖可以看到,數(shù)據(jù)上報端負(fù)責(zé)將數(shù)據(jù)投遞到RabbitMQ對應(yīng)的Exchange,并指明routing_key是common還是special。數(shù)據(jù)處理端,可以根據(jù)情況啟多個Woker來消費(fèi)數(shù)據(jù),但至少需要兩個,一個用來處理common數(shù)據(jù),一個用來處理special的數(shù)據(jù)。注意:當(dāng)需要增加多個Worker來消費(fèi)同一類數(shù)據(jù)時,需要保持Queue名字一致,比如上面的Common數(shù)據(jù)。
訂閱發(fā)布模式
??再來看“事件分發(fā)”的場景,架構(gòu)如下圖所示,使用event name/id來作為RabbitMQ的routing key的名字。Event Processor 01對event 01 和event 02感興趣,則在啟動Consumer Worker時,將自己的Queue綁定到這兩個routing key上即可,其他Event Processor也是如此,這樣便完成了事件的訂閱。當(dāng)有事件發(fā)布時,消息便會按照event name/id被投遞到對應(yīng)的Queue中。?
??由此可見,在不同的應(yīng)用中,變化的只是routing_key與Consumer Queue的綁定關(guān)系,在充分理解RabbitMQ的核心概念后處理這些應(yīng)該也是得心應(yīng)手了。
出處:http://blog.csdn.net/zwgdft/article/details/53561277
總結(jié)
以上是生活随笔為你收集整理的RabbitMQ下的生产消费者模式与订阅发布模式的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 中国工商银行信用卡可以修改账单日吗
- 下一篇: 哔哩哔哩b币有什么用