3.RabbitMQ高階叢集搭建(Haproxy負載均衡、Keepalived高可用)

peng_boke發表於2024-04-12

前言

RabbitMQ叢集搭建。

1.RabbitMQ叢集原理

RabbitMQ這款訊息佇列中介軟體產品本身是基於Erlang編寫,Erlang語言天生具備分散式特性(透過同步Erlang叢集各節點的magic cookie來實現)。因此,RabbitMQ天然支援Clustering。這使得RabbitMQ本身不需要像ActiveMQ、Kafka那樣透過ZooKeeper分別來實現HA方案和儲存叢集的後設資料。叢集是保證可靠性的一種方式,同時可以透過水平擴充套件以達到增加訊息吞吐量能力的目的

5臺機器,3臺RabbitMQ伺服器

192.168.188.180 rmq1(rabbitmq節點1)
192.168.188.181 rmq2(rabbitmq節點2)
192.168.188.182 rmq3(rabbitmq節點3)
192.168.188.190 hp1(haproxy主節點)
192.168.188.191 hp2(haproxy備份點)

2.虛擬機器安裝Linux

安裝Centos,參看我之前的文章。

https://www.cnblogs.com/pengboke/p/18051066。

克隆5臺Centos

image-20240409000640244

修改IP

vim /etc/sysconfig/network-scripts/ifcfg-ens33

重啟網路服務,檢視ip是否配置成功

service network restart

改Centos-02為192.168.188.181

image-20240409001616312

改Centos-02為192.168.188.182

image-20240409001104406

改完之後需要重新登入一下,這樣三臺RabbitMQ伺服器就準備好了。

image-20240409001536261

一樣的步驟:

Centos-04改為192.168.188.190

Centos-05改為192.168.188.191

image-20240409002222852

3.安裝RabbitMQ

3.1設定機器別名

hostnamectl set-hostname 機器別名 --static

修改三臺機器別名如下:

hostnamectl set-hostname rmq1 --static
hostnamectl set-hostname rmq2 --static
hostnamectl set-hostname rmq3 --static

檢視狀態

hostnamectl status

image-20240410214816916

3.2修改hosts檔案

開啟hosts檔案

vi /etc/hosts

修改:

# rabbitmq的ip + 機器別名
192.168.188.180 rmq1 
192.168.188.181 rmq2
192.168.188.182 rmq3

image-20240410215313793

3.3安裝Erlang

安裝erlang repository

curl -s https://packagecloud.io/install/repositories/rabbitmq/erlang/script.rpm.sh | sudo bash

image-20240410215753489

安裝erlang

yum install erlang

image-20240410220027568

驗證,然後出來版本即可,ctro+c 倆次取消當前命令。

#驗證是否安裝成功
erl

image-20240410220051836

3.4安裝RabbitMQ

3.4.1匯入兩個key

rpm --import https://packagecloud.io/rabbitmq/rabbitmq-server/gpgkey
rpm --import https://packagecloud.io/gpg.key

image-20240410220347489

3.4.2下載RabbitMQ指令碼

curl -s https://packagecloud.io/install/repositories/rabbitmq/rabbitmq-server/script.rpm.sh | sudo bash

image-20240410223257603

3.4.3wget下載RabbitMQ

重要說明:如果提示沒有wget命令,先安裝wget命令。

 sudo yum install wget

image-20240410223331762

使用wget下載

curl -s erlang Repositoryde的版本預設很低,安裝舊版本rabbitmq沒有問題,但是我安裝最新的rabbitmq,具體解決看3.8

# 舊版本
# wget https://github.com/rabbitmq/rabbitmq-server/releases/download/v3.13.1/rabbitmq-server-3.13.1-1.el8.noarch.rpm

wget https://github.com/rabbitmq/rabbitmq-server/releases/download/v3.8.5/rabbitmq-server-3.8.5-1.el8.noarch.rpm

image-20240410223529499

3.4.4安裝RabbitMQ簽名檔案

rpm --import https://www.rabbitmq.com/rabbitmq-release-signing-key.asc

image-20240410223556533

3.4.5安裝epel

epel是社群強烈打造的免費開源發行軟體包版本庫。

EPEL,即Extra Packages for Enterprise Linux的簡稱,是為企業級Linux提供的一組高質量的額外軟體包,包括但不限於Red Hat Enterprise Linux (RHEL), CentOS and Scientific Linux (SL), Oracle Enterprise Linux (OEL)。(關於 : EPEL)

yum -y install epel-release

image-20240410223642744

3.4.6安裝socat

socat是一個轉發工具,主要實現不同介面間的轉發,常用的檔案、管道、裝置(終端或調變解調器等)、插座(Unix,IP4,IP6 - raw,UDP,TCP)、SSL、SOCKS4客戶端或代理CONNECT。

yum -y install socat

image-20240410223721336

3.4.7下載RabbitMQ

# 這是舊版本,這裡我們裝最新的版本
# rpm -ivh rabbitmq-server-3.8.5-1.el8.noarch.rpm

rpm -ivh rabbitmq-server-3.13.1-1.el8.noarch.rpm

如果安裝最新的rabbitmq報錯:依賴檢測失敗,轉到3.8Erlong版本

image-20240411002727617

這樣三臺機器的最新版本erlang就安裝完成了。

image-20240411003943415

三臺機器的最新版本rabbitmq就安裝完成了。

image-20240411005615901

3.4.8啟用管理平臺外掛

啟用外掛後,可以視覺化管理RabbitMQ

rabbitmq-plugins enable rabbitmq_management

image-20240411005710700

啟動應用

systemctl start rabbitmq-server

關閉防火牆、禁用防火牆

systemctl stop firewalld
systemctl disable firewalld

關閉SELINUX

getenforce
setenforce 0

image-20240411005915814

3.5建立RabbitMQ使用者並設定許可權

(1)建立新賬戶

# 例子:rabbitmqctl add_user peng 123456
rabbitmqctl add_user 使用者名稱 密碼

(2)設定新賬戶為管理員

# 例子:rabbitmqctl set_user_tags peng administrator
rabbitmqctl set_user_tags 使用者名稱 許可權

(3)授權遠端訪問,分別是訪問許可權、讀許可權、寫許可權。

# 例子:rabbitmqctl set_permissions -p / peng ".*" ".*" ".*"
rabbitmqctl set_permissions -p / 使用者名稱 ".*" ".*" ".*"

(4)重啟服務

systemctl restart rabbitmq-server

image-20240411010531663

3.6登入測試

三臺RabbitMQ安裝完成。

image-20240411010732984

3.7RabbitMQ版本

https://github.com/rabbitmq/rabbitmq-server/releases

安裝最新的RabbitMQ。

image-20240410223118500

3.8Erlong版本

檢視最新Erlong版本

https://packagecloud.io/rabbitmq/erlang

https://github.com/rabbitmq/erlang-rpm/releases

刪除舊版本

# 錯誤
# file /usr/lib64/erlang/releases/start_erl.data from install of erlang-26.2.3-1.el7.x86_64 conflicts with file from package erlang-23.3.4.11-1.el7.x86_64

# 刪除已安裝的erlang舊版本
yum remove erlang-23.3.4.11-1.el7.x86_64


# 刪除已安裝的RabbitMQ舊版本
# find / -name rabbit*
# rm -rf rabbitmq的目錄

systemctl stop rabbitmq-server
yum list | grep rabbitmq
yum -y remove rabbitmq-server.noarch

image-20240411002526553

安裝新版本

檢視最新的erlang版本號

image-20240411003001456

erlang-26.2.3-1.el7.x86_64.rpm裡的el7指的是Centos版本,我的是Centos7。

# 下載最新erlang
wget https://github.com/rabbitmq/erlang-rpm/releases/download/v26.2.3/erlang-26.2.3-1.el7.x86_64.rpm
# 安裝erlang
rpm -ivh erlang-26.2.3-1.el7.x86_64.rpm

這樣就能安裝最新的版本的RabbitMQ。

image-20240411003301966

3.9yum udpate

yum -y install yum-utils
yum clean all
yum-complete-transaction --cleanup-only

package-cleanup --cleandupes
yum -y update --skip-broken

4.配置普通叢集

4.1修改cookie

修改

提示:該cookie檔案只讀的,儲存需要 :wq!

vi /var/lib/rabbitmq/.erlang.cookie

檢視

cat /var/lib/rabbitmq/.erlang.cookie

image-20240411011301319

重啟

sudo service rabbitmq-server stop
sudo service rabbitmq-server start

image-20240411011530479

如果賬戶失效,新增新賬戶即可

# 建立新賬戶
rabbitmqctl add_user longma longma
# 設定新賬戶為管理員
rabbitmqctl set_user_tags longma administrator
# 授權遠端訪問
rabbitmqctl set_permissions -p / longma ".*" ".*" ".*"

4.2rmq2、rmq3節點的hosts設定

如果跟著我的步驟改了,這裡檢查一下即可。

image-20240411011926189

4.3叢集搭建

該例項將rmq2、rmq3加入到rmq1中,因此rmq2、rmq3都要完成以下配置

(1)停止服務
rabbitmqctl stop_app
(2)重置狀態
rabbitmqctl reset
(3)節點加入 --ram記憶體節點
rabbitmqctl join_cluster --ram rabbit@rmq1 
(4)啟動服務
rabbitmqctl start_app

image-20240411012424231

join_cluster命令有一個可選的引數--ram,該引數代表新加入的節點是記憶體節點,預設是磁碟節點。如果是記憶體節點,則所有的佇列、交換器、繫結關係、使用者、訪問許可權和vhost的後設資料都將儲存在記憶體中,如果是磁碟節點,則儲存在磁碟中。記憶體節點可以有更高的效能,但其重啟後所有配置資訊都會丟失,因此RabbitMQ 要求在叢集中至少有一個磁碟節點,其他節點可以是記憶體節點。當記憶體節點離開叢集時,它可以將變更通知到至少一個磁碟節點;然後在其重啟時,再連線到磁碟節點上獲取後設資料資訊。除非是將 RabbitMQ用於RPC 這種需要超低延遲的場景,否則在大多數情況下,RabbitMQ 的效能都是夠用的,可以採用預設的磁碟節點的形式。另外,如果節點以磁碟節點的形式加入,則需要先使用reset命令進行重置,然後才能加入現有群集,重置節點會刪除該節點上存在的所有的歷史資源和資料。採用記憶體節點的形式加入時可以略過reset這一步,因為記憶體上的資料本身就不是持久化的。

5.映象節點

5.1all

如果為所有佇列開啟映象配置,其語法如下:

rabbitmqctl set_policy ha-all "^" '{"ha-mode":"all"}'

5.2exactly

在上面指定了ha-mode 的值為 all ,代表訊息會被同步到所有節點的相同佇列中。這裡我們之所以這樣配置,因為我們本身只有三個節點,因此複製操作的效能開銷比較小。如果叢集有很多節點,那麼此時複製的效能開銷就比較大,此時需要選擇合適的複製係數。通常可以遵循過半寫原則,即對於一個節點數為 n 的叢集,只需要同步到 n/2+1 個節點上即可。此時需要同時修改映象策略為 exactly,並指定複製係數 ha-params,示例命令如下:

rabbitmqctl set_policy ha-two "^" '{"ha-mode":"exactly","ha-params":2,"ha-sync-mode":"automatic"}'

5.4正規表示式

除此之外,RabbitMQ 還支援使用正規表示式來過濾需要進行映象操作的佇列,示例如下:

rabbitmqctl set_policy ha-all "^ha\." '{"ha-mode":"all"}'

6.節點下線

以上介紹的叢集搭建的過程就是服務擴容的過程,如果想要進行服務縮容,即想要把某個節點剔除叢集,有兩種可選方式:

第一種:可以先使用rabbitmqctl stop停止該節點上的服務,然後在其他任意一個節點上執行 forget_cluster_node 命令。這裡以剔除rabbit2為例,此時可以在 rabbit1或rabbit3上執行下面的命令:

rabbitmqctl forget_cluster_node rabbit@rabbit2

第二種方式:先使用 rabbitmqctl stop 停止該節點上的服務,然後再執行 rabbitmqctl reset 這會清空該節點上所有歷史資料,並主動通知叢集中其它節點它將要離開叢集。

7.負載均衡(haproxy)

7.1下載

下載地址:

  • https://www.haproxy.org/#down
  • https://src.fedoraproject.org/repo/pkgs/haproxy/

我的下載地址:

https://src.fedoraproject.org/repo/pkgs/haproxy/haproxy-2.9.4.tar.gz/sha512/a22977f7ceb24325bcbaf531d96aad7b6e8404b026405538e0512a0c7538165736e641a05720e0ca8c9fbec497f0c9935fe0a706a9923e76d34aadd879c64d36/

下載最新的haproxy

image-20240411221633531

下載完畢後上傳root目錄

image-20240411222353251

7.2安裝

解壓

tar xf haproxy-2.9.4.tar.gz

開啟haproxy目錄,

cd haproxy-2.9.4

安裝c++依賴

# 解除安裝:yum remove gcc-c++
yum install gcc-c++ -y

image-20240411222749096

編譯

make TARGET=linux-glibc  PREFIX=/usr/app/haproxy-2.9.4

image-20240411222921028

安裝haproxy

make install PREFIX=/usr/app/haproxy-2.9.4

7.3環境變數

編輯檔案

vi /etc/profile

新增配置,在profile檔案最後加上如下倆行

export HAPROXY_HOME=/usr/app/haproxy-2.9.4
export PATH=$PATH:$HAPROXY_HOME/sbin

使配置環境變數立即生效

source /etc/profile

image-20240411223334384

檢查配置

cat /etc/profile

image-20240411223406781

7.4負載均衡

建立配置檔案:

#  建立資料夾haproxy
mkdir /etc/haproxy

# 建立haproxy.cfg檔案
touch /etc/haproxy/haproxy.cfg  

#編輯haproxy.cfg檔案
vi /etc/haproxy/haproxy.cfg  

image-20240411224019480

haproxy.cfg 配置如下:

global
# 日誌輸出配置、所有日誌都記錄在本機,透過 local0 進行輸出
log 127.0.0.1 local0 info
# 最大連線數
maxconn 4096
# 改變當前的工作目錄
chroot /usr/app/haproxy-2.9.4
# 以指定的 UID 執行 haproxy 程序
uid 99
# 以指定的 GID 執行 haproxy 程序
gid 99
# 以守護進行的方式執行
daemon
# 當前程序的 pid 檔案存放位置
pidfile /usr/app/haproxy-2.9.4/haproxy.pid
# 預設配置
defaults
# 應用全域性的日誌配置
log global
# 使用4層代理模式,7層代理模式則為"http"
mode tcp
# 日誌類別
option tcplog
# 不記錄健康檢查的日誌資訊
option dontlognull
# 3次失敗則認為服務不可用
retries 3
# 每個程序可用的最大連線數
maxconn 2000
# 連線超時
timeout connect 5s
# 客戶端超時
timeout client 120s
# 服務端超時
timeout server 120s
# 繫結配置
listen rabbitmq_cluster
bind :5671
# 配置TCP模式
mode tcp
# 採用加權輪詢的機制進行負載均衡
balance roundrobin
# RabbitMQ 叢集節點配置 5秒請求2次響應成功算正常,3次無響應算當機。權重都是1
server node1 rmq1:5672 check inter 5000 rise 2 fall 3 weight 1
server node2 rmq2:5672 check inter 5000 rise 2 fall 3 weight 1
server node3 rmq3:5672 check inter 5000 rise 2 fall 3 weight 1
# 配置監控頁面
listen monitor
bind :8100
mode http
option httplog
stats enable
stats uri /stats
stats refresh 5s

提示:目錄位置注意修改。

image-20240411224101695

提示:主機配置。

image-20240411224145119

7.5啟動服務

修改haproxy機器別名

# 例子 hostnamectl set-hostname hp1 --static
# 例子 hostnamectl set-hostname hp2 --static
hostnamectl set-hostname 機器別名 --static

修改所有機器hosts檔案

vi /etc/hosts

增加如下配置:

192.168.188.180 rmq1 
192.168.188.181 rmq2
192.168.188.182 rmq3
192.168.188.190 hp1
192.168.188.191 hp2

image-20240411225549109

修改RabbitMQ服務的hosts檔案

image-20240411225841367

啟動RabbitMQ服務

systemctl start rabbitmq-server

關閉防火牆

systemctl stop firewalld
systemctl disable firewalld

啟動haproxy服務:

haproxy -f /etc/haproxy/haproxy.cfg

image-20240411230016359

8.高可用(Keepalived)

8.1安裝Keepalived

我這裡把hp1當做主(MASTER)、把hp2當做備份(BACKUP)

hp1:http://192.168.188.190:8100/stats

hp2:http://192.168.188.191:8100/stats

安裝Keepalived

yum install -y keepalived

image-20240411230837261

刪除原本的配置(如果有的話)

rm -rf /etc/keepalived/keepalived.conf

配置 HAProxy 檢查

vi /etc/keepalived/keepalived.conf

keepalived.conf配置

global_defs {
   # 路由id,主備節點不能相同
   router_id node1
}
# 自定義監控指令碼
vrrp_script chk_haproxy {
    # 指令碼位置
    script "/etc/keepalived/haproxy_check.sh" 
    # 指令碼執行的時間間隔
    interval 5 
    weight 10
}
vrrp_instance VI_1 {
    # Keepalived的角色,MASTER 表示主節點,BACKUP 表示備份節點
    state MASTER  
    # 指定監測的網路卡,可以使用 ifconfig 進行檢視
    interface ens33
    # 虛擬路由的id,主備節點需要設定為相同
    virtual_router_id 1
    # 優先順序,主節點的優先順序需要設定比備份節點高
    priority 100 
    # 設定主備之間的檢查時間,單位為秒 
    advert_int 1 
    # 定義驗證型別和密碼
    authentication { 
        auth_type PASS
        auth_pass 123456
    }
    # 呼叫上面自定義的監控指令碼
    track_script {
        chk_haproxy
    }
    virtual_ipaddress {
        # 虛擬IP地址,可以設定多個
        192.168.188.200  
    }
}

virtual_ipaddress就是我們最終訪問的地址,不需要再去訪問實際的haproxy地址和rabbitmq地址。

備份節點的state為BACKUP,並且要小於MASTER節點的priority

hp1

state MASTER 
priority 100 

hp2

state BACKUP 
priority 99 

image-20240411231230259

8.2配置Keepalived檢查

編輯shell檔案

vi /etc/keepalived/haproxy_check.sh

haproxy_check.sh配置:

#!/bin/bash
# 判斷haproxy是否已經啟動
if [ `ps -C haproxy --no-header | wc -l` -eq 0 ] ; then
    #如果沒有啟動,則啟動
    haproxy -f /etc/haproxy/haproxy.cfg
fi
#睡眠3秒以便haproxy完全啟動
sleep 3
#如果haproxy還是沒有啟動,此時需要將本機的keepalived服務停掉,以便讓VIP自動漂移到另外一臺haproxy
if [ `ps -C haproxy --no-header | wc -l` -eq 0 ]; then
    systemctl stop keepalived
fi

image-20240411232027012

8.3啟動服務

給shell檔案設定執行許可權

chmod +x /etc/keepalived/haproxy_check.sh

分別在hp1和hp2啟動 KeepAlived 服務

systemctl start  keepalived

訪問:

http://192.168.188.190:8100/stats
http://192.168.188.191:8100/stats
http://192.168.188.200:8100/stats

image-20240411234132469

9.驗證故障轉移

如果 haproxy1 已經停止且無法重啟時,KeepAlived服務就會停止,這裡我們直接使用以下命令停止 Keepalived 服務:

# 在hp1上停止keepalived
systemctl stop keepalived

此時再次使用ip addr分別檢視,可以發現haproxy1上的 VIP 已經漂移到haproxy2上。此時對外服務的 VIP 依然可用,代表已經成功地進行了故障轉移。

image-20240412000147694

隨便發了倆次訊息,haproxy已監控到。

image-20240412004132746

如果程式訪問不了虛擬機器部署的虛擬服務(192.168.188.200),並且虛擬機器網路連線使用的是Net模式,可以檢視我的另一篇部落格。

https://www.cnblogs.com/pengboke/p/18130348

192.168.188.200是虛擬IP

 var fac = new ConnectionFactory()
 {            
     HostName = "192.168.188.200",//IP
     Port = 5671,//埠     
     UserName = "peng",
     Password = "123456",
     VirtualHost = "/"
 };

創作不易,感謝支援。

wxzf

相關文章