這裏主要想整理關於消息隊列rabbitmq可能遇到問題,躺一躺其中的坑,而後在團隊沉澱下來,最終變爲整個團隊的技術能力,而後寫着寫着發現,官方文檔寫的都比較詳細也比較好,因此抽取一些比較有價值的連接和和整理一些實際上遇到的問題和處理心得,因此這裏分享出來,設計到的連接可能會相對較多。html
這裏假設用戶已經對rabbitmq有所瞭解,若是不瞭解,能夠先按照這個方式來測試消息隊列,如何使用該消息隊列(官方也有完整的示例)。前端
rabbitmq是一種普遍應用於互聯網的消息隊列,是一種異步的消息隊列,支持多種消息協議,支持多種開發語言,支持多種隊列集羣化方式cluster和federation,還有完善的受權機制,集羣管理和支持各類插件。node
認爲比較值得看的內容:mysql
我認爲比較重要的幾個內容linux
列舉幾個對集羣管理相對重要的:git
一些環境變量配置:
github
注意: 這裏提到的負載均衡器是4層的負載均衡,使用輪訓的方式將請求轉發給後端,能夠假設爲haproxy, lvsweb
環境:
node: rabbitmq-01, rabbitmq-02, rabbitmq-03
queue: 存在節點爲非鏡像隊列
前端負載均衡器: TCP --> rabbitmq-01/rabbitmq-02/rabbitmq-03
需求:
2個節點須要下架,更換新的節點
rabbitmq-02 ---> rabbitmq-02-new
rabbitmq-03 ---> rabbitmq-03-new
操做:
業務低峯期將rabbitmq-02-new,rabbitmq-03-new join到集羣節點,而後刪除rabbitmq-01, rabbitmq-02
複製代碼
開發人員推薦使用代碼中建立(rabbitmq3.0後不支持...3.0後都是create ha) | 這裏略坑-- --sql
queue_args={"x-ha-policy" : "all"}
channel.queue_declare{queue="hello-queue", arguments=queue_args}
複製代碼
腦裂: 腦裂問題是分佈式系統中最多見的問題,指在一個高可用(HA)系統中,當聯繫着的兩個節點斷開聯繫時,原本爲一個總體的系統,分裂爲兩個獨立節點,這時兩個節點開始爭搶共享資源,結果會致使系統混亂,數據損壞。對於無狀態服務的HA,無所謂腦裂不腦裂;但對有狀態服務,數據相關服務(好比MySQL,消息隊列)的HA,必需要嚴格防止腦裂。(但有些生產環境下的系統按照無狀態服務HA的那一套去配置有狀態服務,結果可想而知...),有一些存儲系統像數據庫,kv存儲都已經有很好的一致性協議解決了raft paxos協議解決了,這裏咱們須要格外注意這裏的腦裂處理流程。docker
腦裂帶來的最大問題就是分區問題,分區在rabbitmq中有三種配置模式ignore(默認方式), pause_minority, autoheal
這裏只測試ignore, pause_minority
環境:
node: rabbitmq-01, rabbitmq-02, rabbitmq-03
queue: 鏡像隊列
前端負載均衡器: TCP --> rabbitmq-01/rabbitmq-02/rabbitmq-03
複製代碼
設置C-->B不能互通
複製代碼
iptables -I INPUT -s {NODEX} -j REJECT 這裏是表明涉及節點關閉某個ip數據包的流入
而後查看一下集羣運行狀態,顯示已經存在分區partitions
[{nodes,
[{disc,
['rabbit@rabbitmq-test001','rabbit@rabbitmq-test002',
'rabbit@rabbitmq-test003']}]},
{running_nodes,['rabbit@rabbitmq-test003']},
{cluster_name,<<"rabbit@rabbitmq-test001">>},
{partitions,
[{'rabbit@rabbitmq-test003',
['rabbit@rabbitmq-test001','rabbit@rabbitmq-test002']}]},
{alarms,[{'rabbit@rabbitmq-test003',[]}]}]
複製代碼
對應與web上看,相互檢測失敗,相互顯示爲not running
雖然ABC C-->A -->B能夠通,都能邏輯互通,局部不互通仍是會出現 分區
注意點: 這時候很是重要的一點是負載均衡器存在一個較大的隱患,就是ABC互通存在問題,不過負載均衡器可以正常鏈接到ABC,那麼請求仍是會按照正常的邏輯走,這裏就容易產生數據不一致。(因爲rabbitmq沒有實現相似raft的分佈式協議,因此這一點很重要),這就是rabbitmq集羣默認分區方式ignore最大的問題,它不會自動處理,也不會有集羣選舉的功能,須要咱們自身手動去處理集羣,去選擇信任的分區模式,這裏必定要格外注意,稍有差池就會致使集羣狀態數據異常。
選擇一個你信任的分區,而後重啓全部其餘分區的節點,而後從新加入節點,注意其餘分區節點的數據會被丟掉.
而後重啓全部節點恢復警告
默認模式下,會致使腦裂,丟數據,還須要手工處理,對系統可靠性要求較高的場景必定不能使用,同時運維起來會比較麻煩,成本較高,這是系統默認的配置方式,請必定根據自身場景進行配置。
設置C-->B不能互通
複製代碼
這裏不會出現分區,pause_minority
贊: 這時候會有網絡分區模式會自動關閉異常節點,負載均衡器也會報警,這樣安全級別會較高,當節點<1/2 節點也會正常服務,當從新加入集羣而後數據也能正常恢復。
rabbitmq已經一個使用普遍的消息隊列,設計模式相對完善,也在移動互聯網中已經被大量應用,可能正式因爲這樣緣由,rabbitmq有太多可配置的功能選項和隱藏配置了,因此考慮了各類各樣的適用應用場景,因此若是咱們在生產環境使用,須要對它進行一個全方面的學習和掌握,針對自身的環境進行集羣配置和集羣調優。
列舉幾條本身用的相對自動的搭建流程吧,搭建3集羣rabbitm-server
## 安裝docker 相關的,主要是爲了增長監控使用
sudo yum update -y
sudo yum install -y yum-utils device-mapper-persistent-data lvm2
sudo yum-config-manager --add-repo https://download.docker.com/linux/centos/docker-ce.repo
sudo yum install docker-ce -y
systemctl start docker
## 安裝erlang環境與rabbitmq-server部署
sudo yum install deltarpm -y
wget --content-disposition https://packagecloud.io/rabbitmq/erlang/packages/el/7/erlang-20.0.5-1.el7.centos.x86_64.rpm/download.rpm
sudo yum install -y erlang-20.0.5-1.el7.centos.x86_64.rpm
sudo yum install -y socat
#wget https://dl.bintray.com/rabbitmq/all/rabbitmq-server/3.7.5/rabbitmq-server-3.7.5-1.el7.noarch.rpm
wget download.hyahm.com/rabbitmq-server-3.7.5-1.el7.noarch.rpm
yum install rabbitmq-server-3.7.5-1.el7.noarch.rpm -y
chkconfig rabbitmq-server on
mkdir -p /var/data/rabbitmq && chown rabbitmq:rabbitmq /var/data/rabbitmq && chmod 755 /var/data/rabbitmq
echo 'RABBITMQ_MNESIA_BASE=/var/data/rabbitmq' >> /etc/rabbitmq/rabbitmq-env.conf
echo 'ulimit -S -n 4096' >> /etc/rabbitmq/rabbitmq-env.conf
echo 'cluster_partition_handling=pause_minority' >> /etc/rabbitmq/rabbitmq.conf
## 打開防火牆
iptables -I INPUT -p tcp -s xxxx --dport 25672 -j ACCEPT
iptables -I INPUT -p tcp -s xxx--dport 4369 -j ACCEPT
iptables -I INPUT -p tcp --dport 5672 -j ACCEPT
### 選擇須要訪問的內網地址
iptables -I INPUT -s 192.168.0.0/16 -j ACCEPT
iptables -I INPUT -s 172.17.0.0/16 -j ACCEPT
複製代碼
集羣化:
# on rabbit1
rabbitmq-server -detached
# on rabbit2
rabbitmq-server -detached
# on rabbit3
rabbitmq-server -detached
複製代碼
# on rabbit1
rabbitmqctl cluster_status
# => Cluster status of node rabbit@rabbit1 ...
# => [{nodes,[{disc,[rabbit@rabbit1]}]},{running_nodes,[rabbit@rabbit1]}]
# => ...done.
# on rabbit2
rabbitmqctl cluster_status
# => Cluster status of node rabbit@rabbit2 ...
# => [{nodes,[{disc,[rabbit@rabbit2]}]},{running_nodes,[rabbit@rabbit2]}]
# => ...done.
# on rabbit3
rabbitmqctl cluster_status
# => Cluster status of node rabbit@rabbit3 ...
# => [{nodes,[{disc,[rabbit@rabbit3]}]},{running_nodes,[rabbit@rabbit3]}]
# => ...done.
複製代碼
# on rabbit2
rabbitmqctl stop_app
# => Stopping node rabbit@rabbit2 ...done.
rabbitmqctl reset
# => Resetting node rabbit@rabbit2 ...
rabbitmqctl join_cluster rabbit@rabbit1
# => Clustering node rabbit@rabbit2 with [rabbit@rabbit1] ...done.
rabbitmqctl start_app
# => Starting node rabbit@rabbit2 ...done.
複製代碼
# on rabbit1
rabbitmqctl cluster_status
# => Cluster status of node rabbit@rabbit1 ...
# => [{nodes,[{disc,[rabbit@rabbit1,rabbit@rabbit2,rabbit@rabbit3]}]},
# => {running_nodes,[rabbit@rabbit3,rabbit@rabbit2,rabbit@rabbit1]}]
# => ...done.
複製代碼
systemctl start rabbitmq-server
rabbitmq-plugins enable rabbitmq_management
rabbitmqctl add_user admin xxxxxx
rabbitmqctl set_permissions -p "/" admin ".*" ".*" ".*"
rabbitmqctl set_user_tags admin administrator
複製代碼
docker run -d -e RABBIT_URL=http://{{內網Ip}}:15672 -e RABBIT_CAPABILITIES=bert,no_sort -e RABBIT_USER=admin -e RABBIT_PASSWORD=xxx -e PUBLISH_PORT=9419 -p 9419:9419 kbudde/rabbitmq-exporter
複製代碼