RabbitMQ 基本介紹、安裝教學

By 古古 2020/11/18 Other Tech

RabbitMQ 是在各企業中最為廣泛使用的 message queue,而在 RabbitMQ 的世界裡面有三個角色,分別是 Producer、Queue、Consumer

  • Producer : 負責將 message 發送到 Queue 裡
  • Queue : 負責暫存 message
  • Consumer : 負責去 Queue 中消費 message

RabbitMQ 常見的五種模式

在 RabbitMQ 中,常見的五種模式如下,詳情也可參照官網

  1. Direct 模式
  2. Worker 模式
  3. Publish/Subscribe 模式
  4. Routing 模式
  5. Topics 模式

有關如何在 SpringBoot 中使用 RabbitMQ 的這五種模式,可以參考我的另一篇文章 SpringBoot - RabbitMQ 使用方法

1. Direct 模式

最簡單的模式,只會有一個 Producer 負責發送 message 到 Queue 裡、而也只有一個 Consumer 去 Queue 裡消費 message

2. Worker 模式

跟 Direct 模式很像,但是差別是 Worker 模式中會 同時 有多個 Consumer 會去消費 Queue 裡的 message,增加 message 消化的速率(一個人做很慢,大家一起做就很快)

Worker 模式是滿常用的一種模式,通常是用在大量 asynchronous job 的處理上,可以想像成 n 個 Consumer 就是一堆 Worker or Thread,一起幫忙消化 message

在現在 microservice 很流行的情形下,如果有大量的 asynchronous job 要執行,通常就不會使用 Java 裡的 ThreadPool,而是會改使用這種 Worker 模式,讓許多台 node 可以一起幫忙做

3. Publish/Subscribe 模式

從這個模式之後,在 Producer、Queue、Consumer 之間就多了一個叫做 Exchange 的東西出現,所以以後 Producer 不再是直接把 message 丟到 Queue 裡,而是讓 Producer 把 message 丟給 Exchange,再交由 Exchange 去決定要把這個 message 丟給哪個 Queue

Exchange 自己就有三種 type,用來表示要用什麼樣的規則把 message 丟到想要丟的 Queue 裡面

  • direct
  • fanout
  • topic

在 Publish/Subscribe 模式中,使用的是 Exchange 的 fanout type,當 Producer 把 message 丟給 Exchange 時,Exchange 會把這個 message 丟到他綁定的所有 Queue 上

Publish/Subscribe 模式也是一個滿常用的模式,通常是用在需要訂閱的情況下

譬如說當訂單服務有了一筆新訂單之後就要去通知簡訊服務、商品服務…等,那如果是用前面提到的 RabbitMQ 中的 Direct 模式,則在訂單服務裡就要自己指定要把這個 message 丟到哪個 Queue 上,這樣以後如果又有新的服務要來訂閱這個 message 的話,就還得要回去改訂單服務的 code

但如果是使用這個 Publish/Subscribe 模式的話,訂單服務就可以直接將 message 丟給 Exchange,而我們只要把新的服務專屬的 Queue 和 Exchange 綁定一下,這樣子 Exchange 就可以自動把 message 也丟到新的 Queue 裡了,我們就不需要再去改 code

4. Routing 模式

Routing 模式也是一個用到了 Exchange 的模式,這個模式使用的是 Exchange 的 direct type

當 Producer 把 message 丟給 Exchange 時,同時要在這個 message 上面帶上一個 routing key,而 Exchange 就會根據這個 routing key,將 message 丟到指定的 Queue 上

乍看之下 Routing 模式和 Direct 模式很像,而且甚至會覺得 Routing 模式有點多餘,因為既然是透過 routing key 來決定要將這個 message 丟到哪個 Queue 上,那我就在 code 裡自己寫 if/else 來決定要丟到哪個 Queue 就好了啊,根本不用經過 Exchange,所以就會像下面這樣

String routingKey = "...";
if (routingKey.equals("orange")) {
    sendMessageToQ1();
} else if (routingKey.equals("black") || routingKey.equals("green")) {
    sendMessageToQ2();
}

但是 Routing 模式之所以有它存在的意義,重點就在於他可以 多重綁定,也就是說同一個 routing key 可以綁到 n 個 Queue 上,而不是一對一的綁定

所以我們就可以用一個 Exchange,將 info, error, warning routing key 綁到一般的 log queue上,然後可以再將 error routing key 綁到另一個 error log queue 上,這樣就可以做出一個帶有全部 log 的 Queue、以及一個只包含 error log 的 Queue

不過這種模式要慎用,因為他的重要邏輯都在 Exchange 上,所以如果是對 RabbitMQ 不熟的新手,從 code 中會看不出來原來還有這種用法,只會知道 Producer 把 message 丟給 Exchange,但卻不知道為什麼 log Queue 和 error log Queue 中卻都會有 message 出現

5. Topics 模式

用到了 Exchange 的 topic type,用法基本上跟 Routing 模式一樣,只是 routing key 進化成可以使用模糊綁定而已

RabbitMQ 安裝教學

需要先安裝 docker-desktop,可以到 Docker 官網下載 https://www.docker.com/products/docker-desktop

可以使用 docker 在自己的電腦上快速架設起 RabbitMQ 以及 RabbitMQ 專屬的 Web 管理介面

推薦使用 rabbitmq:management 的 docker image,不僅可以幫我們架設起一個 RabbitMQ,還可以順便為我們架設起一個用來管理該 RabbitMQ 的 web 管理介面,非常方便

執行以下方法,就可以順利啟動這個 docker image

docker run --name rabbitmq -d -p 15672:15672 -p 5672:5672 \ 
-e RABBITMQ_DEFAULT_USER=root -e RABBITMQ_DEFAULT_PASS=admin1234 \
rabbitmq:management

在上面的方法中,可以自己修改 RABBITMQ_DEFAULT_USERRABBITMQ_DEFAULT_PASS 的參數去自定義帳號密碼,像是此處就是設定帳號為 root、密碼為 admin1234

啟動好 docker image 之後,RabbitMQ 使用的 port 默認是 5672,而 RabbitMQ 的 Web 管理介面使用的 port 默認是 15672,因此只要訪問 http://localhost:15672,就會出現 RabbitMQ 的 Web 管理介面,此時就可以在輸入剛剛運行 docker image 所設定的帳號密碼登入進去

到這裡 RabbitMQ 就安裝好了,所以就可以使用 SpringBoot 連接上此 RabbitMQ 了

Web 管理介面導覽

登入之後就會進到 Overview 頁面,在 Overview 頁面可以查看 Queue 的整體狀況以及 cluster node 的 cpu/memory 使用狀態

點擊上方的 Exchanges tab 可以進到 Exchanges 頁面,可以查看目前已存在的 Exchange,以及新增一個新的 Exchange

點擊其中一個已存在的 Exchange,可以查看該 Exchange 的詳細資訊

點擊上方的 Queue tab 可以進到 Queue 頁面,可以查看目前已存在的 Queue,也可以新增一個新的 Queue

同理,點擊其中一個已存在的 Queue,可以查看該 Queue 的詳細資訊,也可以對該 Queue 進行一系列的操作(跟 Exchange 的操作差不多,這裡就不列了)

點擊上方的 Admin tab 可以進到 Admin 頁面,然後在 Admin 裡點擊右側的 Users tab,可以查看/新增 RabbitMQ 的使用者,也可以查看該使用者允許 access 的 virtual host

點擊右側的 Virtual Hosts tab,可以查看/新增 RabbitMQ 的 virtual host

補充: 在 RabbitMQ 裡面有一個 virtual host 的概念,可以想像成是分組,也就是一個 virtual host 就是一組

當 RabbitMQ 運行時,預設會產生一個 virtual host 叫做 /,然後如果不特別調整的話,所有的 Queue 都是創建在這個 / 的 virtual host 裡面,而 user 預設也是被設定成能存取 /

所以如果想要在 RabbitMQ 裡面做分組的權限控管的話,只要多創建幾個 virtual host,user 就可以在不同的 virtual host 下創建 Queue 和 Exchange,不同 virtual host 裡的 Queue 和 Exchange 無法互通,然後也可以去限制說某些 user 只能存取某些 virtual host