交換器(Exchange)是什麼?
當訊息寫入RabbitMQ時,並非直接將訊息寫入佇列中,而是透過交換器(Exchange)將訊息正確分派到佇列中,而依據就是訊息自帶的RouteKey是否與BindKey相符合;若完全沒有符合的佇列,則會自動遺棄該訊息。
交換器有哪幾種?
常用的交換器有四種 Direct, Fanout, Topic and Headers.
- Direct: 預設的模式,即直接將訊息分配到 RouteKey 與 BindKey 完全相同的佇列上。
Case1: BindKey: “log.info“
log.debug -> 不符合
log.info -> 符合
log.infomation -> 不符合 - Fanout: 顧名思義就是將此訊息分配到每一個佇列上,等於是複製了n次。若設定fanout的話會自動忽略 BindKey與RouteKey。
Topic: Topic是較常用也是靈活度最高的模式,有點像是.net的routing概念,只要符合規格的RouteKey就會被傳遞到正確的queue。
特殊符號分別是: * (一個任意字)與 # (零以上個任意字)。Case1:
1
2
3
4
5BindKey: "*I.am.*"
I.am.boy -> 符合
I.am.girl -> 符合
I.amNot.girl -> 不符合
I.am.boy.too ->不符合Case2:
1
2
3
4BindKey "#.strong"
He.is.strong -> 符合
Not.strong -> 符合
I.am.not.strong.neither -> 不符合Headers: 從訊息中的header與BindKey做批配比較,並寫入queue中。這部分我也很少用,之後有特別研究再來補上怎麼使用。
使用上的效能當然還是 fanout > direct > topic,但我認為除非在很極端的狀況下,否則比較這個的意義並不大,畢竟工具的使用還是以符合需求為主。
另一點要注意的是RouteKey長度限制為255 bytes。
Fanout模式的演示
首先我們在宣告Exchange時將type指定為 “fanout”,當然在訂閱端也是需要的,程式碼一樣就不再貼上。
1 | channel.ExchangeDeclare(exchange: "logs", type:"fanout"); |
其他部分沒有改變,將專案建置好後,開啟兩個訂閱者程式,然後執行Sender.exe以fanout模式送出一個訊息,就可以看到兩個視窗幾乎同時收到該訊息,且進行處理。
程式範例檔
完整的範例檔放在這 範例,有興趣的可以自行下載。