在之前的章節中我們改進了我們的日志系統,我們使用direct型交換器代替了隻能盲目廣播消息的fanout型交換器,這使得我們可以有選擇性地接收日志。
盡管使用direct型交換器改進了我們的日志系統,但它仍然有缺陷——它不能基于多個規則或标準進行路由。
在我們的系統中,我呢也許希望訂閱的不僅僅是嚴重級别的日志,而且基于日志發送方。你可能了解過systool這個unix工具,該工具不僅能路由嚴重級别的日志(info、warn、crit等),并且具有各種能力(授權、定時等)。
這将會給我們很多靈活性——我們可能希望不但接收那些來自定時器的錯誤日志而且接收來自核心子產品的。
為在我們的日志系統實作這個,我們還需要再學習一個更加複雜的交換器類型——Topic型交換器。
發送到Topic型交換器的消息不能包含任意路由鍵——它必須是一串字元并且以圓點符号隔開。這些字元可以是任意的,但它們通常都會指定成連結的消息的某些功能。一些有效的路由鍵如:"stock.usd.nyse", "nyse.vmw", "quick.orange.rabbit"等,路由鍵可以包括
任意多個字元,上限是255個位元組長度。
綁定鍵也必須使用類似的形式。topic型交換器的邏輯和direct型很相像——消息發送時會指定一個特别的路由鍵,并且會被路由到所有與綁定鍵相比對的隊列。不過對綁定鍵有兩種特殊類型:
*符号用來代替任意單詞
#符号可以代替0個或多個單詞
用一個例子簡單地解釋下:

這個例子中,我們準備發送一些描述動物的消息,這些消息被發送的時候路由鍵都是包含三個單詞并且以圓點符号分開(總共兩個圓點符),路由鍵的訂單第一個單詞用來描述速度,第二個是顔色,第三個是物種:
"<speed>.<colour>.<species>"。
我們建立3種綁定:Q1和綁定鍵"*.orange.*"綁定,Q2和"*.*.rabbit" 、"lazy.#"分别綁定。這些綁定描述如下:
Q1隻對所有橙色的動物感興趣
Q2希望收到所有兔子的消息及一切懶惰的動物的
使用路由鍵"quick.orange.rabbit"的消息将發送至Q1和Q2,"lazy.orange.elephant"的也是一樣。另一方面,使用路由鍵"quick.orange.fox"的消息将僅被路由Q1,"lazy.brown.fox"僅被路由到Q2。"lazy.pink.rabbit"的消息僅僅會被路由到Q2一次,盡管它比對了
兩種綁定關系,"quick.brown.fox""quick.brown.fox"沒有綁定任何關系所有該消息将會被丢棄。
可是如果我們背棄”約定”直接發送一個單詞或者四個單詞會怎麼樣?比如:"orange" or "quick.orange.male.rabbit",當然了,第一個不會比對任何綁定,直接被丢棄。
另一方面四個單詞的會比對第二種,是以它會被路由到第二個隊列中。
備注:
Topic型交換器比較強大跟其它交換器很相似。
當一個隊列以”#”作為綁定鍵時,它将接收所有消息,而不管路由鍵如何,類似于fanout型交換器。
當特殊字元”*”、”#”沒有用到綁定時,topic型交換器就好比direct型交換器了。
揉在一起
我們将在我們的日志系統中使用topic型交換器。我們假設日志的路由鍵僅由兩部分單詞組成:"<facility>.<severity>"。
emit_log_topic.go源代碼如下:
receive_logs_topic.go端代碼如下:
接收所有log:
接收facility為kern的消息:
僅接收所有critical的消息:
同時建立多個綁定:
發送路由鍵為kern.critical的消息:
具體效果如下:
接收所有:
接收kern:
接收critical:
同時接收kern、critical:
無效綁定(這裡接收不到消息):
發送端:
至此,topic型交換器就over了,topic型交換器相比direct的單對單,fanout型的廣播式,topic型靈活性更大,稍作修改綁定鍵及路由鍵即可實作以上兩種交換器類型,簡直了!