【Java】 一文搞懂 RabbitMQ 的重要概念以及安裝

王果凍ddd發表於2024-03-01

目錄

一 RabbitMQ 介紹

1.1 RabbitMQ 簡介

1.2 RabbitMQ 核心概念

1.2.1 Producer(生產者) 和 Consumer(消費者)

1.2.2 Exchange(交換器)

1.2.3 Queue(訊息佇列)

1.2.4 Broker(訊息中介軟體的服務節點)

1.2.5 Exchange Types(交換器型別)

① fanout

② direct

③ topic

④ headers(不推薦)

二 安裝 RabbitMq

2.1 安裝 erlang

2.2 安裝 RabbitMQ


一 RabbitMQ 介紹

這部分參考了 《RabbitMQ實戰指南》這本書的第 1 章和第 2 章。

1.1 RabbitMQ 簡介

RabbitMQ 是採用 Erlang 語言實現 AMQP(Advanced Message Queuing Protocol,高階訊息佇列協議)的訊息中介軟體,它最初起源於金融系統,用於在分散式系統中儲存轉發訊息。

RabbitMQ 發展到今天,被越來越多的人認可,這和它在易用性、擴充套件性、可靠性和高可用性等方面的卓著表現是分不開的。RabbitMQ 的具體特點可以概括為以下幾點:

  • 可靠性: RabbitMQ使用一些機制來保證訊息的可靠性,如持久化、傳輸確認及釋出確認等。

  • 靈活的路由: 在訊息進入佇列之前,透過交換器來路由訊息。對於典型的路由功能,RabbitMQ 己經提供了一些內建的交換器來實現。針對更復雜的路由功能,可以將多個交換器繫結在一起,也可以透過外掛機制來實現自己的交換器。這個後面會在我們將 RabbitMQ 核心概念的時候詳細介紹到。

  • 擴充套件性: 多個RabbitMQ節點可以組成一個叢集,也可以根據實際業務情況動態地擴充套件叢集中節點。

  • 高可用性: 佇列可以在叢集中的機器上設定映象,使得在部分節點出現問題的情況下佇列仍然可用。

  • 支援多種協議: RabbitMQ 除了原生支援 AMQP 協議,還支援 STOMP、MQTT 等多種訊息中介軟體協議。

  • 多語言客戶端: RabbitMQ幾乎支援所有常用語言,比如 Java、Python、Ruby、PHP、C#、JavaScript等。

  • 易用的管理介面: RabbitMQ提供了一個易用的使用者介面,使得使用者可以監控和管理訊息、叢集中的節點等。在安裝 RabbitMQ 的時候會介紹到,安裝好 RabbitMQ 就自帶管理介面。

  • 外掛機制: RabbitMQ 提供了許多外掛,以實現從多方面進行擴充套件,當然也可以編寫自己的外掛。感覺這個有點類似 Dubbo 的 SPI機制。

1.2 RabbitMQ 核心概念

RabbitMQ 整體上是一個生產者與消費者模型,主要負責接收、儲存和轉發訊息。可以把訊息傳遞的過程想象成:當你將一個包裹送到郵局,郵局會暫存並最終將郵件透過郵遞員送到收件人的手上,RabbitMQ就好比由郵局、郵箱和郵遞員組成的一個系統。從計算機術語層面來說,RabbitMQ 模型更像是一種交換機模型。

下面再來看看圖1—— RabbitMQ 的整體模型架構。

圖1-RabbitMQ 的整體模型架構

下面我會一一介紹上圖中的一些概念。

1.2.1 Producer(生產者) 和 Consumer(消費者)
  • Producer(生產者) :生產訊息的一方(郵件投遞者)

  • Consumer(消費者) :消費訊息的一方(郵件收件人)

訊息一般由 2 部分組成:訊息頭(或者說是標籤 Label)和 訊息體。訊息體也可以稱為 payLoad ,訊息體是不透明的,而訊息頭則由一系列的可選屬性組成,這些屬性包括 routing-key(路由鍵)、priority(相對於其他訊息的優先權)、delivery-mode(指出該訊息可能需要永續性儲存)等。生產者把訊息交由 RabbitMQ 後,RabbitMQ 會根據訊息頭把訊息傳送給感興趣的 Consumer(消費者)。

1.2.2 Exchange(交換器)

在 RabbitMQ 中,訊息並不是直接被投遞到 Queue(訊息佇列) 中的,中間還必須經過 Exchange(交換器) 這一層,Exchange(交換器) 會把我們的訊息分配到對應的 Queue(訊息佇列) 中。

Exchange(交換器) 用來接收生產者傳送的訊息並將這些訊息路由給伺服器中的佇列中,如果路由不到,或許會返回給 Producer(生產者) ,或許會被直接丟棄掉 。這裡可以將RabbitMQ中的交換器看作一個簡單的實體。

RabbitMQ 的 Exchange(交換器) 有4種型別,不同的型別對應著不同的路由策略direct(預設)fanout, topic, 和 headers,不同型別的Exchange轉發訊息的策略有所區別。這個會在介紹 Exchange Types(交換器型別) 的時候介紹到。

Exchange(交換器) 示意圖如下:

Exchange(交換器) 示意圖

生產者將訊息發給交換器的時候,一般會指定一個 RoutingKey(路由鍵),用來指定這個訊息的路由規則,而這個 RoutingKey 需要與交換器型別和繫結鍵(BindingKey)聯合使用才能最終生效

RabbitMQ 中透過 Binding(繫結)Exchange(交換器)Queue(訊息佇列) 關聯起來,在繫結的時候一般會指定一個 BindingKey(繫結建) ,這樣 RabbitMQ 就知道如何正確將訊息路由到佇列了,如下圖所示。一個繫結就是基於路由鍵將交換器和訊息佇列連線起來的路由規則,所以可以將交換器理解成一個由繫結構成的路由表。Exchange 和 Queue 的繫結可以是多對多的關係。

Binding(繫結) 示意圖:

Binding(繫結) 示意圖

生產者將訊息傳送給交換器時,需要一個RoutingKey,當 BindingKey 和 RoutingKey 相匹配時,訊息會被路由到對應的佇列中。在繫結多個佇列到同一個交換器的時候,這些繫結允許使用相同的 BindingKey。BindingKey 並不是在所有的情況下都生效,它依賴於交換器型別,比如fanout型別的交換器就會無視,而是將訊息路由到所有繫結到該交換器的佇列中。

1.2.3 Queue(訊息佇列)

Queue(訊息佇列) 用來儲存訊息直到傳送給消費者。它是訊息的容器,也是訊息的終點。一個訊息可投入一個或多個佇列。訊息一直在佇列裡面,等待消費者連線到這個佇列將其取走。

RabbitMQ 中訊息只能儲存在 佇列 中,這一點和 Kafka 這種訊息中介軟體相反。Kafka 將訊息儲存在 topic(主題) 這個邏輯層面,而相對應的佇列邏輯只是topic實際儲存檔案中的位移標識。 RabbitMQ 的生產者生產訊息並最終投遞到佇列中,消費者可以從佇列中獲取訊息並消費。

多個消費者可以訂閱同一個佇列,這時佇列中的訊息會被平均分攤(Round-Robin,即輪詢)給多個消費者進行處理,而不是每個消費者都收到所有的訊息並處理,這樣避免的訊息被重複消費。

RabbitMQ 不支援佇列層面的廣播消費,如果有廣播消費的需求,需要在其上進行二次開發,這樣會很麻煩,不建議這樣做。

1.2.4 Broker(訊息中介軟體的服務節點)

對於 RabbitMQ 來說,一個 RabbitMQ Broker 可以簡單地看作一個 RabbitMQ 服務節點,或者RabbitMQ服務例項。大多數情況下也可以將一個 RabbitMQ Broker 看作一臺 RabbitMQ 伺服器。

下圖展示了生產者將訊息存入 RabbitMQ Broker,以及消費者從Broker中消費資料的整個流程。

訊息佇列的運轉過程

這樣圖1中的一些關於 RabbitMQ 的基本概念我們就介紹完畢了,下面再來介紹一下 Exchange Types(交換器型別)

1.2.5 Exchange Types(交換器型別)

RabbitMQ 常用的 Exchange Type 有 fanoutdirecttopicheaders 這四種(AMQP規範裡還提到兩種 Exchange Type,分別為 system 與 自定義,這裡不予以描述)。

① fanout

fanout 型別的Exchange路由規則非常簡單,它會把所有傳送到該Exchange的訊息路由到所有與它繫結的Queue中,不需要做任何判斷操作,所以 fanout 型別是所有的交換機型別裡面速度最快的。fanout 型別常用來廣播訊息。

② direct

direct 型別的Exchange路由規則也很簡單,它會把訊息路由到那些 Bindingkey 與 RoutingKey 完全匹配的 Queue 中。

direct 型別交換器

以上圖為例,如果傳送訊息的時候設定路由鍵為“warning”,那麼訊息會路由到 Queue1 和 Queue2。如果在傳送訊息的時候設定路由鍵為"Info”或者"debug”,訊息只會路由到Queue2。如果以其他的路由鍵傳送訊息,則訊息不會路由到這兩個佇列中。

direct 型別常用在處理有優先順序的任務,根據任務的優先順序把訊息傳送到對應的佇列,這樣可以指派更多的資源去處理高優先順序的佇列。

③ topic

前面講到direct型別的交換器路由規則是完全匹配 BindingKey 和 RoutingKey ,但是這種嚴格的匹配方式在很多情況下不能滿足實際業務的需求。topic型別的交換器在匹配規則上進行了擴充套件,它與 direct 型別的交換器相似,也是將訊息路由到 BindingKey 和 RoutingKey 相匹配的佇列中,但這裡的匹配規則有些不同,它約定:

  • RoutingKey 為一個點號“.”分隔的字串(被點號“.”分隔開的每一段獨立的字串稱為一個單詞),如 “com.rabbitmq.client”、“java.util.concurrent”、“com.hidden.client”;

  • BindingKey 和 RoutingKey 一樣也是點號“.”分隔的字串;

  • BindingKey 中可以存在兩種特殊字串“”和“#”,用於做模糊匹配,其中“”用於匹配一個單詞,“#”用於匹配多個單詞(可以是零個)。

topic 型別交換器

以上圖為例:

  • 路由鍵為 “com.rabbitmq.client” 的訊息會同時路由到 Queuel 和 Queue2;

  • 路由鍵為 “com.hidden.client” 的訊息只會路由到 Queue2 中;

  • 路由鍵為 “com.hidden.demo” 的訊息只會路由到 Queue2 中;

  • 路由鍵為 “java.rabbitmq.demo” 的訊息只會路由到Queuel中;

  • 路由鍵為 “java.util.concurrent” 的訊息將會被丟棄或者返回給生產者(需要設定 mandatory 引數),因為它沒有匹配任何路由鍵。

④ headers(不推薦)

headers 型別的交換器不依賴於路由鍵的匹配規則來路由訊息,而是根據傳送的訊息內容中的 headers 屬性進行匹配。在繫結佇列和交換器時制定一組鍵值對,當傳送訊息到交換器時,RabbitMQ會獲取到該訊息的 headers(也是一個鍵值對的形式)'對比其中的鍵值對是否完全匹配佇列和交換器繫結時指定的鍵值對,如果完全匹配則訊息會路由到該佇列,否則不會路由到該佇列。headers 型別的交換器效能會很差,而且也不實用,基本上不會看到它的存在。

二 安裝 RabbitMq

透過 Docker 安裝非常方便,只需要幾條命令就好了,我這裡是只說一下常規安裝方法。

前面提到了 RabbitMQ 是由 Erlang語言編寫的,也正因如此,在安裝RabbitMQ 之前需要安裝 Erlang。

注意:在安裝 RabbitMQ 的時候需要注意 RabbitMQ 和 Erlang 的版本關係,如果不注意的話會導致出錯,兩者對應關係如下:

RabbitMQ 和 Erlang 的版本關係

2.1 安裝 erlang

1 下載 erlang 安裝包

在官網下載然後上傳到 Linux 上或者直接使用下面的命令下載對應的版本。

[root@SnailClimb local]#wget http://erlang.org/download/otp_src_19.3.tar.gz

erlang 官網下載:Downloads - Erlang/OTP

2 解壓 erlang 安裝包

[root@SnailClimb local]#tar -xvzf otp_src_19.3.tar.gz

3 刪除 erlang 安裝包

[root@SnailClimb local]#rm -rf otp_src_19.3.tar.gz

4 安裝 erlang 的依賴工具

[root@SnailClimb local]#yum -y install make gcc gcc-c++ kernel-devel m4 ncurses-devel openssl-devel unixODBC-devel

5 進入erlang 安裝包解壓檔案對 erlang 進行安裝環境的配置

新建一個資料夾

[root@SnailClimb local]# mkdir erlang

對 erlang 進行安裝環境的配置

[root@SnailClimb otp_src_19.3]# 
./configure --prefix=/usr/local/erlang --without-javac

6 編譯安裝

[root@SnailClimb otp_src_19.3]# 
make && make install

7 驗證一下 erlang 是否安裝成功了

[root@SnailClimb otp_src_19.3]# ./bin/erl

執行下面的語句輸出“hello world”

 io:format("hello world~n", []).

輸出“hello world”

大功告成,我們的 erlang 已經安裝完成。

8 配置 erlang 環境變數

[root@SnailClimb etc]# vim profile

追加下列環境變數到檔案末尾

#erlang
ERL_HOME=/usr/local/erlang
PATH=$ERL_HOME/bin:$PATH
export ERL_HOME PATH

執行下列命令使配置檔案profile生效

[root@SnailClimb etc]# source /etc/profile

輸入 erl 檢視 erlang 環境變數是否配置正確

[root@SnailClimb etc]# erl

輸入 erl 檢視 erlang 環境變數是否配置正確

2.2 安裝 RabbitMQ

1. 下載rpm

wget https://www.rabbitmq.com/releases/rabbitmq-server/v3.6.8/rabbitmq-server-3.6.8-1.el7.noarch.rpm

或者直接在官網下載

Installing on RPM-based Linux | RabbitMQ

2. 安裝rpm

rpm --import https://www.rabbitmq.com/rabbitmq-release-signing-key.asc

緊接著執行:

yum install rabbitmq-server-3.6.8-1.el7.noarch.rpm

中途需要你輸入"y"才能繼續安裝。

3 開啟 web 管理外掛

rabbitmq-plugins enable rabbitmq_management

4 設定開機啟動

chkconfig rabbitmq-server on

4. 啟動服務

service rabbitmq-server start

5. 檢視服務狀態

service rabbitmq-server status

6. 訪問 RabbitMQ 控制檯

瀏覽器訪問:http://你的ip地址:15672/

預設使用者名稱和密碼: guest/guest;但是需要注意的是:guestuest使用者只是被容許從localhost訪問。官網文件描述如下:

“guest” user can only connect via localhost

解決遠端訪問 RabbitMQ 遠端訪問密碼錯誤

新建使用者並授權

[root@SnailClimb rabbitmq]# rabbitmqctl add_user root root
Creating user "root" ...
[root@SnailClimb rabbitmq]# rabbitmqctl set_user_tags root administrator
​
Setting tags for user "root" to [administrator] ...
[root@SnailClimb rabbitmq]# 
[root@SnailClimb rabbitmq]# rabbitmqctl set_permissions -p / root ".*" ".*" ".*"
Setting permissions for user "root" in vhost "/" ...

再次訪問:http://你的ip地址:15672/ ,輸入使用者名稱和密碼:root root

RabbitMQ控制檯

 

相關文章