RabbitMQ 是目前非常熱門的一款消息中間件,不管是互聯網行業還是傳統行業都在大量的使用 。 RabbitMQ 憑藉其高可靠、易擴展、高可用及豐富的功能特性受到越來越多企業的青睞。作爲一個合格的開發者,有必要深入地瞭解 RabbitMQ 的相關知識,爲自己的職業生涯添磚加瓦 。
RabbitMQ
RabbitMQ 是一個實現了 AMQP 的開源消息中間件,使用高性能的 Erlang 編寫。 RabbitMQ 具有可靠性、支持多種協議、高可用、支持消息集羣以及多語言客戶端等特點,在分佈式系統中存儲轉發消息,具有不錯的性能表現。
AMQP
AMQP (Advanced Message Queuing Protocol,高級消息隊列協議)是一個線路層的協議規範, 而不是 API 規範(例如 JMS)。由於 AMQP 是一個線路層協議規範,因此它天然就是跨平臺的, 就像 SMTP、 HTTP 等協議一樣,只要開發者按照規範的格式發送數據,任何平臺都可以通過 AMQP 進行消息交互。像目前流行的 StormMQ、 RabbitMQ 等都實現了 AMQP。
安裝Rabbit MQ
Docker安裝
在Docker Hub官網查詢rabbitmq版本信息,安裝一個帶有web管理界面的rabbitmq:Docker Hub官網Rabbit MQ版本頁面
拉取鏡像
docker pull rabbitmq:3.8.0-management
運行rabbitmq容器
首先在宿主機創建好映射目錄rabbitmq,然後創建好data目錄,並且要賦予足夠的權限
賦予足夠的權限
chown -R 1000 [rabbitmq|目錄]
運行容器
執行如下命令時,當前所在目錄一定要在rabbitmq,因爲下面代碼有用到pwd命令。
docker run -d --name rabbitmq \
-p 5672:5672 -p 15672:15672 \
-v $PWD/data:/var/lib/rabbitmq \
--hostname chenfu-admin \
-e RABBITMQ_DEFAULT_VHOST=my_vhost \
-e RABBITMQ_DEFAULT_USER=chenfu \
-e RABBITMQ_DEFAULT_PASS=chenfu \
rabbitmq:3.8.0-management
參數解析
- -d:後臺運行
- –name:容器名稱
- -p:端口映射
- -v:宿主機目錄映射
- –hostname:主機名(RabbitMQ的一個重要注意事項是它根據所謂的 “節點名稱” 存儲數據,默認爲主機名)
- -e:指定環境變量(RABBITMQ_DEFAULT_VHOST:默認虛擬機名;RABBITMQ_DEFAULT_USER:默認的用戶名;RABBITMQ_DEFAULT_PASS:默認用戶名的密碼)
查看容器是否運行成功
docker ps
訪問並登錄rabbitmq的web界面
非Docker安裝
參考博客:centos7安裝Rabbit MQ
主要參考博客:RabbitMQ安裝參考博客
系統環境Cent OS 7.5 Mini
安裝步驟
預裝環境
yum install gcc glibc-devel make ncurses-devel openssl-devel autoconf
yum install unixODBC unixODBC-devel
安裝erlang
wget http://erlang.org/download/otp_src_19.3.tar.gz
解壓並進入其目錄
tar -zxvf otp_src_19.3.tar.gz
cd otp_src_19.3
設置目錄
./configure --prefix=/usr/local/erlang --enable-smp-support
編譯安裝【這個過程,巨慢!打把王者先。。。】
make && make install
ln -s /usr/local/erlang/bin/erl /usr/local/bin/
安裝校驗
輸入如下命令,會顯示出erlang的安裝目錄
whereis erlang
安裝過程出現問題,可以參考這篇文章:erlang安裝教程及常見問題
安裝Rabbit MQ
wget http://www.rabbitmq.com/releases/rabbitmq-server/v3.6.1/rabbitmq-server-generic-unix-3.6.1.tar.xz
解壓縮xz文件
tar -xvf rabbitmq-server-generic-unix-3.6.1.tar.xz
啓動和關閉命令
關閉
./rabbitmq-server stop
啓動
./rabbitmq-server start
或者
./rabbitmq-server -detached
查看狀態
./rabbitmq-server status
配置Rabbit MQ網頁插件
首先創建目錄,否則可能報錯:
mkdir /etc/rabbitmq
啓用插件
./rabbitmq-plugins enable rabbitmq_management
放行端口
配置linux 端口 15672 網頁管理 5672 AMQP端口
firewall-cmd --permanent --add-port=15672/tcp
firewall-cmd --permanent --add-port=5672/tcp
重啓防火牆
systemctl restart firewalld.service
創建賬號
./rabbitmqctl add_user chenfu chenfu
設置權限
./rabbitmqctl set_permissions -p / chenfu ".*" ".*" ".*"
修改角色
./rabbitmqctl set_user_tags chenfu administrator
Rabbit MQ相關概念
RabbitMQ 整體上是一個生產者與消費者模型,主要負責接收、存儲和轉發消息。可以把消息傳遞的過程想象成:當你將一個包裹送到郵局,郵局會暫存並最終將郵件通過郵遞員送到收件人的手上, RabbitMQ 就好比由郵局、郵箱和郵遞員組成的一個系統。從計算機術語層面來說,RabbitMQ 模型更像是一種交換機模型。
Rabbit MQ模型架構
生產者和消費者
Producer: 生產者,就是投遞消息的一方。
生產者創建消息,然後發佈到 RabbitMQ 中。消息一般可以包含 2 個部分:消息體和標籤(Label)。消息體也可以稱之爲 payload,在實際應用中,消息體一般是一個帶有業務邏輯結構的數據,比如一個 JSON 字符串。當然可以進一步對這個消息體進行序列化操作。消息的標籤用來表述這條消息 , 比如一個交換器的名稱和一個路由鍵。 生產者把消息交由 RabbitMQ, RabbitMQ 之後會根據標籤把消息發送給感興趣的消費者(Consumer)。
Consumer: 消費者, 就是接收消息的一方。
消費者連接到 RabbitMQ 服務器,並訂閱到隊列上。當消費者消費一條消息時,只是消費消息的消息體(payload)。在消息路由的過程中,消息的標籤會丟棄,存入到隊列中的消息只有消息體,消費者也只會消費到消息體,也就不知道消息的生產者是誰,當然消費者也不需要知道。
Broker: 消息中間件的服務節點。
對於 RabbitMQ 來說,一個 RabbitMQ Broker 可以簡單地看作一個 RabbitMQ 服務節點,或者 RabbitMQ 服務實例。大多數情況下也可以將一個 RabbitMQ Broker 看作一臺 RabbitMQ 服務器。
Queue: 隊列,是 RabbitMQ 的內部對象,用於存儲消息。
RabbitMQ 中消息都只能存儲在隊列中,RabbitMQ 的生產者生產消息並最終投遞到隊列中,消費者可以從隊列中獲取消息並消費。多個消費者可以訂閱同一個隊列,這時隊列中的消息會被平均分攤(Round-Robin,即輪詢)給多個消費者進行處理,而不是每個消費者都收到所有的消息井處理。
RabbitMQ 不支持隊列層面的廣播消費,如果需要廣播消費,需要在其上進行二次開發,處理邏輯會變得異常複雜,同時也不建議這麼做。
交換器、路由鍵、綁定
Exchange: 交換器
生產者將消息發送到 Exchange (交換器,通常也可以用大寫的 “X” 來表示),由交換器將消息路由到一個或者多個隊列中。如果路由不到,或許會返回給生產者,或許直接丟棄。這裏可以將 RabbitMQ 中的交換器看作一個簡單的實體。
RabbitMQ 中的交換器有四種類型,不同的類型有着不同的路由策略
交換器類型
RabbitMQ 常用的交換器類型有 fanout、 direct、 topic、 headers 這四種。 AMQP 協議裏還提到另外兩種類型: System 和自定義。
fanout
它會把所有發送到該交換器的消息路由到所有與該交換器綁定的隊列中。
direct
direct 類型的交換器路由規則也很簡單,它會把消息路由到那些 BindingKey 和 RoutingKey全匹配的隊列中。
topic
前面講到 direct 類型的交換器路由規則是完全匹配 BindingKey 和 RoutingKey,但是這種嚴格的匹配方式在很多情況下不能滿足實際業務的需求。 topic 類型的交換器在匹配規則上進行了擴展,它與 direct 類型的交換器相似,也是將消息路由到 BindingKey 和 RoutingKey 相匹配的隊列中,但這裏的匹配規則有些不同,它約定:
*:匹配單個字母或數字
#:匹配0~多個字母或數字
RoutingKey: 路由鍵
生產者將消息發給交換器的時候, 一般會指定一個 RoutingKey,用 來指定這個消息的路由規則,而這個 RoutingKey 需要與交換器類型和綁定鍵 (BindingKey) 聯合使用才能最終生效。
在交換器類型和綁定鍵 (BindingKey) 固定的情況下,生產者可以在發送消息給交換器時,通過指定 RoutingKey 來決定消息流向哪裏。
Binding: 綁定
RabbitMQ 中通過綁定將交換器與隊列關聯起來,在綁定的時候一般會指定一個綁定鍵 (BindingKey),這樣 RabbitMQ 就知道如何正確地將消息路由到隊列了。
生產者將消息發送給交換器時, 需要一個 RoutingKey,當 BindingKey 和 RoutingKey 相匹配時,消息會被路由到對應的隊列中。在綁定多個隊列到同一個交換器的時候,這些綁定允許使用相同的 BindingKey。而且BindingKey 並不是在所有的情況下都生效,它依賴於交換器類型,比如 fanout 類型的交換器就會無視 BindingKey,而是將消息路由到所有綁定到該交換器的隊列中 。