網絡分區的斷定node
RabbitMQ中與網絡分區的斷定相關的是net_ticktime這個參數,默認爲60s。在RabbitMQ集羣中的每一個broker節點會每隔 net_ticktime/4 (默認15s)計一次tick(若是有任何數據被寫入節點中,此節點被認爲被ticked),若是在連續四次某節點都沒有被ticked到,則斷定此節點處於down的狀態,其他節點能夠將此節點剝離出當前分區。將連續四次的tick時間即爲T,那麼T的取值範圍爲 0.75ticktime < T < 1.25ticktimeshell
默認狀況下,在45s,日誌出現網絡
=ERROR REPORT==== 16-Jul-2017::15:20:55 === Mnesia('rabbit@node1'): ** ERROR ** mnesia_event got {inconsistent_database, running_partitioned_network, 'rabbit@node2'}
當一個節點起來的時候,RabbitMQ會記錄是否發生了網絡分區,你能夠經過WebUI進行查看;app
RabbitMQ GUI上顯示 Network partition detected Mnesia reports that this RabbitMQ cluster has experienced a network partition. There is a risk of losing data. Please read RabbitMQ documentation about network partitions and the possible solutions.
或者能夠經過rabbitmqctl cluster_status命令查看,若是查看到信息中的partitions那一項是空的,就像這樣ide
[{nodes,[{disc,['rabbit@node1', 'rabbit@node2']}]}, {running_nodes,['rabbit@node2','rabbit@node1']}, {cluster_name,<<"rabbit@node1">>}, {partitions,[]}]
然而當網絡分區時,會變成這樣:this
[{nodes, [{disc, ['rabbit@node1','rabbit@node2']}]}, {running_nodes,['rabbit@node1']}, {cluster_name,<<"rabbit@node1">>}, {partitions, [{'rabbit@node1',['rabbit@node2']}]}]
當一個RabbitMQ集羣發生網絡分區時,這個集羣會分紅兩個或者多個分區,它們各自爲政,互相都認爲對方分區的節點已經down,包括queues,bindings,exchanges這些信息的建立和銷燬都處於自身分區內,與其它分區無關。若是原集羣中配置了鏡像隊列,而這個鏡像隊列又牽涉到兩個或者多個網絡分區中的節點時,每個網絡分區中都會出現一個master節點,若是分區節點個數充足,也會出現新的slave節點,對於各個網絡分區,彼此的隊列都是相互獨立的,固然也會有一些其餘未知的、怪異的事情發生。當網絡恢復時,網絡分區的狀態仍是會保持,除非採起一些措施去解決他.net
自動處理網絡分區日誌
RabbitMQ提供了4種處理網絡分區的方式,在rabbitmq.config中配置cluster_partition_handling參數便可,分別爲: code
默認是ignore: ignore的配置是當網絡分區的時候,RabbitMQ不會自動作任何處理,即須要手動處理中間件
pause_minority: 當發生網絡分區時,集羣中的節點在觀察到某些節點down掉時,會自動檢測其自身是否處於少數派(小於或者等於集羣中通常的節點數)。少數派中的節點在分區發生時會自動關閉,當分區結束時又會啓動。這裏的關閉是指RabbitMQ application關閉,而Erlang VM並不關閉,這個相似於執行了rabbitmqctl stop_app命令。處於關閉的節點會每秒檢測一次是否可連通到剩餘集羣中,若是能夠則啓動自身的應用,至關於執行rabbitmqctl start_app命令。
pause_if_all_down: 在pause_if_all_down模式下,RabbitMQ會自動關閉不能和list中節點通訊的節點。語法爲{pause_if_all_down, [nodes], ignore|autoheal},其中[nodes]即爲前面所說的list。若是一個節點與list中的全部節點都沒法通訊時,自關閉其自身。若是list中的全部節點都down時,其他節點若是是ok的話,也會根據這個規則去關閉其自身,此時集羣中全部的節點會關閉。若是某節點可以與list中的節點恢復通訊,那麼會啓動其自身的RabbitMQ應用,慢慢的集羣能夠恢復
autoheal: 在autoheal模式下,當認爲發生網絡分區時,RabbitMQ會自動決定一個獲勝的(winning)分區,而後重啓不在這個分區中的節點以恢復網絡分區。一個獲勝的分區是指客戶端鏈接最多的一個分區。若是產生一個平局,既有兩個或者多個分區的客戶端鏈接數同樣多,那麼節點數最多的一個分區就是獲勝的分區。若是此時節點數也同樣多,將會以一種特殊的方式來挑選獲勝分區
oscar cmp目前的配置以下:
rabbitmq.config
[ {rabbit, [{cluster_nodes, {['rabbit@sh01-oscar-cmp-prod-rmq03','rabbit@sh01-oscar-cmp-prod-rmq01','rabbit@sh01-oscar-cmp-prod-rmq02'],ram }}, {cluster_partition_handling,pause_minority}]}, {kernel,[{net_ticktime, 60}]} ].
能夠看出使用的第二種方式
grafana添加報警規則
partitions Current Number of network partitions. 0 is ok. If the cluster is splitted the value is at least 2
由此能夠看出,partitions爲0時正常,若是集羣發生了分裂值至少爲2.故咱們能夠設置partitions值不爲0時報警
添加規則:
- alert: Rabbitmq_node_partitions expr: (rabbitmq_partitions{job="rabbitmq_monitor"}) != 0 for: 2m labels: issuetype: "嚴重" sourcetype: "中間件" annotations: summary: "Instance {{ $labels.instance }} rabbitmq集羣節點故障: partitions" description: "{{ $labels.instance }} of job {{ $labels.job }} on {{ $labels.node }} rabbitmq集羣節點故障: partitions" referenceURL: "http://wiki.virtueit.net/display/CMDT/2.+Maintenance+Manual" recovered: "recovered"