2019年9月10日

RabbitMQ - Topic Exchange的規則,Routing Key、Binding Key差異在哪

前言

RabbitMQ支援四種Exchange,Direct、Fanout、Topic、Headers。本篇主要想聊聊Topic Exchange以及Routing Key、Binding Key用法。

Topic Exchange

Topic Exchange會跟一至多個擁有不同Binding Key的Queue綁在一起,每次有新的Message進到一個Topic Exchange時,Exchange會檢查進來的Message所夾帶的Routing Key,是否符合某些Queue的Binding Key,如果有符合的話,這個Message就會被送到那個Queue之中。

Routing Key 和 Binding Key

每個Queue會透過一組至多組Binding Key跟Exchange綁在一起,讓Exchange知道把Message塞入這個Queue的規則。基本上Binding Key可以是任意英數的組合。

每個Message都會夾帶一個Routing Key進入Exchange,Exchange會判斷這個Routing Key符合哪個Binding Key,接著將Message塞入符合的Queue中。

比如我們有兩個Queue,Binding Key分別是dog及cat,那麼當Meesage的Routing Key是dog時,這則Message就會被塞到dog queue之中,如果是cat,則會被塞到cat queue之中。

. 符號

有時候我們會希望我們的Binding Key更有意義一點,像是可以分類之類的。我們就可以把key命名成animal.doganimal.cat,利用.來區別有意義的文字。

這樣的情況,Message的Routing Key必須同樣的設定為animal.doganimal.cat,讓Exchange可以把Message塞到對應的Queue中。

* 符號

如果今天我們突然希望有一個queue,他可以接收所有animal的Message,不管是dog或是cat,我們就可以利用*符號來新增一個Binding Keyanimal.*的queue。

這種情況下,如果我們塞了一個Routing Keyanimal.dog的Message進到Exchange,那這個Message將會同時被塞到Binding Keyanimal.doganimal.*的Queue,如果新增了一種動物,Routing Keyanimal.bird,那麼這個Message就只會被塞到animal.*

或是我們想要搜集所有的dog,不管他是什麼大小、或甚至不是動物,animal.dog.bigtoy.dog.small,我們可以將Binding Key設為*.dog.*

# 符號

還有另外一個有意義的特殊符號是#,這邊先補上官網的定義:

  • * (star) can substitute for exactly one word.(可以取代掉剛好一個字詞。)

  • # (hash) can substitute for zero or more words.(可以取代掉零或多個字詞。)

所謂一個字詞,代表是.隔開的字詞:

  • animal.dog:兩個字
  • animal.dog.big:三個字
  • animaldog:一個字。

所以當我們指定一個Queue的Binding Keyanimal.#的時候,這個Queue將可以接收Routing Key為animal開頭的Message,例如:

  • animal
  • animal.dog
  • animal.dog.big
  • animal.dog.big.black

但是animal.*卻只能接收animal.doganimal.cat的Message之類的。

其他注意事項

  1. 如果一個Queue有多組Binding Key,且Message的Routing Key符合該Queue的多組Binding Key,那麼這個Message也只會被塞入這個Queue一次,不會重複塞入。

  2. 如果Message符合了Exchange中n個Queue的Binding Key的條件,那麼就會有n個一模一樣的Message分別被塞到這n個Queue中。同1,如果滿足了其中一個Queue的多個Binding Key,那還是只塞一次。

  3. 如果Message沒有滿足任何一個Quque的條件,那麼這個Message就會被丟棄。

參考

RabbitMQ tutorials - Topics