四. RabbitMQ路由解析

什麼是路由呢?就和你們家裏的路由器是一個概念,路由器就是把網絡信號做轉發、那麼RabbitMQ中的路由,就是把消息做轉發;

RabbitMQ一共提供了四種路由:

Ø Direct類型

Ø Fanout類型

Ø Topic類型

Ø Header類型

 

 

01Direct類型的路由:

上一篇文章中寫的RabbitMQ的基本應用案例中使用的Exchange就是direct類型的,direct類型的exchange路由規則很簡單:

exchange在和queue進行binding時會設置routingkey(爲了避免和下邊的routingKey混淆,很多時候把這裏的routingKey叫做BindingKey)

 

channel.QueueBind(queue:"Q1",exchange:"myexchange",routingKey:"orange");將消息發送到Broker時會設置對應的routingkey:channel.BasicPublish(exchange:"myexchange",routingKey:"orange",basicProperties: null, body: body);

 

只有RoutingKey和BindingKey完全相同時,exchange纔會把消息路由到綁定的queue中去

 

我們知道了direact類型的交換機只有routingKey和bindingKey相同的時候纔會進行消息路由,根據這一特點我們可以通過routingKey將消息路由到不同的queue中。如在進行日誌處理時,需求是所有的日誌都保存到文本文件,出現錯誤日誌時則還需要短信通知以便及時處理。

 

我們可以創建兩個隊列:只接收錯誤日誌的log_error隊列和接收所有日誌信息的log_all隊列。消費者C1處理log_error隊列中消息,將這些消息通過短信通知管理員,消費者C2處理log_all隊列的信息,將這些信息記錄到文本文件。如下圖所示:

 

生產者用於發送日誌消息,代碼下圖所示:

如果圖片不清晰,請關注朝夕net社區微信公衆號獲取視頻錄播

 

消費者C1用於處理log_error隊列中的消息,錯誤消息進行短信通知,代碼如下:

 

消費者C2用於處理log_all隊列中的消息,所有消息記錄到文本文件中,代碼下圖所示:

生產者,消費者同時運行起來,結果如圖6:

 

 

02 Fonout類型的路由:

fanout類型的exchange路由規則是最簡單的,交換機會把消息廣播到與該Exchange綁定的所有queue中,即所有和該exchange綁定的隊列都會收到消息。fanout類型exchange和隊列綁定時不需要指定routingKey,即使指定了routingKey也會被忽略掉。路由結構如下圖:

fanout類型交換機主要用於發佈/訂閱的一些場景,如用戶註冊了我們的網站後,我們通過短信和郵件兩種方式通知用戶;

 

代碼如下圖:

這裏通過代碼簡單演示將消息同時使用短信和郵件兩種方式通知用戶的流程。首先聲明一個fanout類型的exchange,然後聲明兩個隊列 SMSqueue和EMAILqueue,這兩個隊列都和這個exchange綁定。消費者1處理EMAILqueue的消息,通過郵件方式發送通知;消費者2處理SMSqueue的消息通過短信方式發送通知。

生產者代碼:

 

消費者1將EMAILqueue的消息通過郵件方式發送通知,代碼如下圖:

      消費者2將SMSqueue的消息通過短信方式發送通知,代碼如下圖:

 

啓動這三個應用程序,執行結果如下圖

03 Topic類型的路由:

topic類型exchange的路由規則也是基於routingKey和bindingKey的,其路由過程和direct類型基本一致,兩者的區別在於direct類型的exchange要求routingKey和bindingKey必須相同才進行將消息路由到綁定的queue中,而topic類型的bindingKey是一個匹配規則,只要routingKey符合bindingKey的規則就可以將消息路由到綁定的queue中去,結構如下圖所示。

 

注意routingKey和bindingKey的結構都是一系列由點號連接單詞的字符串。

例如【aaa.bbb.ccc】bindingKey的兩個特殊符號:*表示一個單詞,#表示0或多個單詞(注意是單詞,而不是字符)。如下圖,usa.news和usa.weather都和usa.#匹配,而usa.news和europe.news都和#.news匹配。如下圖所示;

代碼實現如下圖所示:這裏使用代碼實現上圖中的例子,爲了方便我們只定義兩個隊列:接收美國相關信息的usaQueue(bindingKey是usa.#)和接收新聞消息的newsQueue(bindingKey是#.news)。然後定義兩個消費者,消費者1處理useaQueue的消息,消費者2處理newsQueue的消息。

 

生產者代碼:如下圖所示

然後我這裏提供有多個消費者。

 

消費者1代碼如下圖,只處理usaQueue中的消息

 

消費者2代碼如下圖,只處理newsQueue中的消息:

生成者發送的四條消息中,消息1的routingKey爲usa.news,同時符合usaQueue的bindingKey(usa.#)和newsQueue的bindingKey(#.news),所以消息1同時路由到兩個隊列中;消息2的routingKey爲usa.weather只符合usa.#,發送到usaQueue;消息的rouKey爲europe.news,只符合#.news,發送到newsQueue中;消息4的routingKey爲europe.weahter,和兩個隊列的bindingKey都不符合,所以被丟棄。執行這三個Console應用程序,結果如下圖。

注:一點補充:topic類型交換機十分靈活,可以輕鬆實現direct和fanout類型交換機的功能。如果綁定隊列時所有的bindingKey都是#,則交換機和fanout類型交換機表現一致;如果所有的bindingKey都不包含*和#,則交換機和direct類型交換機表現一致。

04 Header類型的路由:

Hearder路由是一種比較特別的路由,header類型路由規則和上邊的幾種exchange都不一樣,header類型exchange不是通過routingKey進行路由的,而是通過Headers。exchange在和queue進行binding時可以設置arguments:如下圖所示;

 將消息發送到exchange時可以設置消息的Header:如下圖

user和pass是普通的鍵值對,我們也可以設置其他的鍵值對。x-match是一個特殊的屬性,當x-match爲all時,aguments和basicProrperties.Headers的所有鍵值對都相等時纔會路由到queue(AND關係);

當x-match爲any時,aguments和basicProrperties.Headers的鍵值對只要有一個相同就可以路由到queue(OR關係)。

 

下面給大家展示兩個案例:創建兩個隊列Allqueue和Anyqueue,其中Allqueue和exchange綁定時的x-match爲all,Anyqueue和exchange綁定時的x-match爲any;然後發送兩條消息。

發送第一條消息時basicProperties.Headers中的user和pass都和綁定隊列時的agruments的user和pass相等,發送第二條消息是兩者的pass不相等,代碼如下圖(內容較多,分兩張圖展示):

 

執行程序,打開WebUI管理界面,結果如下,我們看到只有user和pass都相等時消息纔會路由到Allqueue;user和pass只要有一個相等就會路由到Anyqueue,如圖

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章