前言
上一篇對(duì)RabbitMQ的流程和相關(guān)的理論進(jìn)行初步的概述,如果小伙伴之前對(duì)消息隊(duì)列不是很了解,那么在看理論時(shí)會(huì)有些困惑,這里以消息模式為切入點(diǎn),結(jié)合理論細(xì)節(jié)和代碼實(shí)踐的方式一起來學(xué)習(xí)。
正文
常用的模式有Simple、Work、Fanout、Direct、Topic、Headers,可以通過設(shè)置交換機(jī)類型和配置參數(shù)來實(shí)現(xiàn)各個(gè)模式;接下來就分別進(jìn)行實(shí)操演示吧。
以下演示都是通過管理員的賬號(hào)進(jìn)行。其實(shí)每種模式其實(shí)很大一部分操作都是一樣的,所以公共部分不會(huì)重復(fù)截圖說明,不過會(huì)針對(duì)不同的配置進(jìn)行說明。
1. 簡(jiǎn)單模式(Simple)
簡(jiǎn)單模式顧名思義就是簡(jiǎn)單,不用配置太多的東西,如下圖所示:
上圖解析:
P:表示生產(chǎn)者,負(fù)責(zé)推送消息;
C:表示消費(fèi)者,負(fù)責(zé)接收消息;
中間紅色部分:代表的是隊(duì)列(Queue);
小伙伴可能會(huì)奇怪,這里沒有交換機(jī)嗎?
其實(shí)是有的,上一篇說流程的時(shí)候,消息肯定是要通過交換機(jī)轉(zhuǎn)發(fā)到隊(duì)列中的,這里沒有指定,那是因?yàn)橛玫搅四J(rèn)的交換機(jī),具體看以下演示。
1.1 Web管理界面進(jìn)行演示
對(duì)于Web界面演示來說,只需要將消息能生產(chǎn)、投遞、消費(fèi)即可,我們不用去弄一個(gè)生產(chǎn)者和消費(fèi)者,生產(chǎn)者和消費(fèi)者都是業(yè)務(wù)處理邏輯用的,所以通常都是根據(jù)業(yè)務(wù)需求就行實(shí)現(xiàn)的;話不多說開始演示吧。
根據(jù)上圖所示,我們只需要?jiǎng)?chuàng)建一個(gè)隊(duì)列即可,然后就可以進(jìn)行消息模擬發(fā)送和消費(fèi)了。
此時(shí)并沒有指定交換機(jī)綁定,點(diǎn)擊隊(duì)列名看詳情中的Bindings,有一個(gè)默認(rèn)的交換機(jī)已經(jīng)和隊(duì)列進(jìn)行綁定:
隊(duì)列詳情頁面的說明,在上篇文章中就已經(jīng)標(biāo)注了,這里就不再贅述。
有了綁定關(guān)系之后,就可以在默認(rèn)的交換機(jī)頁面開始模擬轉(zhuǎn)發(fā)消息;首先進(jìn)入Exchanges管理頁面,點(diǎn)擊默認(rèn)交換機(jī)(AMQP default)進(jìn)入詳情開始發(fā)布消息:
消息發(fā)送成功之后就會(huì)在隊(duì)列界面看到消息情況:
隊(duì)列里面有了消息之后,就可以模擬消費(fèi)者進(jìn)行消息消費(fèi),點(diǎn)擊隊(duì)列名進(jìn)入詳情,可在詳情也模擬消費(fèi):
如上所示,簡(jiǎn)單模式整個(gè)消費(fèi)流程就通過Web頁面模擬完了。但在消費(fèi)消息時(shí),提供了Ack Mode模式(消息確認(rèn)模式)選擇來進(jìn)行消費(fèi),可選擇的模式如下:
Nack message requeue true:獲取消息,但是不會(huì)向Server做ack應(yīng)答確認(rèn)(即不告訴服務(wù)器消息被消費(fèi)了),消息重新入隊(duì)。即隊(duì)列中的消息不會(huì)被刪除掉;
Automatic Ack:獲取消息,向Server做應(yīng)答確認(rèn)(即會(huì)告訴服務(wù)器消息被消費(fèi)了),消息不重新入隊(duì),將會(huì)從隊(duì)列中刪除;
Reject requeue true:拒絕獲取消息(即拒絕處理消息),消息重新入隊(duì);
Reject requeue false:拒絕獲取消息(即拒絕處理消息),消息不重新入隊(duì),將會(huì)被刪除;
到這關(guān)于簡(jiǎn)單模式下的界面演示就結(jié)束了,其中描述的細(xì)節(jié)內(nèi)容是共用的,在其他模式下的操作也類似,后續(xù)不做重復(fù)說明。
1.2 代碼進(jìn)行演示
這里就用控制臺(tái)的方式,一步一步的實(shí)現(xiàn)。這里需要引入Nuget包:RabbitMQ.Client。生產(chǎn)者的整體代碼如下:
接下來就一步一步來調(diào)試,看看消息是怎么一步一步發(fā)出去的;
創(chuàng)建連接
剛開始沒有任何連接,如下:
代碼繼續(xù)下一步,連接就有了:
此時(shí)就可以理解為網(wǎng)絡(luò)連接上了,但通道還沒有創(chuàng)建出來,如下:
根據(jù)連接創(chuàng)建通道
通道根據(jù)連接進(jìn)行創(chuàng)建,目的是為了提高傳輸效率,共用一個(gè)連接,不然頻繁的創(chuàng)建和銷毀連接會(huì)占資源,影響性能。
定義隊(duì)列
有連接和通道之后理論就可以直接發(fā)消息了,但直接通信會(huì)相互依賴比較強(qiáng),達(dá)不到解耦合的效果。所以需要定義一個(gè)隊(duì)列將消息存放到里面,客戶端想用了自己來消費(fèi)就行,另外隊(duì)列還可以達(dá)到一定的削峰作用。
創(chuàng)建隊(duì)列的時(shí)候需要傳幾個(gè)參數(shù),分別意思如下:
參數(shù)1:queue, 隊(duì)列的名稱;
參數(shù)2:durable, 隊(duì)列是否持久化;如果為true,服務(wù)器重啟之后隊(duì)列還在,不會(huì)被清除;否則就被清掉。
參數(shù)3:exclusive ,是否排他,即是否私有的,如果為true,會(huì)對(duì)當(dāng)前隊(duì)列加鎖,其他的通道不能訪問,并且連接自動(dòng)關(guān)閉;
參數(shù)4:autodelete, 是否自動(dòng)刪除,當(dāng)最后一個(gè)消費(fèi)者斷開連接之后是否自動(dòng)刪除消息;
參數(shù)5:arguments, 用來設(shè)置隊(duì)列附加參數(shù),如設(shè)置隊(duì)列的有效期、隊(duì)列的消息生命周期、消息的最大長(zhǎng)度等;
發(fā)送消息
經(jīng)過以上步驟,就可以發(fā)送消息了,如上沒有定義交換機(jī),那就是綁定了默認(rèn)交換機(jī)。
發(fā)送時(shí)的幾個(gè)參數(shù)意思如下:
參數(shù)1:exchange,交換機(jī),這里沒有指定交換機(jī)。
參數(shù)2:routingKey,路由key,即指定隊(duì)列,簡(jiǎn)單模式下,路由key默認(rèn)就是隊(duì)列名
參數(shù)3:basicProperties, 配置其他相關(guān)屬性
參數(shù)4:body ,需要發(fā)送的消息內(nèi)容
以上的生產(chǎn)者完成了,現(xiàn)在再來一個(gè)消費(fèi)者演示一下消息消費(fèi),消費(fèi)者整體代碼如下:
效果如下:
在整個(gè)過程中,還是會(huì)先建立連接,創(chuàng)建通道,指定隊(duì)列;不同的是增加對(duì)接收數(shù)據(jù)的處理。
是不是用起來比較簡(jiǎn)單方便,主要是在復(fù)雜項(xiàng)目中,消息隊(duì)列的作用真的很大。來,接著往下說說其他模式。
2. 工作模式(Work)
工作模式是考慮到多個(gè)消費(fèi)者情況下,消息如何被消費(fèi)的,主要有兩種方案,輪詢分發(fā)和公平分發(fā);
上圖解析:
P:表示生產(chǎn)者,負(fù)責(zé)推送消息;
C1、C2:表示多個(gè)消費(fèi)者,都可以從同一個(gè)隊(duì)列接收消息;
中間紅色部分:代表的是隊(duì)列(Queue);
這兩種方式需要多個(gè)消費(fèi)者,在界面不太好模擬,所以就直接上代碼演示了。
2.1 輪詢分發(fā)
在簡(jiǎn)單模式基礎(chǔ)上稍微改動(dòng)一下代碼即可。在生產(chǎn)者中發(fā)多條消息出來,然后啟用多個(gè)消費(fèi)者就可以進(jìn)行模擬如下:
生產(chǎn)者代碼整體如下:
消費(fèi)者代碼整體如下:
兩個(gè)消費(fèi)者的代碼都是一樣,沒有變動(dòng);兩個(gè)消費(fèi)者的都是在消費(fèi)同一個(gè)隊(duì)列的消息,可以先啟動(dòng)兩個(gè)消費(fèi)者,然后在啟動(dòng)生產(chǎn)者,效果如下:
由上可見,默認(rèn)情況下其實(shí)采用的是輪詢方式。
2.2 公平分發(fā)
在實(shí)際業(yè)務(wù)中,有些業(yè)務(wù)處理比較耗時(shí),有些處理耗時(shí)不長(zhǎng),如上案例,假如奇數(shù)消息需要處理比較耗時(shí),那么對(duì)應(yīng)的消費(fèi)者就壓力比較大。這種情況可以通過公平分發(fā)的方式進(jìn)行業(yè)務(wù)處理,處理快點(diǎn)的就多處理點(diǎn)。
如何才能知道消費(fèi)者處理業(yè)務(wù)完成呢?消費(fèi)者處理完成之后主動(dòng)上報(bào)是最好不過的,所以只需要在消費(fèi)者端將自動(dòng)確認(rèn)機(jī)制改為手動(dòng)確認(rèn)即可,即:業(yè)務(wù)處理完成之后,手動(dòng)上報(bào)確認(rèn)狀態(tài)。
生產(chǎn)者的代碼不需要變動(dòng),只需要稍微改改消費(fèi)者代碼即可,這里模擬兩個(gè)不同處理能力的消費(fèi)者:
消費(fèi)者1整體代碼如下:
消費(fèi)者2整體代碼如下,主要是模擬時(shí)間不一樣:
先啟動(dòng)兩個(gè)消費(fèi)者,再啟動(dòng)生產(chǎn)者,看看消費(fèi)情況,如下:
以上演示就是公平分發(fā)模式的演示,其中有兩個(gè)關(guān)鍵的步驟:
設(shè)置每次消費(fèi)的消息條數(shù),可以根據(jù)實(shí)際業(yè)務(wù)情況配置,這里設(shè)置的是每次取一條。通過 channel.BasicQos進(jìn)行設(shè)置。
將消息確認(rèn)模式改為自動(dòng)模式,這樣就可以根據(jù)實(shí)際業(yè)務(wù)處理情況反饋確認(rèn)信息,服務(wù)器就會(huì)將消息處理掉,即刪除消息。所以一般在實(shí)際業(yè)務(wù)場(chǎng)景大都會(huì)推薦使用手動(dòng)確認(rèn)的方式,這樣避免業(yè)務(wù)未處理導(dǎo)致消息就被服務(wù)器給清掉的情況。
3. 發(fā)布訂閱模式(Fanout)
Fanout模式是一種發(fā)布訂閱模式,是一種廣播機(jī)制,不需要指定路由Key。這種模式的交換機(jī)就會(huì)將消息廣播到綁定的所有隊(duì)列上去,只要有消費(fèi)者訂閱對(duì)應(yīng)的隊(duì)列,就會(huì)收到消息。如下圖:
上圖解析:
P:表示生產(chǎn)者,負(fù)責(zé)推送消息;
X:表示交換機(jī),圖中表示一個(gè)交換機(jī)綁定了多個(gè)隊(duì)列;
C1、C2:表示多個(gè)消費(fèi)者,都可以從同一個(gè)隊(duì)列接收消息;
中間紅色部分:代表的是隊(duì)列(Queue);
在這種模式下,消息會(huì)一次性被多個(gè)消費(fèi)者消費(fèi)。
3.1 Web管理界面進(jìn)行演示
先創(chuàng)建一個(gè)Fanout模式的交換機(jī);
創(chuàng)建兩個(gè)隊(duì)列(根據(jù)實(shí)際需要?jiǎng)?chuàng)建多個(gè)),并將隊(duì)列綁定到上一步創(chuàng)建的交換機(jī)上;
這里演示就創(chuàng)建兩個(gè)隊(duì)列,分別是FanoutQ1和FanoutQ2
在隊(duì)列詳情頁或交換機(jī)詳情頁都可以進(jìn)行交換機(jī)和隊(duì)列的綁定,這里分別在FanoutQ1和FanoutQ2隊(duì)列詳情頁進(jìn)行綁定,如下:
同樣的方式綁定FanoutQ2, 綁定完成之后,可以在交換機(jī)詳情頁看到對(duì)應(yīng)的綁定隊(duì)列:
通過交換機(jī)上投遞消息,看效果;
此時(shí)通過FanoutExchange交換機(jī)投遞消息,綁定到此交換機(jī)上的隊(duì)列都能收到:
查看隊(duì)列消息情況,可以看到兩個(gè)隊(duì)列都接收到消息了。
3.2 代碼進(jìn)行演示
其實(shí)代碼和操作Web一樣,只是用代碼實(shí)現(xiàn)生產(chǎn)者和消費(fèi)者而已。
生產(chǎn)者的代碼
因?yàn)镕anout交換機(jī)不用關(guān)注RoutingKey,所以在發(fā)布消息時(shí),第二個(gè)參數(shù)不需要傳遞RoutingKey。
消費(fèi)者1的代碼
消費(fèi)者比較關(guān)注的是交換機(jī)需要和生產(chǎn)者指定的是同一個(gè),隊(duì)列和交換機(jī)有綁定。
消費(fèi)者2的代碼,其實(shí)和消費(fèi)者1基本一樣,只是定義的隊(duì)列不一樣
先啟動(dòng)消費(fèi)者,然后啟動(dòng)生產(chǎn)者,看效果
這里是控制臺(tái)程序,為了顯示方便就先啟動(dòng)消費(fèi)者,后期的生產(chǎn)者,實(shí)際應(yīng)用場(chǎng)景先啟動(dòng)誰都行。
4. 路由模式(Direct)
Direct模式是在Fanout基礎(chǔ)增加RoutingKey條件, 即交換機(jī)不會(huì)將消息現(xiàn)全部投遞到所有隊(duì)列,而是只投遞到對(duì)應(yīng)RoutingKey下的隊(duì)列。如圖:
上圖解析:
P:表示生產(chǎn)者,負(fù)責(zé)推送消息;
X:表示交換機(jī),指定類型為direct,圖中表示一個(gè)交換機(jī)綁定了多個(gè)隊(duì)列;
中間箭頭上的error、info、warning代表具體的RoutingKey;
C1、C2:表示多個(gè)消費(fèi)者,都可以從同一個(gè)隊(duì)列接收消息;
中間紅色部分:代表的是隊(duì)列(Queue);
Direct模式其實(shí)在實(shí)際應(yīng)用場(chǎng)景中用的比較多的,默認(rèn)的Exhanges也是Direct模式, 很多關(guān)于消息隊(duì)列的框架,默認(rèn)也是采用這種模式,主要原因是根據(jù)RoutingKey精確的處理對(duì)應(yīng)的業(yè)務(wù),不會(huì)由于考慮不周到,導(dǎo)致消息處理有不確定性,性能相對(duì)也不錯(cuò)。
4.1 Web管理界面進(jìn)行演示
先創(chuàng)建一個(gè)Direct模式的交換機(jī);
創(chuàng)建兩個(gè)隊(duì)列,然后將隊(duì)列綁定到上一步創(chuàng)建的交換機(jī)上,并指定對(duì)應(yīng)的RoutingKey;
創(chuàng)建隊(duì)列完成之后,還需要綁定到交換機(jī)上,上一種模式演示的是從隊(duì)列詳情中維護(hù)綁定關(guān)系,這次從交換機(jī)詳情中進(jìn)行演示,如下:
綁定第1個(gè)隊(duì)列,指定RoutingKey是order,模擬處理訂單的:
綁定第2個(gè)隊(duì)列,指定RoutingKey是msg,模擬處理消息的:
有了綁定關(guān)系,就可以測(cè)試驗(yàn)證了。
注:這里的RoutingKey可以根據(jù)實(shí)際情況隨意指定的。
向交換機(jī)上投遞消息,看效果;
模擬發(fā)布一個(gè)RoutingKey為order的消息:
再發(fā)布一個(gè)消息,指定RoutingKey為msg,如下:
兩個(gè)消息都發(fā)布成功,而是指定對(duì)應(yīng)的RoutingKey進(jìn)行投遞,所以現(xiàn)在綁定到此交換機(jī)上兩個(gè)隊(duì)列中分別有一條數(shù)據(jù),查看隊(duì)列的消息概況:
可以進(jìn)入隊(duì)列詳情,通過GetMessage獲取到具體的消息內(nèi)容,這里就不截圖了,上面已經(jīng)演示過。
4.2 代碼進(jìn)行演示
在Fanout的代碼基礎(chǔ)上稍微改動(dòng)即可,主要改動(dòng)點(diǎn)就是改變交換機(jī)的類型,并在隊(duì)列和交換機(jī)綁定時(shí)設(shè)置對(duì)應(yīng)的RoutingKey,發(fā)布消息的時(shí)候指定交換機(jī)和RoutingKey。
生產(chǎn)者代碼
消費(fèi)者1代碼,主要是綁定隊(duì)列時(shí)指定的RoutingKey為order
消費(fèi)者2代碼,主要是綁定隊(duì)列時(shí)指定的RoutingKey為msg
運(yùn)行起來看效果:
如上演示效果,和Web演示一樣,只有精確匹配到RoutingKey才能消費(fèi)到對(duì)應(yīng)的消息數(shù)據(jù)。
5. 主題模式(Topic)
Topic模式是在Direct模式基礎(chǔ)增加模糊匹配RoutingKey,Direct精確匹配RoutingKey,Topic可以通*或#進(jìn)行模糊匹配,從而把消息投遞到對(duì)應(yīng)的隊(duì)列中,如圖:
上圖解析:
P:表示生產(chǎn)者,負(fù)責(zé)推送消息;
X:表示交換機(jī),指定類型為topic,圖中表示一個(gè)交換機(jī)綁定了多個(gè)隊(duì)列;
中間箭頭上的文字代表模糊匹配的RoutingKey;其中*表示匹配RoutingKey中的一個(gè)詞,#號(hào)表示匹配RoutingKey的零個(gè)或多個(gè)詞,匹配符需要與點(diǎn)號(hào)(.)搭配使用。*.orange.test.# 示例中orange算一個(gè)詞,test算一個(gè)詞,即通過點(diǎn)號(hào)(.)分開的就稱為一個(gè)詞。
C1、C2:表示多個(gè)消費(fèi)者,都可以從同一個(gè)隊(duì)列接收消息;
中間紅色部分:代表的是隊(duì)列(Queue);
5.1 Web管理界面進(jìn)行演示
先創(chuàng)建一個(gè)Topic模式的交換機(jī);
創(chuàng)建兩個(gè)隊(duì)列,然后將隊(duì)列綁定到上一步創(chuàng)建的交換機(jī)上,并指定對(duì)應(yīng)的RoutingKey;
將隊(duì)列綁定到交換機(jī)上,這里還是在交換機(jī)詳情中進(jìn)行演示,如下:
同樣的步驟分別對(duì)TopicQ1和TopicQ2進(jìn)行規(guī)則綁定,如下:
現(xiàn)在的TopicExchange的綁定關(guān)系如下:
有了關(guān)系之后就可以進(jìn)行驗(yàn)證效果了。
向交換機(jī)上投遞消息,會(huì)根據(jù)RoutingKey的模糊匹配規(guī)則將消息投遞到對(duì)應(yīng)的隊(duì)列中,看效果;
先指定order.create.test發(fā)布消息,看看會(huì)匹配哪些隊(duì)列:
TopicQ2接收到消息,匹配到路由規(guī)則order.#
再指定RoutingKey 為order.update 發(fā)布一個(gè)消息,如下:
TopicQ1和TopicQ2都收到消息了,匹配到路由規(guī)則order.#和order.*,如下:
再指定RoutingKey 為order發(fā)布一個(gè)消息,就會(huì)匹配到order.#,這里就不截圖了。
以上測(cè)試說明:在Topic類型交換機(jī)和隊(duì)列綁定關(guān)系時(shí),可以指定RoutingKey的匹配規(guī)則,星號(hào)、#號(hào)、點(diǎn)號(hào)搭配使用,其中*表示匹配RoutingKey中的一個(gè)詞,#號(hào)表示匹配RoutingKey的零個(gè)或多個(gè)詞。
更多情況,小伙伴們自己動(dòng)手試試。
5.2 代碼進(jìn)行演示
在Direct的代碼基礎(chǔ)上稍微改動(dòng)即可,主要改動(dòng)點(diǎn)就是改變交換機(jī)的類型,并在隊(duì)列和交換機(jī)綁定時(shí)設(shè)置對(duì)應(yīng)的RoutingKey,這里的RoutingKey是一個(gè)規(guī)則,是星號(hào)、#號(hào)、點(diǎn)號(hào)和每個(gè)詞的組合,發(fā)布消息的時(shí)候指定交換機(jī)和RoutingKey,RoutingKey會(huì)去匹配綁定的規(guī)則。
生產(chǎn)者代碼
消費(fèi)者1代碼,指定路由匹配規(guī)則為order.#
消費(fèi)者2代碼,指定路由匹配規(guī)則為order.*
演示效果,將生產(chǎn)者和消費(fèi)者都啟動(dòng)
如上圖,和Web演示一樣,#號(hào)匹配0個(gè)和多個(gè)詞,*號(hào)只能匹配一個(gè)詞。 符號(hào)可以與詞任意組合,小伙伴可以根據(jù)業(yè)務(wù)情況自行發(fā)揮。
6. 參數(shù)模式(Headers)
Headers模式不是通過RoutingKey進(jìn)行匹配投遞消息,而是匹配請(qǐng)求頭中所帶的鍵值進(jìn)行消息投遞,所以創(chuàng)建隊(duì)列是需要設(shè)置綁定的頭部信息,有兩種模式:全部匹配和部分匹配。
5.1 Web管理界面進(jìn)行演示
先創(chuàng)建一個(gè)Headers模式的交換機(jī);
創(chuàng)建兩個(gè)隊(duì)列,然后將隊(duì)列綁定到上一步創(chuàng)建的交換機(jī)上,可以指定Headers的參數(shù);
將隊(duì)列綁定到交換機(jī)上,這里還是在交換機(jī)詳情中進(jìn)行演示,如下:
這里不使用RoutingKey的方式,而是通過設(shè)置參數(shù)的形式進(jìn)行綁定,后續(xù)投遞消息的時(shí)候就匹配參數(shù),如果能匹配上,就將消息投遞到對(duì)應(yīng)的隊(duì)列。
綁定HeaderQ1隊(duì)列:
同樣的方式綁定HeaderQ2隊(duì)列,只是只添加了一個(gè)鍵值對(duì),order:111,最后HeaderExchange交換機(jī)的綁定關(guān)系如下:
關(guān)系綁定好之后就可以進(jìn)行測(cè)試效果了。
向交換機(jī)上投遞消息,會(huì)根據(jù)檢查Headers參數(shù)的條件是否符合,若符合將消息投遞到對(duì)應(yīng)的隊(duì)列中,看效果;
設(shè)置兩個(gè)參數(shù)進(jìn)行發(fā)布,如下:
可以看到兩個(gè)隊(duì)列都匹配到了,因?yàn)閛rder和msg鍵值對(duì)匹配到HeaderQ1,order的鍵值對(duì)匹配到HeaderQ2,如果只設(shè)置一個(gè)order簡(jiǎn)直對(duì)呢:
此時(shí)只有HeaderQ2才能精確匹配,HeaderQ1沒有全部匹配,所以對(duì)應(yīng)隊(duì)列沒有收到消息,如下:
由此可見,在界面上沒有指定x-match綁定的話,默認(rèn)是all,就是要全部匹配才投遞消息到對(duì)應(yīng)隊(duì)列。
這里繼續(xù)新增一個(gè)HeaderQ3的隊(duì)列,創(chuàng)建方式和上面不一樣,只是在綁定交換機(jī)的時(shí)候增加x-match 為 any,如下:
綁定成功之后,現(xiàn)在關(guān)系如下,其中order的鍵值對(duì)是在每個(gè)綁定中都有,如下:
測(cè)試發(fā)消息之前,把之前消息都清空了,也就是隊(duì)列中的消息都是空的,這次我們?cè)僦付╫rder為111的參數(shù)進(jìn)行發(fā)布消息,看看有哪些隊(duì)列收到消息呢:
消息發(fā)出后,之后HeaderQ2和HeaderQ3收到消息,HeaderQ2只有一個(gè)order參數(shù),精確匹配上了,HeaderQ3有多個(gè)參數(shù),但設(shè)置了x-match為any,所以只要匹配其中一個(gè)即可。HeaderQ1多個(gè)參數(shù)需要全部匹配才行,所以沒有接收到消息:
5.2 代碼進(jìn)行演示
Headers模式是根據(jù)參數(shù)進(jìn)行匹配,不是通過RoutingKey,所以只需要在綁定隊(duì)列時(shí)設(shè)置好參數(shù),在發(fā)送消息的時(shí)候也設(shè)置好參數(shù),這樣就會(huì)根據(jù)匹配原則去匹配參數(shù),如果匹配上,消息就投遞到對(duì)應(yīng)的隊(duì)列,供消費(fèi)者進(jìn)行消費(fèi)。這里為了演示比較清晰一點(diǎn),使用一個(gè)生產(chǎn)者,三個(gè)消費(fèi)者的形式進(jìn)行演示。
生產(chǎn)者
代碼中關(guān)鍵的部分是指定交換機(jī)的類型為Headers,然后模擬了兩類參數(shù)的形式投遞消息,方便用于測(cè)試參數(shù)匹配模式的測(cè)試。
消費(fèi)者1,綁定參數(shù)為order:111和msg:222
消費(fèi)者2,和消費(fèi)者1代表基本一樣,只是綁定參數(shù)不一樣;
消費(fèi)者3,代表基本和消費(fèi)者1一樣,只是在參數(shù)指定的時(shí)候增加了x-match來指定匹配模式,這里指定為any,也就是只要其中有部分匹配上也可以消費(fèi)到消息。
演示效果,啟動(dòng)生產(chǎn)者和消費(fèi)者:
如上圖,消費(fèi)者3指定了匹配模式為部分匹配,所以可以接收到一個(gè)參數(shù)的消息,而消費(fèi)者1需要精確匹配,所以不能接收到。
關(guān)于常用的消息模式就聊到這吧,小伙伴們可以根據(jù)自己的業(yè)務(wù)場(chǎng)景進(jìn)行使用,相關(guān)演示代碼的地址如下:
碼云:https://gitee.com/CodeZoe/dot-net-core-study-demo/tree/main/RabbitMQDemo
總結(jié)
RabbitMQ提供了多種模式應(yīng)對(duì)各種業(yè)務(wù),但匹配條件越是模糊或者參數(shù)化,那性能相對(duì)比較弱。再回顧一些常用的消息隊(duì)列組件,是不是很多都是默認(rèn)使用Direct模式,精確匹配的RoutingKey可以針對(duì)具體不同業(yè)務(wù)處理,匹配性能也相對(duì)比較高;當(dāng)然其他模式小伙伴也可以針對(duì)業(yè)務(wù)情況進(jìn)行使用。
后續(xù)的文章將繼續(xù)分享RabbitMQ消息確認(rèn)機(jī)制、死信隊(duì)列、磁盤監(jiān)控等相關(guān)知識(shí)點(diǎn)的應(yīng)用,關(guān)注“Code綜藝圈”,和我一起學(xué)習(xí)吧。
----------------------------------
原文:https://mp.weixin.qq.com/s/LP_aAf_fODUPOtiikVwvTw
該文章在 2023/5/20 8:18:33 編輯過