RabbitMQ入門看這一篇就夠了

一文搞懂 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 官網下載:http://www.erlang.org/downloads

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

或者直接在官網下載

https://www.rabbitmq.com/install-rpm.html

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控制臺

作者:Snailclimb
鏈接:RabbitMQ 入門
來源:gitee

?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容