1. 程式人生 > 實用技巧 >RabbitMQ叢集搭建

RabbitMQ叢集搭建

一、前提

  • erlang安裝版本一致
  • RabbitMQ安裝版本一致
  • 下面的例子以192.168.73.134與192.168.73.135為伺服器搭建Rabbitmq叢集.

二、RabbitMQ叢集

RabbitMQ是用erlang開發的,叢集非常方便,因為erlang天生就是一門分散式語言,但其本身並不支援負載均衡。Rabbit模式大概分為以下三種:單一模式、普通模式、映象模式。

  • 單一模式:最簡單的情況,非叢集模式。

  • 普通模式:預設的叢集模式。

      對於Queue來說,訊息實體只存在於其中一個節點,A、B兩個節點僅有相同的元資料,即佇列結構。
      
      當訊息進入A節點的Queue中後,consumer從B節點拉取時,RabbitMQ會臨時在A、B間進行訊息傳輸,把A中的訊息實體取出並經過B傳送給consumer。
      所以consumer應儘量連線每一個節點,從中取訊息。即對於同一個邏輯佇列,要在多個節點建立物理Queue。否則無論consumer連A或B,出口總在A,會產生瓶頸。
      
      該模式存在一個問題就是當A節點故障後,B節點無法取到A節點中還未消費的訊息實體。
      
      如果做了訊息持久化,那麼得等A節點恢復,然後才可被消費;如果沒有持久化的話,然後就沒有然後了……
    
  • 映象模式:把需要的佇列做成映象佇列,存在於多個節點,屬於RabbitMQ的HA方案。

      該模式解決了上述問題,其實質和普通模式不同之處在於,訊息實體會主動在映象節點間同步,而不是在consumer取資料時臨時拉取。
      
      該模式帶來的副作用也很明顯,除了降低系統性能外,如果映象佇列數量過多,加之大量的訊息進入,叢集內部的網路頻寬將會被這種同步通訊大大消耗掉。
      
      所以在對可靠性要求較高的場合中適用(後面會詳細介紹這種模式,目前我們搭建的環境屬於該模式)。
    

2.1 叢集中的基本概念

RabbitMQ的叢集節點包括記憶體節點、磁碟節點。

顧名思義記憶體節點就是將所有資料放在記憶體,磁碟節點將資料放在磁碟。不過,如前文所述,如果在投遞訊息時,打開了訊息的持久化,那即使是記憶體節點,資料還是安全的放在磁碟。

一個RabbitMQ叢集中可以共享user、vhost、queue、exchange等,所有的資料和狀態都是必須在所有節點上覆制的,一個例外是那些當前只屬於建立它的節點的訊息佇列,儘管它們可見且可被所有節點讀取。RabbitMQ節點可以動態地加入到叢集中,一個節點它可以加入到叢集中,也可以從叢集環叢集進行一個基本的負載均衡。

叢集中有兩種節點:

  • 記憶體節點:只儲存狀態到記憶體(一個例外的情況是:持久的queue的持久內容將被儲存到disk)

  • 磁碟節點:儲存狀態到記憶體和磁碟。

記憶體節點雖然不寫入磁碟,但是它執行比磁碟節點要好。叢集中,只需要一個磁碟節點來儲存狀態 就足夠了
如果叢集中只有記憶體節點,那麼不能停止它們,否則所有的狀態,訊息等都會丟失。

思路:
那麼具體如何實現RabbitMQ高可用,我們先搭建一個普通叢集模式,在這個模式基礎上再配置映象模式實現高可用,Rabbit叢集前增加一個反向代理,生產者、消費者通過反向代理訪問RabbitMQ叢集。

架構圖如下:

2.2 叢集模式配置

step1: 區域網配置
在安裝好的三臺節點伺服器中,分別修改/etc/hosts檔案
1. vim /etc/hosts

192.168.73.134 node1
192.168.73.135 node2
step2: 設定不同節點間同一認證的Erlang Cookie
Erlang的叢集中各節點是通過一個magic cookie來實現的,這個cookie存放在 /var/lib/rabbitmq/.erlang.cookie 中,檔案是400的許可權。
所以必須保證各節點cookie保持一致,否則節點之間就無法通訊。
採用從主節點copy的方式保持Cookie的一致性:

1. chmod 777  /var/lib/rabbitmq/.erlang.cookie
2. scp -p 22 /var/lib/rabbitmq/.erlang.cookie root@192.168.73.135:/var/lib/rabbitmq/

複製好後檢視檔案所屬使用者和組以及許可權是否滿足要求,不滿足則修改。之後還原.erlang.cookie的許可權,否則可能會遇到錯誤:
3. chown rabbitmq:rabbitmq .erlang.cookie
4. chmod 400 /var/lib/rabbitmq/.erlang.cookie
step3: 使用 -detached執行各節點
設定好cookie後將各個節點的RabbitMQ重啟:
1. cd /sbin
2. rabbitmqctl stop
3. rabbitmq-server start

這裡正常重啟可能會提示該節點示例已經再執行中。如果出現使用以下命令啟動:
1. ps -aux | grep erl
2. kill -9 {pid}
3. RABBITMQ_NODE_PORT=5678 RABBITMQ_NODENAME=rabbit@node1 ./rabbitmq-server -detached
    RABBITMQ_NODE_PORT=5678 RABBITMQ_NODENAME=rabbit@node2 ./rabbitmq-server -detached

ps:上面5678是因為在安裝時將rabbitmq的埠修改為5678了,而nodename與hosts裡面設定的保持一致。
    依次啟動所有節點。
step4: 檢視各節點的狀態
1. 檢視啟動埠:  netstat -lntp 

    Active Internet connections (only servers)
    Proto Recv-Q Send-Q Local Address           Foreign Address         State       PID/Program name    
    tcp        0      0 0.0.0.0:4369            0.0.0.0:*               LISTEN      27321/epmd          
    tcp        0      0 0.0.0.0:22              0.0.0.0:*               LISTEN      760/sshd            
    tcp        0      0 127.0.0.1:25            0.0.0.0:*               LISTEN      1066/master         
    tcp        0      0 0.0.0.0:15678           0.0.0.0:*               LISTEN      27862/beam.smp      
    tcp        0      0 0.0.0.0:25672           0.0.0.0:*               LISTEN      27862/beam.smp      
    tcp6       0      0 :::5678                 :::*                    LISTEN      27862/beam.smp      
    tcp6       0      0 :::8080                 :::*                    LISTEN      964/java            
    tcp6       0      0 :::4369                 :::*                    LISTEN      27321/epmd          
    tcp6       0      0 :::22                   :::*                    LISTEN      760/sshd            
    tcp6       0      0 ::1:25                  :::*                    LISTEN      1066/master         
    tcp6       0      0 127.0.0.1:8005          :::*                    LISTEN      964/java            
    tcp6       0      0 :::8009                 :::*                    LISTEN      964/java

2. 檢視rabbitmq啟動狀態:  
    rabbitmqctl -n rabbit1
step5: 建立並部署叢集
將rabbit
step5: 檢視叢集狀態
1.檢視節點1的叢集狀態:   rabbitmqctl -n rabbit
至此,rabbitmq叢集搭建完畢。

三、RabbitMQ映象模式

上面配置RabbitMQ預設叢集模式,但並不保證佇列的高可用性,儘管交換機、繫結這些可以複製到叢集裡的任何一個節點,但是佇列內容不會複製,雖然該模式解決一部分節點壓力,但佇列節點宕機直接導致該佇列無法使用,只能等待重啟,所以要想在佇列節點宕機或故障也能正常使用,就要複製佇列內容到叢集裡的每個節點,需要建立映象佇列。

step1:增加負載均衡器

關於負載均衡器,商業的比如F5的BIG-IP,Radware的AppDirector,是硬體架構的產品,可以實現很高的處理能力。但這些產品昂貴的價格會讓人止步,所以我們還有軟體負載均衡方案。網際網路公司常用的軟體LB一般有LVS、HAProxy、Nginx等。LVS是一個核心層的產品,主要在第四層負責資料包轉發,使用較複雜。HAProxy和Nginx是應用層的產品,但Nginx主要用於處理HTTP,所以這裡選擇HAProxy作為RabbitMQ前端的LB。

1. 安裝HAProxy(在192.168.73.136上安裝HAProxy)
    yum -y install haproxy

2. 修改haproxy.config配置
    vim /etc/haproxy/haproxy.config
    在其中增加以下配置:
    listen rabbitmq_cluster 0.0.0.0:5678
        mode tcp
        balance roundrobin
        server rabbitmaster 192.168.73.134:5678 check inter 2000 rise 2 fall 3
        server rabbitslave 192.168.73.135:5678 check inter 2000 rise 2 fall 3

修改完HaProxy配置之後重新啟動可能會提示繫結埠失敗,此時執行以下命令即可:

    setsebool -P haproxy_connect_any=1

負載均衡器會監聽192.168.73.136的5678埠,輪詢我們的兩個節點192.168.73.134、192.168.73.135的5678埠,這樣磁碟節點除了故障也不會影響,除非同時出故障。

step2:配置Rabbitmq策略

在任意一個節點上執行:

    rabbitmqctl set_policy ha-all "^" '{"ha-mode":"all"}'
    上面的命令會將所有佇列設定為映象佇列,即佇列會被複制到各個節點,各個節點狀態保持一致
step3:使用負載伺服器傳送訊息

客戶端使用負載伺服器172.16.3.110 (panyuntao3)傳送訊息,佇列會被複制到所有節點。到這裡我們完成了RabbitMQ叢集的高可用配置。

作者:明天你好向前奔跑
連結:https://www.jianshu.com/p/01527d177e12