RabbitMQ 分布式設置和高可用性討論


abbitMQ的集群主要有配置方式,分別是:本地局域網Cluster,federation,shovel。

RabbitMQ Cluster主要是用於同一個網段內的局域網。

federation和shovel可以用於廣域網,shovel比federation更底層,可以用於更多地方。

RabbitMQ Cluster配置

RabbitMQ Cluster是根據Erlang的實現的。必須滿足一下幾個要求:

  1. 所有機器上,必須Erlang運行時和RabbitMQ的版本相同。(否則會不能連接到一起)
  2. 所有機器上,的Erlang的Cookie都相同。

注意:由於RabbitMQ會使用Node@HostName,如果你在/etc/hosts里面定義了IP HostName關系,當你的IP發生變化時,命令行都會失去作用。

查看機器上的Erlang的Cookie。

linux上位置有兩個地方。一個是在$HOME目錄下的.erlang.cookie 另外在/var/lib/rabbitmq/.erlang.cookie

通過修改rabbitmq-server腳本文件和rabbitmqctl,在 erl 后面增加 -setcookie wugetestnodes

注意:必須兩個腳本同時增加-setcookie "所以寫相關cookie",否則rabbitmqctl無法控制對應的rabbitmq

服務器啟動

每個節點運行一下命令:

$rabbitmq-server -detached             #讓當前rabbitmq-server的進程后台運行。

每個節點執行以下命令:

$rabbitmqctl cluster_status          #獲得集群配置信息。

例子:

將節點加入到主節點中

首先停止正在運行的節點。

在節點2上運行以下命令:

sudo ./rabbitmqctl stop_app  #停止rabbitmq運行

sudo .rabbitmqctl join_cluster --ram rabbit@cs_hd_os1  #加入到rabbit節點中,使用內存模式。

sudo  ./rabbitmqctl cluster_status  #查看狀態


sudo ./rabbitmqctl start_app  #啟動rabbitmq

sudo  ./rabbitmqctl cluster_status  #查看狀態

默認分布式現象

當設置完成基本Cluster結構之后,會將 Vhost為"/"下面的Queue隊列同步。同步效果如下

節點1:

節點2 

無論是從同一個Cluster中那個節點消費,隊列狀態都會進行同步.

修改節點類型

我們要將節點2的RAM類型修改為Disc類型。

./rabbitmqctl stop_app
./rabbitmqctl change_cluster_node_type disc
./rabbitmqctl start_app
./rabbitmqctl cluster_status

當Cluster集群中僅有一台機器為Disc情況下,這台機器不能修改存儲狀態。

當集群節點使用./rabbitmqctl stop_app情況下,集群其他節點保存停止節點的信息。但是運行狀態會改變。

構建Cluster的數據高可靠性

場景描述:

有兩台服務器,服務器一:cs_hd_os1。服務器二:cs_hd_os2 設置cs_hd_os2加入到cs_hd_os1的集群里面。

初始化創建Cluster集群數據情況

這里沒有配置Policy相關文件。

  1. 當兩台服務器rabbitmq都運行時候。在cs_hd_os1和cs_hd_os2可以看到在 vhost為"/"下的內容相互復制。(Exchange,Bind, Queue)都會復制到對方里面。
  2. 當其中一台停機之后,另外一台智能看到Exchange名稱,Bind,Queue都消失了。

注意:兩個RabbitMQ的Queue不能重名,重名之后會有異常產生。

當其中一個Node失效后,另外一個Node也失效

先啟動最后一個失效的節點,節點不能啟動。

這是因為數據庫崩潰了。刪除掉RabbitMQ的數據庫就可以恢復了。

為節點配置HA策略

HA策略主要配置

HA的策略主要分為 三種:

ha-mode ha-params 說明
all 鏡像隊列將會在整個集群中復制。當一個新的節點加入后,也會在這個節點上復制一份。
exactly count 鏡像隊列將會在集群上復制count份。如果集群數量少於count時候,隊列會復制到所有節點上。如果大於Count集群,有一個節點crash后,新進入節點也不會做新的鏡像。(這位阻止集群雪崩)
nodes node name 鏡像隊列會在node name中復制。如果這個名稱不是集群中的一個,這不會觸發錯誤。如果在這個node list中沒有一個節點在線,那么這個queue會被聲明在client連接的節點。

節點策略與集群遷移

如果master節點沒有包含在這個策略中的時候,只有當有一個slave node與Master同步完成之后,master才會離開。client將要重新連接服務器。

獨有的隊列(Exclusive queue)

獨有的隊列不會被鏡像話,因為狀態無法保證。

設置策略方法

方法1 :使用命令行來設置

set_policy [-p vhostpath] [--priority priority] [--apply-to apply-to] {name} {pattern} {definition}
ha-mode ha-params 說明
-p /wuge 設置vhost信息。
--priority 10 設置優先級。高數字會優先處理。
--apply-to queue 作用對象。queue、exchanges,all
name 規則名稱
./rabbitmqctl set_policy -p '/wuge' --priority 9 --apply-to all testctl "^hello" '{"ha-mode":"all","ha-sync-mode":"automatic"}'

方法2:通過restful API

/api/policies/%2Fwuge/testctl

{"vhost":"/wuge","name":"testctl","pattern":"^hello","apply-to":"all","definition":{"ha-mode":"all","ha-sync-mode":"automatic"}}

定義ha-sync-mode說明

ha-sync-mode分為兩種狀態設置:一種為手動"manual",另一種為自動"automatic"。 默認的設置為manual

我們可以通過使用rabbitmqctl來同步數據。

說明 命令
設置那兩個系統之間進行同步 rabbitmqctl list_queues name slave_pids synchronised_slave_pids
手動同步那個隊列 rabbitmqctl sync_queue name
手動終止對應的隊列 rabbitmqctl cancel_sync_queue name

分布式數據同步

新的Slave節點加入的處理方法

一個新的Slave節點加入,他需要同步其他節點的數據。而當同步數據的時候,當前同步的Queue就不能被使用。(無法發送消息到Queue中,也無法從里面獲取消息進行處理)。

在Slave之間進行數據同步的時候,如果是police策略范圍內的。(例如本例:task_police策略中,有task名稱開頭,性能下降嚴重)。所有的消息發送和消息消費,性能都降低到極點。僅僅是非同步策略的1/10。

而發送到一個沒有策略的數據時候,性能得到很高的提升。與原來相同。

我們可以得到以下結論:

  1. 在策略下,多個node節點Mirror會降低性能。
  2. 同步狀態下,同步的Queue不能接受數據。其他Queue性能會受到影響。(有同步策略的Queue都有影響,性能降低到1/10。沒有同步策略的Queue,性能幾乎沒有變化。如果沒有同步狀態,對比單服務器性能下降到1/3)。
  3. 同步狀態下,對非同一個同步策略下的Queue影響。

兩個Slave節點的Queue數據之間進行同步之前,最好讓Queue中數據被消費完全。否則同步會造成性能的集體降低。

RabbitMQ網絡分區影響和選擇

在rabbitMQ中,我們可能會因為network partition,導致rabbitmq集群出現不同組。rabbitmq給了我們特定的三個選擇。

   
ignore(默認) 認為網絡非常好,所有機器都在同一個交換機上。
pause_minority 暫停,選擇最小集群作為可信集群,重新啟動其他集群。
autoheal 根據連接數最高的節點,重啟其他節點。

如何判斷cluster保持狀態。 當節點交互keepalive時間超過之后,就會認為節點失敗。

[{rabbit:[{cluster_partiton_handling:ignore},{cluster_keepalive_interval:10000}]}]

RabbitMQ同步討論

當RabbitMQ服務器Mirror Queue隊列的其中一個Slave Node停止之后,重新連接到Master Node之后,無論數據是否有變動,都會重新驗證數據是否同步。(根據同步狀態的時間消耗,可以獲知第一次同步時候,會重新發送消息。而第一次同步之后,再次同步不會所有數據都同步)。

同步會造成發送端暫停,數據不會再被發送,客戶端會一直等待服務器Broker的Queue隊列完成同步。當客戶端Producer一直要發送數據到服務端,從而造成IO等待,不能發送數據完成。

解決相關問題:

1,使用Exchange,動態修改Exchange和Queue的版本。 2,舉例說明:

首先定義一個Exchange。為task_Exchange.
定義兩個queue,為task_queue和task_otherqueue
現將task_Exchange和task_queue構建消費隊列。

發送數據到task_Exchange和task_queue,使用routekey為test。當task_queue堆積過大,而且也需要同步的時候。

可以綁定task_Exchange和task_otherqueue。也是用routekey為test。並且取消task_Exchange和task_queue綁定。數據就會發送到其他隊列。從而減少阻塞造成的影響。

我通過實驗發現,不可以在同步狀態下進行以上操作,必須在非同步狀態下修改。同步狀態會導致客戶端連接錯誤。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM