1 RabbitMQ集羣簡介
RabbitMQ 集羣是一個或多個節點的邏輯分組,每個節點共享用户、虛擬主機、隊列、流、交換機、綁定、運行時參數和其他分佈式狀態。
集羣中的節點名稱必須是唯一的。在集羣中,節點使用節點名稱來識別和相互聯繫。這意味着每個節點名稱的主機名部分必須可以解析。CLI工具也使用節點名稱來識別和尋址節點。當節點啓動時,它會檢查是否已為其分配了節點名稱。如果未顯式配置值,則節點會解析其主機名並在其前面加上rabbit@ 以計算其節點名稱。
RabbitMQ代理操作所需的所有數據/狀態都在所有節點之間複製。消息隊列是此規則的例外,默認情況下消息隊列駐留在一個節點上,但可以從所有節點查看和訪問。要在集羣中的節點之間複製隊列,使用支持複製的隊列類型。
RabbitMQ的集羣部署有兩種模式:普通集羣是一種分佈式集羣,將隊列分散到集羣的各個節點,提高整個集羣的併發能力。鏡像集羣在普通集羣的基礎上,添加了主從備份功能,又稱為主從複製集羣,提高集羣的數據可用性。
鏡像集羣雖然支持主從複製,但主從同步並不是強一致的,某些情況下可能有數據丟失的風險。因此在RabbitMQ的3.8版本以後,推出了新的功能:使用仲裁隊列來代替鏡像集羣,底層採用Raft協議確保主從的數據一致性。請求仍然都是由主節點進行操作,然後同步到從節點中。但是對於任何節點來説,既可能是某個仲裁隊列的主節點,也可能是其它仲裁隊列的從節點。因此也具有分散節點壓力,提高併發訪問的特點。另外如果主節點掛了,其中的某個從節點就會變成主節點,並在其它節點上儘可能創建出新的主節點,保障主從數量一致。一個仲裁隊列的默認數量是5,即一個主節點,4個副本節點,如果集羣中節點數量少於5,比如我們搭建了3個節點的集羣,那麼創建的仲裁隊列就是1主2副本。當然如果集羣中的節點數大於5個的話,那麼就只會在5個節點中創建出1主4副本。
本例即是通過普通集羣加仲裁隊列來實現RabbitMQ的高可用。
2 安裝配置規劃
| 配置項 | 主機一 | 主機二 | 主機三 |
|---|---|---|---|
| IP地址 | 10.10.1.41 | 10.10.1.42 | 10.10.1.43 |
| 主機名稱 | KL1 | KL2 | KL3 |
| 配置用户 | kylin | kylin | kylin |
| 安裝文件目錄 | /home/kylin/Install | /home/kylin/Install | /home/kylin/Install |
| 消息隊列目錄 | /data/rabbitmq | /data/rabbitmq | /data/rabbitmq |
| 相關端口 | 使用默認值 | 使用默認值 | 使用默認值 |
| MQ測試用户 | test/password | ||
| MQ虛擬主機 | test | ||
3 安裝RabbitMQ
3.1 安裝版本説明
RabbitMQ僅3.8及以上版本支持仲裁隊列,因此本例選擇最新版本的RabbitMQ4.1.4版。根據官方網站上RabbitMQ與Erlang的版本兼容性矩陣,Erlang版本選擇27.x中最新的27.3.4.3。
銀河麒麟V10的桌面版和服務器版的安裝體系差異很大,默認已經安裝的包也不同,因此在安裝Erlang之前,銀河麒麟V10的桌面版和服務器版需要安裝不同的包。本例基於以下銀河麒麟版本建立。
Kylin-Desktop-V10-GFB-HWE-Release-020-X86_64
Kylin-Desktop-V10-GFB-020-Release-20.1.3-ARM64
Kylin-Server-V10-GFB-Release-030-X86_64
Kylin-Server-V10-GFB-030-Release-30.1.3-ARM64
3.2 麒麟V10桌面版(GFB)
3.2.1 安裝前準備
使用管理員用户,創建安裝文件目錄。
kylin@KL1:~$ mkdir Install
3.2.2 安裝ncurses
3.2.2.1 使用deb包安裝
銀河麒麟V10桌面版(GFB)默認已安裝libtinfo6、libncurses6、libncursesw6,版本為6.2-0kylin2,需要安裝對應版本的libncurses-dev。本例拿到的是6.2-0kylin2.1版本,因為依賴關係除安裝libncurses-dev外,需要安裝對應版本的libtinfo6、libncurses6、libncursesw6。
使用管理員賬户,執行dpkg -i命令安裝libncurses-dev及其依賴包。
kylin@KL1:~/Install$ sudo dpkg -i libncurses-dev_6.2-0kylin2.1_amd64.deb libtinfo6_6.2-0kylin2.1_amd64.deb libncurses6_6.2-0kylin2.1_amd64.deb libncursesw6_6.2-0kylin2.1_amd64.deb
正在選中未選擇的軟件包 libncurses-dev:amd64。
(正在讀取數據庫 ... 系統當前共安裝有 187718 個文件和目錄。)
準備解壓 libncurses-dev_6.2-0kylin2.1_amd64.deb ...
正在解壓 libncurses-dev:amd64 (6.2-0kylin2.1) ...
準備解壓 libtinfo6_6.2-0kylin2.1_amd64.deb ...
正在解壓 libtinfo6:amd64 (6.2-0kylin2.1) 並覆蓋 (6.2-0kylin2) ...
準備解壓 libncurses6_6.2-0kylin2.1_amd64.deb ...
正在解壓 libncurses6:amd64 (6.2-0kylin2.1) 並覆蓋 (6.2-0kylin2) ...
準備解壓 libncursesw6_6.2-0kylin2.1_amd64.deb ...
正在解壓 libncursesw6:amd64 (6.2-0kylin2.1) 並覆蓋 (6.2-0kylin2) ...
正在設置 libtinfo6:amd64 (6.2-0kylin2.1) ...
正在設置 libncurses6:amd64 (6.2-0kylin2.1) ...
正在設置 libncursesw6:amd64 (6.2-0kylin2.1) ...
正在設置 libncurses-dev:amd64 (6.2-0kylin2.1) ...
正在處理用於 man-db (2.9.1-1kylin0k1) 的觸發器 ...
正在處理用於 libc-bin (2.31-0kylin9.1k20.8) 的觸發器 ...
如果無法獲取麒麟官方安裝包,可以下載debian提供的包,版本為6.2+20201114-2或其他接近版本。可以使用中科大的鏡像網站。
3.2.2.2 使用源代碼安裝
從GNU官方網站下載最新版本的源代碼包ncurses-6.5.tar.gz,放置到安裝目錄。解壓縮後進入解壓後的目錄,執行configure命令。
kylin@KL1:~/Install$ tar -zxf ncurses-6.5.tar.gz
kylin@KL1:~/Install$ cd ncurses-6.5/
kylin@KL1:~/Install/ncurses-6.5$ ./configure
checking for ggrep... no
checking for grep... grep
checking for egrep... grep -E
Configuring NCURSES 6.5 ABI 6 (Fri Sep 19 10:43:14 CST 2025)
…………
這裏很多提示信息,此處省略。
…………
** Configuration summary for NCURSES 6.5 20240427:
extended funcs: yes
xterm terminfo: xterm-new
bin directory: /usr/bin
lib directory: /usr/lib
include directory: /usr/include
man directory: /usr/share/man
terminfo directory: /usr/share/terminfo
繼續執行make指令進行編譯。
kylin@KL1:~/Install/ncurses-6.5$ make
( cd man && make DESTDIR="" RPATH_LIST="/usr/lib" all )
make[1]: 進入目錄“/home/kylin/Install/ncurses-6.5/man”
/bin/sh ./MKterminfo.sh ./terminfo.head ./../include/Caps ./../include/Caps-ncurses ./terminfo.tail >terminfo.5
…………
這裏很多提示信息,此處省略。
…………
compiling demo (obj_s)
/usr/bin/g++ -o demo ../objects/demo.o -L../lib -lncurses++w -L../lib -lformw -lmenuw -lpanelw -lncursesw -lutil -DHAVE_CONFIG_H -DBUILDING_NCURSES_CXX -I../c++ -I. -I../include -D_DEFAULT_SOURCE -D_XOPEN_SOURCE=600 -DNDEBUG -O2 -DNCURSES_STATIC
make[1]: 離開目錄“/home/kylin/Install/ncurses-6.5/c++”
編譯成功後,用管理員賬户執行make install安裝。
kylin@KL1:~/Install/ncurses-6.5$ sudo make install
( cd man && make DESTDIR="" RPATH_LIST="/usr/lib" install )
make[1]: 進入目錄“/home/kylin/Install/ncurses-6.5/man”
/bin/sh ../edit_man.sh normal installing /usr/share/man . terminfo.5 *-config.1 ./*.[0-9]* ...made /home/kylin/Install/ncurses-6.5/man_alias.sed
…………
這裏很多提示信息,此處省略。
…………
installing ./cursesapp.h in /usr/include
installing ./cursesf.h in /usr/include
installing ./cursesm.h in /usr/include
installing ./cursesp.h in /usr/include
installing ./cursesw.h in /usr/include
installing ./cursslk.h in /usr/include
installing etip.h in /usr/include
make[1]: 離開目錄“/home/kylin/Install/ncurses-6.5/c++”
3.2.3 安裝OpenSSL
從OpenSSL官方網站下載指定版本的源代碼包openssl-1.1.1w.tar.gz,放置到安裝目錄。解壓縮openssl-OpenSSL_1_1_1w.zip,進入解壓後的目錄。
kylin@KL1:~/Install$ unzip openssl-OpenSSL_1_1_1w.zip
Archive: openssl-OpenSSL_1_1_1w.zip
e04bd3433fd84e1861bf258ea37928d9845e6a86
creating: openssl-OpenSSL_1_1_1w/
inflating: openssl-OpenSSL_1_1_1w/ACKNOWLEDGEMENTS
inflating: openssl-OpenSSL_1_1_1w/AUTHORS
inflating: openssl-OpenSSL_1_1_1w/CHANGES
inflating: openssl-OpenSSL_1_1_1w/CONTRIBUTING
…………
這裏很多提示信息,此處省略。
…………
inflating: openssl-OpenSSL_1_1_1w/util/shlib_wrap.sh.in
inflating: openssl-OpenSSL_1_1_1w/util/su-filter.pl
inflating: openssl-OpenSSL_1_1_1w/util/unlocal_shlib.com.in
creating: openssl-OpenSSL_1_1_1w/wycheproof/
kylin@KL1:~/Install$ cd openssl-OpenSSL_1_1_1w/
執行config命令指定安裝目錄進行配置。
kylin@KL1:~/Install/openssl-OpenSSL_1_1_1w$ ./config --prefix=/usr/local/openssl
Operating system: x86_64-whatever-linux2
Configuring OpenSSL version 1.1.1w (0x1010117fL) for linux-x86_64
Using os-specific seed configuration
Creating configdata.pm
Creating Makefile
**********************************************************************
*** ***
*** OpenSSL has been successfully configured ***
*** ***
*** If you encounter a problem while building, please open an ***
*** issue on GitHub <https://github.com/openssl/openssl/issues> ***
*** and include the output from the following command: ***
*** ***
*** perl configdata.pm --dump ***
*** ***
*** (If you are new to OpenSSL, you might want to consult the ***
*** 'Troubleshooting' section in the INSTALL file first) ***
*** ***
**********************************************************************
繼續執行make指令進行編譯。
kylin@KL1:~/Install/openssl-OpenSSL_1_1_1w$ make
/usr/bin/perl "-I." -Mconfigdata "util/dofile.pl" \
"-oMakefile" include/crypto/bn_conf.h.in > include/crypto/bn_conf.h
/usr/bin/perl "-I." -Mconfigdata "util/dofile.pl" \
"-oMakefile" include/crypto/dso_conf.h.in > include/crypto/dso_conf.h
/usr/bin/perl "-I." -Mconfigdata "util/dofile.pl" \
"-oMakefile" include/openssl/opensslconf.h.in > include/openssl/opensslconf.h
make depend && make _all
…………
這裏很多提示信息,此處省略。
…………
/usr/bin/perl "-I." -Mconfigdata "util/dofile.pl" \
"-oMakefile" util/shlib_wrap.sh.in > "util/shlib_wrap.sh"
chmod a+x util/shlib_wrap.sh
make[1]: Leaving directory '/home/kylin/Install/openssl-OpenSSL_1_1_1w'
編譯成功後,用管理員賬户執行make install安裝。
kylin@KL1:~/Install/openssl-OpenSSL_1_1_1w$ sudo make install
make depend && make _build_libs
make[1]: Entering directory '/home/kylin/Install/openssl-OpenSSL_1_1_1w'
make[1]: Leaving directory '/home/kylin/Install/openssl-OpenSSL_1_1_1w'
make[1]: Entering directory '/home/kylin/Install/openssl-OpenSSL_1_1_1w'
make[1]: Nothing to be done for '_build_libs'.
make[1]: Leaving directory '/home/kylin/Install/openssl-OpenSSL_1_1_1w'
…………
這裏很多提示信息,此處省略。
…………
/usr/local/openssl/share/doc/openssl/html/man7/SM2.html
/usr/local/openssl/share/doc/openssl/html/man7/ssl.html
/usr/local/openssl/share/doc/openssl/html/man7/X25519.html
/usr/local/openssl/share/doc/openssl/html/man7/X448.html -> /usr/local/openssl/share/doc/openssl/html/man7/X25519.html
/usr/local/openssl/share/doc/openssl/html/man7/x509.html
3.3 麒麟V10高級服務器版(GFB)
3.3.1 安裝前準備
銀河麒麟V10高級服務器版,允許使用root直接登錄,這裏安全起見,創建用户kylin並加入wheel組,作為管理員用户使用。
[root@localhost ~]# adduser kylin
[root@localhost ~]# passwd kylin
更改用户 kylin 的密碼 。
新的 密碼:
重新輸入新的 密碼:
passwd:所有的身份驗證令牌已經成功更新。
[root@localhost ~]# usermod -aG wheel kylin
再使用root用户創建/data共享目錄。
[root@localhost ~]# mkdir /data
[root@localhost ~]# chmod a+rwx /data
[root@localhost ~]# chmod -t /data
使用root用户修改主機名,並重新登錄。
[root@localhost ~]# hostnamectl set-hostname KL1
[root@localhost ~]# logout
使用kylin用户創建目錄Install用於放置所有安裝文件。
[kylin@KL1 ~]$ mkdir Install
3.3.2 安裝ncurses
在麒麟V10高級服務器版擴展盤中可以找到ncurses-devel的RPM包,其中x86版文件名為“ncurses-devel-6.2-3.gfb03.ky10.x86_64.rpm”,ARM版文件名為“ncurses-devel-6.2-3.gfb03.ky10.aarch64.rpm”。使用管理員賬户安裝RPM包。
[kylin@KL1 Install]$ sudo rpm -i ncurses-devel-6.2-3.gfb03.ky10.x86_64.rpm
警告:ncurses-devel-6.2-3.gfb03.ky10.x86_64.rpm: 頭V4 RSA/SHA1 Signature, 密鑰 ID 34fe765a: NOKEY
3.4 安裝Erlang
從Erlang官方網站下載指定版本的源代碼包otp_src_27.3.4.3.tar.gz,放置到安裝目錄。解壓縮安裝包後進入解壓後的目錄,執行configure命令。
kylin@KL1:~/Install$ tar -zxf otp_src_27.3.4.3.tar.gz
kylin@KL1:~/Install$ cd otp_src_27.3.4.3/
kylin@KL1:~/Install/otp_src_27.3.4.3$ ./configure
=== Running configure in /home/kylin/Install/otp_src_27.3.4.3/erts ===
./configure --disable-option-checking --cache-file=/dev/null --srcdir="/home/kylin/Install/otp_src_27.3.4.3/erts"
checking build system type... x86_64-pc-linux-gnu
checking host system type... x86_64-pc-linux-gnu
checking target system type... x86_64-pc-linux-gnu
checking for gcc... gcc
…………
這裏很多提示信息,此處省略。
…………
Please check that wx-config is in path, the directory
where wxWidgets libraries are installed (returned by
'wx-config --libs' or 'wx-config --static --libs' command)
is in LD_LIBRARY_PATH or equivalent variable and
wxWidgets version is 3.0.2 or above.
*********************************************************************
在配置Erlang的時候會提示因為缺少ODBC library、GLU headers等,導致odbc、wx等不可用,這個不影響RabbitMQ的一般使用,暫時不用理會。
繼續執行make指令進行編譯。
kylin@KL1:~/Install/otp_src_27.3.4.3$ make
MAKE depend
make[1]: 進入目錄“/home/kylin/Install/otp_src_27.3.4.3/erts/emulator”
MAKE generate
make[2]: 進入目錄“/home/kylin/Install/otp_src_27.3.4.3/erts/emulator”
GEN x86_64-pc-linux-gnu/opt/jit/OPCODES-GENERATED
GEN x86_64-pc-linux-gnu/opt/jit/beam_asm_global.hpp
…………
這裏很多提示信息,此處省略。
…………
GEN /home/kylin/Install/otp_src_27.3.4.3/bin/start.script
GEN /home/kylin/Install/otp_src_27.3.4.3/bin/start_sasl.script
GEN /home/kylin/Install/otp_src_27.3.4.3/bin/start_clean.script
make[2]: “/home/kylin/Install/otp_src_27.3.4.3/bin/no_dot_erlang.script”已是最新。
make[2]: 離開目錄“/home/kylin/Install/otp_src_27.3.4.3/erts/start_scripts”
make[1]: 離開目錄“/home/kylin/Install/otp_src_27.3.4.3/erts”
編譯成功後,用管理員賬户執行make install安裝。
kylin@KL1:~/Install/otp_src_27.3.4.3$ sudo make install
MAKE erl_interface_build
make[1]: 進入目錄“/home/kylin/Install/otp_src_27.3.4.3/lib/erl_interface”
=== Entering application erl_interface
make[2]: 進入目錄“/home/kylin/Install/otp_src_27.3.4.3/lib/erl_interface/src”
MAKE opt
make[3]: 進入目錄“/home/kylin/Install/otp_src_27.3.4.3/lib/erl_interface/src”
make[3]: 對“opt”無需做任何事。
…………
這裏很多提示信息,此處省略。
…………
ln -s ../lib/erlang/bin/run_erl run_erl
ln -s ../lib/erlang/bin/to_erl to_erl
ln -s ../lib/erlang/bin/dialyzer dialyzer
ln -s ../lib/erlang/bin/typer typer
ln -s ../lib/erlang/bin/escript escript
ln -s ../lib/erlang/bin/ct_run ct_run
測試Erlang,使用erl命令進入Erlang控制枱,使用crypto:start測試OpenSSL,使用halt命令退出。
kylin@KL1:~$ erl
Erlang/OTP 27 [erts-15.2.7.2] [source] [64-bit] [smp:4:4] [ds:4:4:10] [async-threads:1]
Eshell V15.2.7.2 (press Ctrl+G to abort, type help(). for help)
1> crypto:start().
ok
2> halt().
3.5 安裝RabbitMQ
解壓縮rabbitmq-server-generic-unix-4.1.4.tar.xz,將解壓後的目錄移動到指定位置。
kylin@KL1:~/Install$ tar -xf rabbitmq-server-generic-unix-4.1.4.tar.xz
kylin@KL1:~/Install$ mv rabbitmq_server-4.1.4 /data/rabbitmq
編輯配置文件/etc/profile,將/data/rabbitmq/sbin加入到PATH環境變量中,使用source /etc/profile命令更新環境變量。
kylin@KL1:/data/rabbitmq$ sudo vi /etc/profile
…………
其他配置內容。
…………
export PATH=$PATH:/data/rabbitmq/sbin
kylin@KL1:/data/rabbitmq$ source /etc/profile
使用rabbitmq-server -detached以後台服務方式啓動RabbitMQ,使用rabbitmqctl status查看RabbitMQ狀態,可以看到RabbitMQ開啓了5672端口和25672端口,分別服務於amqp和clustering協議。
kylin@KL1:~$ rabbitmq-server -detached
kylin@KL1:/data/rabbitmq$ rabbitmqctl status
Status of node rabbit@KL1 ...
Runtime
OS PID: 616311
…………
此處有很多狀態信息,此處忽略。
…………
Listeners
Interface: [::], port: 25672, protocol: clustering, purpose: inter-node and CLI tool communication
Interface: [::], port: 5672, protocol: amqp, purpose: AMQP 0-9-1 and AMQP 1.0
使用rabbitmqctl start_app和rabbitmq-plugins enable rabbitmq_management命令開啓管理控制枱,再使用rabbitmqctl status查看RabbitMQ狀態,可以看到15672端口已經打開,此時可以使用瀏覽器管理消息隊列。
kylin@KL1:/data/rabbitmq$ rabbitmqctl start_app
Starting node rabbit@KL1 ...
kylin@KL1:/data/rabbitmq$ rabbitmq-plugins enable rabbitmq_management
Enabling plugins on node rabbit@KL1:
rabbitmq_management
The following plugins have been configured:
rabbitmq_management
rabbitmq_management_agent
rabbitmq_web_dispatch
Applying plugin configuration to rabbit@KL1...
The following plugins have been enabled:
rabbitmq_management
rabbitmq_management_agent
rabbitmq_web_dispatch
started 3 plugins.
kylin@KL1:~$ rabbitmqctl status
Status of node rabbit@KL1 ...
Runtime
…………
此處有很多狀態信息,此處忽略。
…………
Interface: [::], port: 15672, protocol: http, purpose: HTTP API
Interface: [::], port: 25672, protocol: clustering, purpose: inter-node and CLI tool communication
Interface: [::], port: 5672, protocol: amqp, purpose: AMQP 0-9-1 and AMQP 1.0
3.6 註冊RabbitMQ為服務
使用管理員用户編輯/etc/systemd/system/rabbitmq.service文件,在文件中加入如下內容。
kylin@KL1 ~$ sudo vi /etc/systemd/system/rabbitmq.service
[Unit]
Description = RabbitMQ Server
After = network.target
[Service]
Type = simple
User = kylin
Group = kylin
ExecStart = /data/rabbitmq/sbin/rabbitmq-server
ExecStop = /data/rabbitmq/sbin/rabbitmqctl stop
Restart = on-failure
RestartSec = 60s
LimitNOFILE = 65536
[Install]
WantedBy = multi-user.target
重新加載服務,將服務設置為開機啓動。
kylin@KL1 ~$ sudo systemctl daemon-reload
kylin@KL1 ~$ sudo systemctl enable rabbitmq
Created symlink /etc/systemd/system/multi-user.target.wants/rabbitmq.service → /etc/systemd/system/rabbitmq.service.
啓動服務並查看服務狀態。如果之前RabbitMQ已啓動,先結束進程。
kylin@KL1 ~$ ps -AL|grep beam
2212 2212 ? 00:00:00 beam.smp
kylin@KL1 ~$ kill 2212
kylin@KL1 ~$ sudo systemctl start rabbitmq
kylin@KL1 ~$ sudo systemctl status rabbitmq
● rabbitmq.service - RabbitMQ Server
Loaded: loaded (/etc/systemd/system/rabbitmq.service; enabled; vendor preset: disabled)
Active: active (running) since Wed 2025-09-24 10:24:47 CST; 2s ago
Main PID: 1012826 (rabbitmq-server)
Tasks: 26
Memory: 124.6M
CGroup: /system.slice/rabbitmq.service
├─1012826 /bin/sh /data/rabbitmq/sbin/rabbitmq-server
├─1012833 /usr/local/lib/erlang/erts-14.2.5.11/bin/beam.smp -W w -MBas ageffcbf -MHas ageffcbf -MBlmbcs 512 -MHlmbcs 512 -MMmcs 30 -pc unicode -P 1048576 -t 5000000 -stbt db -zdbbl >
├─1012839 erl_child_setup 65536
├─1012858 sh -s disksup
├─1012860 /usr/local/lib/erlang/lib/os_mon-2.9.1/priv/bin/memsup
├─1012861 /usr/local/lib/erlang/lib/os_mon-2.9.1/priv/bin/cpu_sup
├─1012862 /usr/local/lib/erlang/erts-14.2.5.11/bin/inet_gethost 4
├─1012863 /usr/local/lib/erlang/erts-14.2.5.11/bin/inet_gethost 4
└─1012916 /bin/sh -s rabbit_disk_monitor
4 配置RabbitMQ集羣
4.1 修改hosts文件
修改/etc/hosts文件,將集羣涉及的主機名稱添加到hosts文件中。
kylin@KL1~$ sudo vi /etc/hosts
127.0.0.1 localhost
10.10.1.41 KL1
10.10.1.42 KL2
10.10.1.43 KL3
4.2 開放防火牆端口
麒麟高級服務器版默認開啓了防火牆,需要開放RabbitMQ相關的端口,包括4369(EPMD)、5671-5672(AMQP)、15672(管理頁面)、25672(節點間通訊)、35672-35682(CLI工具)等,以上端口均為TCP協議。
[kylin@KL1 ~]$ sudo firewall-cmd --add-port=4369/tcp --permanent
success
[kylin@KL1 ~]$ sudo firewall-cmd --add-port=5671-5672/tcp --permanent
success
[kylin@KL1 ~]$ sudo firewall-cmd --add-port=15672/tcp --permanent
success
[kylin@KL1 ~]$ sudo firewall-cmd --add-port=25672/tcp --permanent
success
[kylin@KL1 ~]$ sudo firewall-cmd --add-port=35672-35682/tcp --permanent
success
[kylin@KL1 ~]$ sudo firewall-cmd --reload
success
[kylin@KL1 ~]$ sudo firewall-cmd --list-ports
4369/tcp 15672/tcp 25672/tcp 35672-35682/tcp 5671-5672/tcp
4.3 複製cookie文件
將.erlang.cookie從主機服務器複製到其他服務器相同目錄。本例中.erlang.cookie文件在kylin用户目錄下。如果提示沒有權限,需要先修改從機上的文件權限。
kylin@KL1:~$ scp .erlang.cookie kylin@KL2:/home/kylin
kylin@KL2's password:
.erlang.cookie 100% 20 7.8KB/s 00:00
修改.erlang.cookie文件之前如果已經用rabbitmq-server啓動了消息隊列,在修改.erlang.cookie文件會無法使用rabbitmqctl控制,需要結束進程,rabbitmq的進程名稱為beam.smp。
[kylin@KL1 ~]$ ps -AL|grep beam.smp
33029 33029 ? 00:00:00 beam.smp
[kylin@KL5 ~]$ kill 33029
4.4 將從機加入集羣
分別啓動主機和從機的服務後,在從機上使用rabbitmqctl stop_app指令停止應用,使用rabbitmqctl join_cluster指令將從機加入主機集羣,再使用rabbitmqctl start_app指令啓動應用。此時可以使用rabbitmqctl cluster_status指令查看集羣狀態。
kylin@KL2:~$ rabbitmqctl stop_app
Stopping rabbit application on node rabbit@KL2 ...
kylin@KL2:~$ rabbitmqctl join_cluster rabbit@KL1
Clustering node rabbit@KL2 with rabbit@KL1
kylin@KL2:~$ rabbitmqctl start_app
Starting node rabbit@KL2 ...
kylin@KL2:~$ rabbitmqctl cluster_status
Cluster status of node rabbit@KL2 ...
Basics
Cluster name: rabbit@KL2
Total CPU cores available cluster-wide: 8
Cluster Tags
(none)
Disk Nodes
rabbit@KL1
rabbit@KL2
Running Nodes
rabbit@KL1
rabbit@KL2
Versions
rabbit@KL1: RabbitMQ 4.1.4 on Erlang 27.3.4.3
rabbit@KL2: RabbitMQ 4.1.4 on Erlang 27.3.4.3
CPU Cores
Node: rabbit@KL1, available CPU cores: 4
Node: rabbit@KL2, available CPU cores: 4
Maintenance status
Node: rabbit@KL1, status: not under maintenance
Node: rabbit@KL2, status: not under maintenance
…………
此處有很多狀態信息,此處忽略。
…………
此時,集羣已經建立,但模式為普通模式,下一步需要將隊列配置為鏡像模式。配置可以採用管理頁面方式,也可以使用命令行方式配置。
4.5 增加測試用户
正常情況下在本機可以使用默認用户guest登錄管理頁面,但guest用户默認被禁止在本機以外登錄管理頁面,此時可以先用命令行方式增加虛擬主機、增加用户、設置角色、設置權限,在通過新建的用户遠程登錄管理頁面。
kylin@KL1:~$ rabbitmqctl add_vhost /test
Adding vhost "/test" ...
kylin@KL1:~$ rabbitmqctl add_user test password
Adding user "test" ...
kylin@KL1:~$ rabbitmqctl set_user_tags test administrator
Setting tags for user "test" to [administrator] ...
kylin@KL1:~$ rabbitmqctl set_permissions -p /test test ".*" ".*" ".*"
Setting permissions for user "test" in vhost "/test" ...
4.6 創建仲裁隊列
使用瀏覽器打開主機的配置頁面,創建需要的交換機和消息隊列等,在創建消息隊列時選擇quorum類型。
如果是使用程序創建消息隊列,在創建方法中的arguments參數中,設置“x-queue-type”值為“quorum”。
5 集羣切換測試
集羣啓動-後,連接管理頁面可以查看集羣狀態、隊列狀態,此時隊列顯示主節點為KL1,KL1為集羣主機,KL2、KL3為集羣從機。
在正常狀態下,測試向消息隊列dataQueue發送了10條數據。
通過暫停虛擬機的方式,將KL1主機暫停。在KL1主機暫停的最初十幾秒內,從機上的消息隊列暫時不可連接,管理頁面也沒有響應,應該在切換集羣主從。之後可正常連接從機上的消息隊列,收發消息,管理頁面可以看到KL1節點變成停止狀態,消息隊列顯示主節點為KL3,KL3為集羣主機。
在KL1故障狀態下,向消息隊列dataQueue又發送了6條數據,現在KL2顯示共有16條數據。
通過查看運行日誌,可以看到節點KL3已經發現KL1無法連接了。
kylin@KL3:~$ tail -f /data/rabbitmq/var/log/rabbitmq/rabbit@KL3.log
2025-09-29 11:47:38.441999+08:00 [notice] <0.15253.0> queue 'alarmQueue' in vhost '/test': candidate -> leader in term: 2 machine version: 7, last applied 2
2025-09-29 11:47:38.625921+08:00 [notice] <0.15237.0> queue 'commandQueue' in vhost '/test': candidate -> leader in term: 2 machine version: 7, last applied 5
2025-09-29 11:47:38.836939+08:00 [notice] <0.15245.0> queue 'answerQueue' in vhost '/test': candidate -> leader in term: 2 machine version: 7, last applied 2
2025-09-29 11:47:39.035406+08:00 [notice] <0.15261.0> queue 'dataQueue' in vhost '/test': candidate -> leader in term: 2 machine version: 7, last applied 14
2025-09-29 11:47:39.085129+08:00 [notice] <0.15269.0> queue 'faultQueue' in vhost '/test': candidate -> leader in term: 2 machine version: 7, last applied 2
2025-09-29 11:48:34.480926+08:00 [error] <0.611.0> ** Node rabbit@KL1 not responding **
2025-09-29 11:48:34.480926+08:00 [error] <0.611.0> ** Removing (timedout) connection **
2025-09-29 11:48:34.480926+08:00 [error] <0.611.0>
2025-09-29 11:48:34.481448+08:00 [info] <0.1310.0> rabbit on node rabbit@KL1 down
2025-09-29 11:48:34.481730+08:00 [warning] <0.18251.0> Management delegate query returned errors:
2025-09-29 11:48:34.481730+08:00 [warning] <0.18251.0> [{<31743.492.0>,{exit,{nodedown,rabbit@KL1},[]}}]
2025-09-29 11:48:34.482387+08:00 [warning] <0.1480.0> Management delegate query returned errors:
2025-09-29 11:48:34.482387+08:00 [warning] <0.1480.0> [{<31743.492.0>,{exit,{nodedown,rabbit@KL1},[]}}]
2025-09-29 11:48:41.489553+08:00 [info] <0.1310.0> node rabbit@KL1 down: net_tick_timeout
使用命令行方式,也可以看到集羣節點包括KL1、KL2和KL3,但目前只有KL2、KL3運行。
kylin@KL3:~$ rabbitmqctl cluster_status
Cluster status of node rabbit@KL3 ...
Basics
Cluster name: rabbit@KL3
Total CPU cores available cluster-wide: 2
Cluster Tags
(none)
Disk Nodes
rabbit@KL1
rabbit@KL2
rabbit@KL3
Running Nodes
rabbit@KL2
rabbit@KL3…………
這裏很多狀態信息,此處省略。
…………
此時恢復虛擬機,將KL1主機恢復並接入。此時發生了集羣網絡分區,即KL1處於一個分區,KL2、KL3處於一個分區。
此時查看隊列,發現共有26條,實際上包含KL1所在分區在KL1斷網前收到的10條消息,KL2、KL3所在分區在KL1斷網前收到的10條消息和KL1斷網後收到的6條消息,其中KL1斷網前的10條消息被重複計算了。
可以在KL1上使用rabbitmqctl stop_app、rabbitmqctl start_app重啓動消息隊列服務的方式完成分區消除。之後集羣狀態恢復,消息隊列中消息數量恢復為16條。
在rabbitmq.conf文件中配置cluster_partition_handling = autoheal參數,可以使得集羣恢復時,自動解決網絡分區問題。
kylin@KL1:~$ vi /data/rabbitmq/etc/rabbitmq/rabbitmq.conf
cluster_partition_handling = autoheal
使用autoheal配置的集羣,在集羣中主機恢復後,可以消除網絡分區,自動恢復集羣。
2025-09-29 15:03:26.331319+08:00 [error] <0.257.0> ** Node rabbit@KL1 not responding **
2025-09-29 15:03:26.331319+08:00 [error] <0.257.0> ** Removing (timedout) connection **
2025-09-29 15:03:26.331319+08:00 [error] <0.257.0>
2025-09-29 15:03:26.331567+08:00 [info] <0.491.0> rabbit on node rabbit@KL1 down
2025-09-29 15:03:26.331699+08:00 [warning] <0.1045.0> Management delegate query returned errors:
2025-09-29 15:03:26.331699+08:00 [warning] <0.1045.0> [{<24597.678.0>,{exit,{nodedown,rabbit@KL1},[]}}]
2025-09-29 15:03:26.331785+08:00 [warning] <0.741.0> Management delegate query returned errors:
2025-09-29 15:03:26.331785+08:00 [warning] <0.741.0> [{<24597.678.0>,{exit,{nodedown,rabbit@KL1},[]}}]
2025-09-29 15:03:33.343042+08:00 [info] <0.491.0> node rabbit@KL1 down: net_tick_timeout
2025-09-29 15:03:54.352322+08:00 [info] <0.491.0> node rabbit@KL1 up
2025-09-29 15:03:54.395179+08:00 [info] <0.491.0> Autoheal: I am the winner, waiting for [rabbit@KL1] to stop
2025-09-29 15:04:55.798338+08:00 [info] <0.491.0> rabbit on node rabbit@KL1 up
2025-09-29 15:04:56.269645+08:00 [info] <0.556.0> queue 'answerQueue' in vhost '/test': granting vote for {'/test_answerQueue',rabbit@KL1} with last {index, term} {8,7} for term 8 previous term was 7
2025-09-29 15:04:56.286039+08:00 [info] <0.556.0> queue 'answerQueue' in vhost '/test': detected a new leader {'/test_answerQueue',rabbit@KL1} in term 8
6 參考文獻
https://www.rabbitmq.com/docs/which-erlang
https://www.rabbitmq.com/docs/4.0
https://rabbitmq.cn/docs/
https://www.cnblogs.com/studyjobs/p/17744247.html
https://github.com/rabbitmq/rabbitmq-server/blob/v3.8.9/docs/rabbitmq.conf.example