天天看點

使用 Docker -compose 部署多機 RabbitMQ 叢集

本文介紹 RabbitMQ 叢集的 Docker 化部署,最開始是想通過 DockerSwarm 方式來部署的,但是 RabbitMQ 節點加入叢集時一直失敗,在網上找了很多辦法,始終沒有解決這個問題,無奈隻能放棄。是以最終采用配置 hosts 檔案方式來保證節點之間的通信,下面來進行詳細說明。

部署環境

  • 系統:CentOS8
  • 兩台伺服器:10.1.1.1/10.1.1.2

docker-compose 檔案

version: '3'

services:
  rabbit1:
    container_name: rabbit1
    image: rabbitmq:3.7-management-alpine
    restart: always
    hostname: rabbit1
    extra_hosts:
      - "rabbit1:10.1.1.1"
      - "rabbit2:10.1.1.2"
    environment:
      - RABBITMQ_ERLANG_COOKIE=MY_COOKIE
      - RABBITMQ_DEFAULT_USER=MY_USER
      - RABBITMQ_DEFAULT_PASS=MY_PASS
    ports:
      - "4369:4369"
      - "5671:5671"
      - "5672:5672"
      - "15671:15671"
      - "15672:15672"
      - "25672:25672"           

複制

這樣,10.1.1.1 上的 docker-compose 檔案就寫好了,部署另一台時,隻要将

rabbit1

改成

rabbit2

就可以了。如果是更多台伺服器的話,也是同樣的道理,将 IP 配置到

extra_hosts

參數下即可。

啟動服務

在兩台伺服器上分别執行:

# docker-compose up -d           

複制

加入叢集

如果将

rabbit1

作為主節點的話,需要在

rabbit2

上執行指令,将其加入到叢集,如下:

# docker exec -it rabbit2 /bin/bash

rabbit2# rabbitmqctl stop_app
rabbit2# rabbitmqctl reset
rabbit2# rabbitmqctl join_cluster rabbit@rabbit1
rabbit2# rabbitmqctl start_app           

複制

預設情況下,RabbitMQ 啟動後是磁盤節點,如果想以記憶體節點方式加入,可以加

--ram

參數。

如果想要修改節點類型,可以使用指令:

# rabbitmqctl change_cluster_node_type disc(ram)           

複制

修改節點類型之前需要先

rabbitmqctl stop_app

通過下面指令來檢視叢集狀态:

# rabbitmqctl cluster_status           

複制

注意,由于 RAM 節點僅将内部資料庫表存儲在記憶體中,是以在記憶體節點啟動時必須從其他節點同步這些資料,是以一個叢集必須至少包含一個磁盤節點。

HAProxy 負載均衡

ha 同樣采用 Docker 方式來部署,先看一下 haproxy.cfg 配置檔案:

# Simple configuration for an HTTP proxy listening on port 80 on all
# interfaces and forwarding requests to a single backend "servers" with a
# single server "server1" listening on 127.0.0.1:8000

global
    daemon
    maxconn 256

defaults
    mode http
    timeout connect 5000ms
    timeout client 5000ms
    timeout server 5000ms

listen rabbitmq_cluster
    bind 0.0.0.0:5677
    option tcplog
    mode tcp
    balance leastconn
    server  rabbit1 10.1.1.1:5672 weight 1 check inter 2s rise 2 fall 3
    server  rabbit2 10.2.2.2:5672 weight 1 check inter 2s rise 2 fall 3

listen http_front
    bind 0.0.0.0:8002
    stats uri /haproxy?stats

listen rabbitmq_admin
    bind 0.0.0.0:8001
    server rabbit1 10.1.1.1:15672
    server rabbit2 10.1.1.2:15672           

複制

再看一下 docker-compose 檔案:

version: '3'

services:
  haproxy:
    container_name: rabbit-haproxy
    image: haproxy
    restart: always
    hostname: haproxy
    network_mode: rabbitmq_default
    volumes:
      - ./haproxy.cfg:/usr/local/etc/haproxy/haproxy.cfg
    ports:
      - "5677:5677"
      - "8001:8001"
      - "8002:8002"           

複制

啟動之後,就可以通過 ha 的位址來通路 RabbitMQ 叢集管理頁面了。

如果公司内部有現成的負載均衡,比如 LVS,那麼也可以省略這一步。

其實到這裡,叢集就可以正常使用了,但還有很重要的一點需要做些說明。

叢集模式

普通模式

  • 對于 Queue 來說,消息實體隻存在于其中一個節點,A、B 兩個節點僅有相同的中繼資料,即隊列結構。
  • 當消息進入 A 節點的隊列中後,消費者從 B 節點拉取時,RabbitMQ 會臨時在 A、B 間進行消息傳輸,把 A 中的消息實體取出并經過 B 發送給消費者。
  • 是以,消費者應盡量連接配接每一個節點,從中取消息。即對于同一個邏輯隊列,要在多個節點建立實體隊列,否則,無論消費者連 A 或者連 B,出口總在 A,會産生瓶頸。
  • 該模式還存在一個問題就是當 A 節點故障後,B 節點無法取到 A 節點中還未消費的消息實體。
  • 如果做了消息持久化,那麼得等 A 節點恢複,才可被消費;如果沒有持久化的話,消息會丢失。

鏡像模式

  • 該模式解決了上述問題,其和普通模式不同之處在于,消息實體會主動在鏡像節點間同步,而不是在消費者取資料時臨時拉取。
  • 該模式帶來的副作用也很明顯,除了降低系統性能外,如果鏡像隊列數量過多,加之大量的消息進入,叢集内部的網絡帶寬将會被這種同步通訊大大消耗掉。
  • 是以,在對可靠性要求較高的場合中适用于該模式。

個人感覺,在生産環境中,還是使用鏡像模式比較保險。

要想使用鏡像模式,不管是通過管理頁面,還是指令行方式,隻需要簡單配置即可完成。管理頁面方式就不過多介紹了,下面說說如何通過指令行來設定,一條指令就搞定。

添加:

# rabbitmqctl set_policy -p testvhost testha "^" '{"ha-mode":"all","ha-sync-mode":"automatic"}'
Setting policy "testha" for pattern "^" to "{"ha-mode":"all","ha-sync-mode":"automatic"}" with priority "0" for vhost "testvhost" ...           

複制

清除:

# rabbitmqctl clear_policy -p testvhost testha
Clearing policy "testha" on vhost "testvhost" ...           

複制

檢視:

# rabbitmqctl list_policies -p testvhost
Listing policies for vhost "testvhost" ...
vhost   name    pattern apply-to        definition      priority
testvhost       testha  ^       all     {"ha-mode":"all","ha-sync-mode":"automatic"}    0           

複制

參數說明:

  • Virtual host:政策應用的 vhost。
  • Name:為政策名稱,可以是任何名稱,但建議使用不帶空格的基于 ASCII 的名稱。
  • Pattern:與一個或多個 queue(exchange) 名稱比對的正規表達式,可以使用任何正規表達式。隻有一個

    ^

    代表比對所有,

    ^test

    為比對名稱為 "test" 的 exchanges 或者 queue。
  • Apply to:Pattern 應用對象。
  • Priority:配置多個政策時的優先級,值越大,優先級越高。沒有指定優先級的消息會以 0 優先級對待,對于超過隊列所定最大優先級的消息,優先級以最大優先級對待。
  • Definition:鍵/值對,将被插入比對 queues and exchanges 的可選參數映射中。

    ha-mode

    :政策鍵,分為 3 種模式:
    • all

      :所有的 queue。
    • exctly

      :部分(需配置

      ha-params

      參數,此參數為 int 類型。比如 3,衆多叢集中的随機 3 台機器)。
    • nodes

      :指定(需配置

      ha-params

      參數,此參數為數組類型。比如 ["rabbit@rabbit2", "rabbit@rabbit3"] 這樣指定為 rabbit2 與 rabbit3 這兩台機器)。

    ha-sync-mode

    :隊列同步:
    • manual

      :手動(預設模式)。新的隊列鏡像将不會收到現有的消息,它隻會接收新的消息。
    • automatic

      :自動同步。當一個新鏡像加入時,隊列會自動同步。隊列同步是一個阻塞操作。

以上就是本篇全部内容,歡迎大家留言交流。

下一篇: Springcloud Eureka instance 配置項→