rabbitmq學習筆記
- 2019 年 10 月 4 日
- 筆記
rabbitMQ學習筆記
2017年12月31日星期日 Lee
環境:centos7
版本:rabbitmq-server-3.7.2-1
準備了3台主機做實驗。先配置hosts如下。
cat /etc/hosts
192.168.5.71 node1
192.168.5.72 node72
192.168.5.73 node73
0、基礎知識
建議看下美團分享的rabbitmq基礎:http://mp.weixin.qq.com/s/OABseRR0BnbK9svIPyLKXw
AMQP三個組件:交換器、隊列、綁定
處理流程:消息 —> 交換器 —> Client
交換器的4種類型:
direct 根據路由鍵投遞消息
fanout 廣播方式,綁定到同一個exchange上的queue都能收到同樣的msg。不需要路由鍵,如果接受到消息的Exchange沒有與任何Queue綁定,則消息會被拋棄
topic 根據queue定義的topic名稱來接收相應的msg
header (很少用,直接忽略它)
虛擬主機vhost:
每個vhost相當於一個mini的rabbitmq服務器,有獨立的權限控制機制。不同的vhost可以存在同名的交換器和隊列名。
在rabbitmq中,權限控制是以vhost為單位的。
rabbitmqctl [add_vhost|delete_vhost] vhost1 即可添加/刪除一個名為vhost1的虛擬主機
消息確認機制:
RabbitMQ提供了transaction、confirm兩種消息確認機制。
transaction即事務機制,手動提交和回滾;
confirm機制提供了Confirmlistener和waitForConfirms兩種方式。
confirm機制效率明顯會高於transaction機制,但transaction的優勢在於強一致性。如果沒有特別的要求,建議使用conrim機制。
1、從實驗來看,消息的確認機制只是確認publisher發送消息到broker,由broker進行應答,不能確認消息是否有效消費。
2、而為了確認消息是否被發送給queue,應該在發送消息中啟用參數mandatory=true,使用ReturnListener接收未被發送成功的消息。
3、接下來就需要確認消息是否被有效消費。publisher端目前並沒有提供監聽事件,但提供了應答機制來保證消息被成功消費,應答方式:
basicAck:成功消費,消息從隊列中刪除
basicNack:requeue=true,消息重新進入隊列,false被刪除
basicReject:等同於basicNack
basicRecover:消息重入隊列,requeue=true,發送給新的consumer,false發送給相同的consumer
發送方確認機制:
客戶端發送請求(消息)時,在消息的屬性(Message Properties,在AMQP協議中定義了14種properties,這些屬性會隨着消息一起發送)中設置兩個值replyTo(一個Queue名稱,用於告訴服務器處理完成後將通知我的消息發送到這個Queue中)和correlationId(此次請求的標識號,服務器處理完成後需要將此屬性返還,客戶端將根據這個id了解哪條請求被成功執行了或執行失敗)。服務器端收到消息處理完後,將生成一條應答消息到replyTo指定的Queue,同時帶上correlationId屬性。客戶端之前已訂閱replyTo指定的Queue,從中收到服務器的應答消息後,根據其中的correlationId屬性分析哪條請求被執行了,根據執行結果進行後續業務處理。
erlang節點:
erlang類似JVM,erlang節點能自動嘗試啟動所在節點的應用程序。
1、單機版搭建及rabbitmq參數詳解
在node1上執行如下的操作步驟:
yum localinstall rabbitmq-server-3.7.2-1.el7.noarch.rpm erlang-19.3.6.5-1.el7.centos.x86_64.rpm -y
rpm -qpl rabbitmq-server-3.7.2-1.el7.noarch.rpm | less 可以列出rabbitmq的軟件釋放文件路徑,如下:
/etc/rabbitmq
/usr/lib/rabbitmq/
/var/lib/rabbitmq
cp /usr/share/doc/rabbitmq-server-3.7.2/rabbitmq.config.example /etc/rabbitmq/
cd /etc/rabbitmq/
mv rabbitmq.config.example rabbitmq.config
vim rabbitmq.config 開啟部分注釋後,具體取消注釋的地方如下:
[
{rabbit,
[
{tcp_listeners, [5672]},
{loopback_users, []}
]}
].
systemctl start rabbitmq-server 或者使用rabbitmq-server -detached 這種啟動方式
常用命令:
rabbitmqctl status 列出rabbitmq的運行狀態,版本信息等非常多的運行參數
列出隊列情況
[root@node1 /root ]# rabbitmqctl list_queues
Timeout: 60.0 seconds …
Listing queues for vhost / …
查看當前exchanges的情況
[root@node1 /root ]# rabbitmqctl list_exchanges
Listing exchanges for vhost / …
amq.fanout fanout
amq.match headers
amq.direct direct
amq.rabbitmq.log topic
amq.topic topic
amq.rabbitmq.trace topic
amq.headers headers
direct
查看bingding,剛安裝服務的時候也沒有binding
[root@node1 /root ]# rabbitmqctl list_bindings
Listing bindings for vhost /…
列出用戶
[root@node1 /root ]# rabbitmqctl list_users
Listing users …
guest [administrator]
列出vhosts
[root@node1 /root ]# rabbitmqctl list_vhosts
Listing vhosts …
/
添加用戶
[root@node1 /root ]# rabbitmqctl add_user ops 123456
Adding user "ops" …
修改密碼
[root@node1 /root ]# rabbitmqctl change_password ops 12345678
設置用戶權限
[root@node1 /root ]# rabbitmqctl set_user_tags ops administrator
Setting tags for user "ops" to [administrator] …
刪除用戶(會連帶這個賬戶相關的訪問控制條目都刪掉)
[root@node1 /root ]# rabbitmqctl delete_user ops
Deleting user "ops" …
列出有哪些插件
[root@node1 /root ]# rabbitmq-plugins list
安裝管控頁面【web管理頁面】
rabbitmq-plugins enable rabbitmq_management
卸載插件
rabbitmq-plugins disable xxxxx
停止rabbitmq程序及節點(erlang)
rabbitmqctl stop
單獨停止rabbitmq
rabbitmqctl stop_app
停止遠程節點:
rabbitmqctl stop -n rabbit@[remote_hostname]
啟動rabbitmq-server後執行rabbitmq-plugins enable rabbitmq_management安裝web管理插件,然後在瀏覽器訪問
http://192.168.5.71:15672/
默認用戶名和密碼都是guest

單節點很少用,因此這裡一些命令就不說了, 統一放到後面集群環境下說。
2、三節點集群版
在node72和node73上安裝rabbitmq,啟動rabbitmq進程,然後安裝好rabbitmq_management插件。
rpm包安裝的rabbitmq在 /var/lib/rabbitmq/ 路徑下,有一個 .erlang.cookie的文件。
在node1上執行:
cd /var/lib/rabbitmq/
chmod u+w .erlang.cookie
scp .erlang.cookie root@node72:/var/lib/rabbitmq/
scp .erlang.cookie root@node73:/var/lib/rabbitmq/
然後執行 rabbitmqctl cluster_status 可以看到cluster_name 集群的名稱。

在3台主機都上執行:
rabbitmqctl stop // 執行這個命令確保rabbitmq進程是停止狀態的
rabbitmq-server -detached // 使用-detached參數後台啟動tabbitmq
然後在node72和node73上執行如下命令,將其加入到node1的集群環境中:
rabbitmqctl stop_app
rabbitmqctl reset // (可選)第一次加入集群的新主機的話,建議執行下reset這個命令 清空節點的狀態
rabbitmqctl join_cluster rabbit@node1
rabbitmqctl start_app
這時候,再到node1上執行rabbitmqctl cluster_status 可以看到集群running node信息

再web節目也有顯示了:

3、rabbitmq的鏡像隊列
3.1 配置鏡像隊列:
在任意一個節點上執行:
rabbitmqctl set_policy ha-all "^" '{"ha-mode":"all"}' -p /
這個命令會將/ 這個vhost的所有隊列設置為鏡像隊列,即隊列會被複制到各個節點,各個節點狀態保持一致。
rabbitmqctl add_vhost vh4
rabbitmqctl set_policy ha-all "^" '{"ha-mode":"all"}' -p vh4
這個命令會將vh4 這個vhost的所有隊列設置為鏡像隊列,即隊列會被複制到各個節點,各個節點狀態保持一致。
至此,RabbitMQ 高可用集群就已經搭建好了,最後一個步驟就是搭建均衡器
3.2 查看vhost名為vh3的全部鏡像隊列是否同步完成:
rabbitmqctl list_queues name pid slave_pids synchronised_slave_pids -p vh3

如上圖,兩個紅色框內的信息一模一樣,說明所有的slave隊列里的數據都同步了。這樣的話,我們才能放心的剔除某個節點且保證數據不丟失。
3.3 鏡像隊列節點宕機的情況:
如果鏡像隊列丟失了一個從節點,則對任何消費者都不會有影響。
主節點宕機,集群內部會重新選主。消費者需要重新附加到主隊列。
4、修改某個節點為內存節點
rabbitmq要求集群中至少一個磁盤節點【為了提高性能,不需要全部節點都是disc的節點】,所以我們可以啟動部分節點為RAM模式
當節點加入或者離開集群時,他們必須通知到至少一個磁盤節點。
如果集群內就1個磁盤節點,其餘都是內存節點。如果這個唯一的一個磁盤節點宕機了,那麼集群還是可以路由消息的。但是這個時候不支持如下操作:
創建隊列、創建交換器、創建綁定、添加用戶、更改權限、添加或刪除集群節點
以node72、node73為例。
step1、將node72 、node73從集群中移除
在node72上執行:
rabbitmqctl stop_app
rabbitmqctl reset
然後,執行下面命令,將節點再次加回集群中:
rabbitmqctl join_cluster –ram rabbit@node1 // 說明:我們也可以在一開始搭建集群的時候,就用 –ram參數添加節點
rabbitmqctl start_app
再次查看集群狀態,如下圖:

5、rabbitmq的負載均衡
可以使用Haproxy、Nginx做4層負載均衡,如果使用的是阿里雲環境 還可以直接使用使用阿里雲的SLB服務。
6、rabbitmq的運行參數說明
配置文件: /etc/rabbitmq/rabbitmq.config
部分參數:
{vm_memory_high_watermark, 0.4} 控制rabbitmq允許消耗的內存占宿主機內存的的百分比。
{msg_store_file_size_limit, 16777216} 控制rabbitmq垃圾收集存儲內容之前,消息存儲數據庫的最大大小。默認16MB
{queue_index_max_journal_entries, 32768} 在轉儲到消息存儲數據庫並提交前,消息存儲日誌中的最大條目數,默認32768條
具體的運行參數還有很多,官方文檔都有很詳細的說明,其實我們一般要改的參數也不多。
7、rabbitmq的ACL權限控制


例子:
[root@node1 /root ]# rabbitmqctl add_user ops 123456 — 添加一個普通賬號ops
[root@node1 /root ]# rabbitmqctl add_vhost vhost1 — 添加一個虛擬主機vhost1
[root@node1 /root ]# rabbitmqctl set_permissions -p vhost1 ops ".*" ".*" ".*" — 給ops賬戶的vhost1虛擬主機授權:配置、寫、讀 的權限。.*表示匹配任意隊列和交換器
[root@node1 /root ]# rabbitmqctl list_permissions -p vhost1 — 列出vhost1當前開放的權限:
Listing permissions for vhost "vhost1" …
ops .* .* .*
[root@node1 /root ]# rabbitmqctl set_permissions -p vhost2 ops "coupons-queue-.*" ".*" ".*"
[root@node1 /root ]# rabbitmqctl list_permissions -p vhost2
Listing permissions for vhost "vhost2" …
ops coupons-queue-.* .* all
在rabbitmq的web控制台,看到的ops賬戶的權限如下:


[root@node1 /root ]# rabbitmqctl clear_permissions -p vhost1 ops — 刪除vhost1虛擬主機上ops賬號的權限
[root@node1 /root ]# rabbitmqctl clear_permissions -p vhost2 ops — 刪除vhost2虛擬主機上ops賬號的權限
8、其他管理類命令
說明:下面的命令實驗的結果,是因為我在rabbitmq的web界面執行了一些入隊、bind等系列操作後的結果
列出vhost1虛擬主機的全部隊列情況(name、messages、consumers、memory情況)
[root@node1 /root ]# rabbitmqctl list_queues -p vhost1 name messages consumers memory
Timeout: 60.0 seconds …
Listing queues for vhost vhost1 …
msg-inbox-errors 7 0 55760
檢查vhost1虛擬主機的隊列屬性
[root@node1 /root ]# rabbitmqctl list_queues -p vhost1 name durable auto_delete
Timeout: 60.0 seconds …
Listing queues for vhost vhost1 …
msg-inbox-errors true false — 可以看出隊列是持久化的,未設置自動刪除
查看交換器和綁定情況
[root@node1 /root ]# rabbitmqctl list_exchanges -p vhost1
Listing exchanges for vhost vhost1 …
amq.topic topic
amq.headers headers
amq.match headers
amq.direct direct
amq.rabbitmq.trace topic
amq.fanout fanout
direct
查看rabbitmq默認交換器的屬性設置
[root@node1 /root ]# rabbitmqctl list_exchanges name type durable auto_delete
Listing exchanges for vhost / …
amq.fanout fanout true false
direct true false
amq.rabbitmq.trace topic true false
amq.rabbitmq.log topic true false
amq.topic topic true false
amq.headers headers true false
amq.direct direct true false
amq.match headers true false
查看綁定信息
[root@node1 /root ]# rabbitmqctl list_bindings -p vhost1
Listing bindings for vhost vhost1…
exchange msg-inbox-errors queue msg-inbox-errors []
exchange q1 queue q1 []
amq.fanout exchange q1 queue []
test_change exchange msg-inbox-errors queue []
## 上面的q1、msg-inbox-errors隊列是我在rabbitmq管理界面手動綁定的。test_change是我人工創建的一個交換器
顯示broker的狀態
rabbitmqctl environment
查看rabbitmq的運行詳情(結果特別細緻)
rabbitmqctl status
列出consumer
list_consumers
列出channel
list_channels
列出連接信息
list_connections
9、rabbitmq的日誌
默認日誌文件的路徑是 /var/log/rabbitmq/
rabbitmq的啟動日誌類似下圖這樣:

此外,這個文件還記錄了執行了哪些的管理操作,連接建立及斷開等很多運行狀態情況。
切割日誌命令:
rabbitmqctl rotate_logs

10、其他:
rabbitmqctl reset命令:
reset 命令在節點為單機狀態和是集群的一部分時行為有點不太一樣。
節點單機狀態時,reset 命令將清空節點的狀態,並將其恢復到空白狀態。當節點是集群的一部分時,該命令也會和集群中的磁盤節點通信,告訴他們該節點正在離開集群。
這很重要,不然,集群會認為該節點出了故障,並期望其最終能夠恢復回來,在該節點回來之前,集群禁止新的節點加入。


11、rabbitmq的heartbeat
官方文檔:http://www.rabbitmq.com/heartbeats.html
https://www.cnblogs.com/Tommy-Yu/p/5775852.html
http://blog.csdn.net/jiao_fuyou/article/details/23186407
http://www.linuxidc.com/Linux/2014-01/95715.htm
心跳案例:http://holys.im/2016/09/20/why-rabbitmq-message-not-consumed/
心跳超時間隔
The heartbeat timeout value defines after what period of time the peer TCP connection should be considered dead by RabbitMQ and client libraries. This value is negotiated between the client and RabbitMQ server at the time of connection. The client must be configured to request heartbeats. In RabbitMQ versions 3.0 and higher, the broker will attempt to negotiate heartbeats by default (although the client can still veto them). The timeout is in seconds, and default value is 60 (580 prior to release 3.5.5).
心跳超時值決定了tcp相互連接的最大時間, 超過了這個時間, 該連接即被RMQ和客戶端視為丟失(dead)。 這個值在客戶端和服務器建立連接的時候協商確定。客戶端需配才能發心跳包。 RMQ3.0及以上版本, RMQ將試着將beatheart協調為默認值(客戶端可以否決這個值)。 超時時間單位為秒,默認值為60( 3.5.5發佈版之前是580)。
Heartbeat frames are sent about every timeout / 2 seconds. After two missed heartbeats, the peer is considered to be unreachable. Different clients manifest this differently but the TCP connection will be closed. When a client detects that RabbitMQ node is unreachable due to a heartbeat, it needs to re-connect.
心跳包每半個超時時間發送一次。 丟失了兩個心跳包, 連接被認為不可抵達。 不同的客戶端有不同的提示, 但tcp連接都會被關閉。 當客戶端檢測到RMQ節點不可抵達(根據心跳判定), 它需要重新連接(到服務器)。
Heartbeats can be disabled by setting the timeout interval to 0. This is not a recommended practice.
心跳機制可以被禁用:設定超時間隔為0。但是不建議這樣設置。
12、rabbitmq的插件
級聯複製:rabbitmq_shovel插件(用在跨IDC間的複製,一般情況下,用的很少)
安裝方法:
rabbitmq-plugins enable rabbitmq_shovel
rabbitmq-plugins enable rabbitmq_shovel_management
13、rabbitmq的HTTP API
官方介紹很詳細。這裡略過。
14、rabbitmqadmin命令行工具介紹
官方文檔:http://www.rabbitmq.com/management-cli.html
wget https://raw.githubusercontent.com/rabbitmq/rabbitmq-management/v3.7.2/bin/rabbitmqadmin
chmod +x rabbitmqadmin
mv rabbitmqadmin /usr/local/bin
rabbitmqadmin –help
rabbitmqadmin -V "/" list queues

rabbitmqadmin -V "/" list exchanges

在默認的vhost / 下面 創建一個名為cli_test的exchange
rabbitmqadmin -V "/" -u guest -p guest declare exchange name=cli_test type=topic
列出連接列表
rabbitmqadmin list connections names
關閉消費者
rabbitmqadmin close connection name="127.0.0.1:11111"
15、rabbitmq的監控
1、使用 zabbix監控。
2、prometheus的監控的配置部署稍有複雜(需要在rabbitmq上額外的安裝plugin)。
3、使用rabbitmq自帶的REST API來採集監控(監控配置項的正確性,如是否配置了持久化、是否配置了鏡像隊列)
