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