閱讀目錄: 準備工作 搭建 RabbitMQ Server 單機版 RabbitMQ Server 高可用集群相關概念 搭建 RabbitMQ Server 高可用集群 搭建 HAProxy 負載均衡 因為公司測試伺服器暫不能用,只能在自己電腦上重新搭建一下 RabbitMQ Server 高可用集 ...
閱讀目錄:
- 準備工作
- 搭建 RabbitMQ Server 單機版
- RabbitMQ Server 高可用集群相關概念
- 搭建 RabbitMQ Server 高可用集群
- 搭建 HAProxy 負載均衡
因為公司測試伺服器暫不能用,只能在自己電腦上重新搭建一下 RabbitMQ Server 高可用集群,正好把這個過程記錄下來,以便日後查看。
公司測試伺服器上的 RabbitMQ 集群,我搭建的是三台伺服器,因為自己電腦空間有限,這邊只能搭建兩台伺服器用作高可用集群,用的是 Vagrant 虛擬機管理工具。
環境介紹:
RabbitMQ | 節點 | IP 地址 | 工作模式 |
---|---|---|---|
node1 | 192.168.1.50 | DISK | CentOS 7.0 - 64位 |
node2 | 192.168.1.51 | DISK | CentOS 7.0 - 64位 |
整體架構:
1. 準備工作
首先,在node1
伺服器上,修改vi /etc/hostname
:
node1
在node2
伺服器上,修改vi /etc/hostname
:
node2
然後在node1
伺服器上,修改vi /etc/hosts
:
node1 192.168.1.50
node2 192.168.1.51
127.0.0.1 node1
::1 node1
在node2
伺服器上,修改vi /etc/hosts
:
192.168.1.50 node1
192.168.1.51 node2
127.0.0.1 node2
::1 node2
然後查看下hostnamectl status
,如果不正確的話,需要再進行設置下:
[root@node1 ~]# hostnamectl status
Static hostname: node1
Icon name: computer-vm
Chassis: vm
Machine ID: 241163503ce842c489360d0a48a606fc
Boot ID: cdb59c025cb447e3afed7317af78979e
Virtualization: oracle
Operating System: CentOS Linux 7 (Core)
CPE OS Name: cpe:/o:centos:centos:7
Kernel: Linux 3.10.0-229.el7.x86_64
Architecture: x86_64
[root@node1 ~]# hostnamectl --static set-hostname node1
為了後面我們安裝的順利,我們最好再配置一下代理:
[root@node1 ~]# export http_proxy=http://192.168.1.44:1087;export https_proxy=http://192.168.1.44:1087;
[root@node1 ~]# curl ip.cn
當前 IP:104.245.13.31 來自:美國 Linost
2. 搭建 RabbitMQ Server 單機版
下麵以node1
伺服器做演示示例。
首先,更新軟體包和存儲庫:
[root@node1 ~]# yum -y update
然後安裝 Erlang(RabbitMQ 運行需要 Erlang 環境):
[root@node1 ~]# vi /etc/yum.repos.d/rabbitmq-erlang.repo
[root@node1 ~]# [rabbitmq-erlang]
name=rabbitmq-erlang
baseurl=https://dl.bintray.com/rabbitmq/rpm/erlang/20/el/7
gpgcheck=1
gpgkey=https://dl.bintray.com/rabbitmq/Keys/rabbitmq-release-signing-key.asc
repo_gpgcheck=0
enabled=1
[root@node1 ~]# yum -y install erlang socat
然後安裝 RabbitMQ Server:
[root@node1 ~]# mkdir -p ~/download && cd ~/download
[root@node1 download]# wget https://www.rabbitmq.com/releases/rabbitmq-server/v3.6.10/rabbitmq-server-3.6.10-1.el7.noarch.rpm
[root@node1 download]# rpm --import https://www.rabbitmq.com/rabbitmq-release-signing-key.asc
[root@node1 download]# rpm -Uvh rabbitmq-server-3.6.10-1.el7.noarch.rpm
卸載 RabbitMQ 命令:
[root@node1 ~]# rpm -e rabbitmq-server-3.6.10-1.el7.noarch
安裝好之後,就可以啟動 RabbitMQ Server 了:
[root@node1 download]# systemctl start rabbitmq-server
也可以添加到系統服務中啟動:
[root@node1 download]# systemctl enable rabbitmq-server
Created symlink from /etc/systemd/system/multi-user.target.wants/rabbitmq-server.service to /usr/lib/systemd/system/rabbitmq-server.service.
啟動成功之後,我們可以查看下 RabbitMQ Server 的狀態:
[root@node1 download]# systemctl status rabbitmq-server
● rabbitmq-server.service - RabbitMQ broker
Loaded: loaded (/usr/lib/systemd/system/rabbitmq-server.service; disabled)
Active: active (running) since 五 2018-04-27 04:44:31 CEST; 3min 27s ago
Process: 17216 ExecStop=/usr/sbin/rabbitmqctl stop (code=exited, status=0/SUCCESS)
Main PID: 17368 (beam.smp)
Status: "Initialized"
CGroup: /system.slice/rabbitmq-server.service
├─17368 /usr/lib64/erlang/erts-9.3/bin/beam.smp -W w -A 64 -P 1048576 -t 5000000 -stbt db -zdbbl 32000 -K true -- -root /usr/lib64/erlang -progname erl -- -home /var/lib/rabbitmq -- -pa /usr...
├─17521 /usr/lib64/erlang/erts-9.3/bin/epmd -daemon
├─17655 erl_child_setup 1024
├─17675 inet_gethost 4
└─17676 inet_gethost 4
4月 27 04:44:30 node1 rabbitmq-server[17368]: RabbitMQ 3.6.10. Copyright (C) 2007-2017 Pivotal Software, Inc.
4月 27 04:44:30 node1 rabbitmq-server[17368]: ## ## Licensed under the MPL. See http://www.rabbitmq.com/
4月 27 04:44:30 node1 rabbitmq-server[17368]: ## ##
4月 27 04:44:30 node1 rabbitmq-server[17368]: ########## Logs: /var/log/rabbitmq/[email protected]
4月 27 04:44:30 node1 rabbitmq-server[17368]: ###### ## /var/log/rabbitmq/[email protected]
4月 27 04:44:30 node1 rabbitmq-server[17368]: ##########
4月 27 04:44:30 node1 rabbitmq-server[17368]: Starting broker...
4月 27 04:44:31 node1 rabbitmq-server[17368]: systemd unit for activation check: "rabbitmq-server.service"
4月 27 04:44:31 node1 systemd[1]: Started RabbitMQ broker.
4月 27 04:44:31 node1 rabbitmq-server[17368]: completed with 0 plugins.
[root@node1 download]# systemctl enable rabbitmq-server
ln -s '/usr/lib/systemd/system/rabbitmq-server.service' '/etc/systemd/system/multi-user.target.wants/rabbitmq-server.service'
然後啟動 RabbitMQ Web 管理控制台:
[root@node1 download]# rabbitmq-plugins enable rabbitmq_management
The following plugins have been enabled:
amqp_client
cowlib
cowboy
rabbitmq_web_dispatch
rabbitmq_management_agent
rabbitmq_management
Applying plugin configuration to rabbit@node1... started 6 plugins.
RabbitMQ Server 預設guest
用戶,只能localhost
地址訪問,我們還需要創建管理用戶:
[root@node1 download]# rabbitmqctl add_user admin admin123 &&
rabbitmqctl set_user_tags admin administrator &&
rabbitmqctl set_permissions -p / admin ".*" ".*" ".*"
然後添加防火牆運行訪問的埠:
[root@node1 download]# firewall-cmd --zone=public --permanent --add-port=4369/tcp &&
firewall-cmd --zone=public --permanent --add-port=25672/tcp &&
firewall-cmd --zone=public --permanent --add-port=5671-5672/tcp &&
firewall-cmd --zone=public --permanent --add-port=15672/tcp &&
firewall-cmd --zone=public --permanent --add-port=61613-61614/tcp &&
firewall-cmd --zone=public --permanent --add-port=1883/tcp &&
firewall-cmd --zone=public --permanent --add-port=8883/tcp
success
重新啟動防火牆:
[root@node1 download]# firewall-cmd --reload
success
上面這些做完了,RabbitMQ 單機版的部署也完成了,我們可以瀏覽器訪問``:
將上面的搭建過程,在node2
伺服器上,再做重覆一邊。
3. RabbitMQ Server 高可用集群相關概念
設計集群的目的
- 允許消費者和生產者在 RabbitMQ 節點崩潰的情況下繼續運行。
- 通過增加更多的節點來擴展消息通信的吞吐量。
集群配置方式
- cluster:不支持跨網段,用於同一個網段內的區域網;可以隨意的動態增加或者減少;節點之間需要運行相同版本的 RabbitMQ 和 Erlang。
- federation:應用於廣域網,允許單台伺服器上的交換機或隊列接收發佈到另一臺伺服器上交換機或隊列的消息,可以是單獨機器或集群。federation 隊列類似於單向點對點連接,消息會在聯盟隊列之間轉發任意次,直到被消費者接受。通常使用 federation 來連接 internet 上的中間伺服器,用作訂閱分發消息或工作隊列。
- shovel:連接方式與 federation 的連接方式類似,但它工作在更低層次。可以應用於廣域網。
節點類型
- RAM node:記憶體節點將所有的隊列、交換機、綁定、用戶、許可權和 vhost 的元數據定義存儲在記憶體中,好處是可以使得像交換機和隊列聲明等操作更加的快速。
- Disk node:將元數據存儲在磁碟中,單節點系統只允許磁碟類型的節點,防止重啟 RabbitMQ 的時候,丟失系統的配置信息。
問題說明:RabbitMQ 要求在集群中至少有一個磁碟節點,所有其他節點可以是記憶體節點,當節點加入或者離開集群時,必須要將該變更通知到至少一個磁碟節點。如果集群中唯一的一個磁碟節點崩潰的話,集群仍然可以保持運行,但是無法進行其他操作(增刪改查),直到節點恢復。
解決方案:設置兩個磁碟節點,至少有一個是可用的,可以保存元數據的更改。
Erlang Cookie
Erlang Cookie 是保證不同節點可以相互通信的密鑰,要保證集群中的不同節點相互通信必須共用相同的 Erlang Cookie。具體的目錄存放在/var/lib/rabbitmq/.erlang.cookie
。
說明:這就要從 rabbitmqctl 命令的工作原理說起,RabbitMQ 底層是通過 Erlang 架構來實現的,所以 rabbitmqctl 會啟動 Erlang 節點,並基於 Erlang 節點來使用 Erlang 系統連接 RabbitMQ 節點,在連接過程中需要正確的 Erlang Cookie 和節點名稱,Erlang 節點通過交換 Erlang Cookie 以獲得認證。
鏡像隊列
RabbitMQ 的 Cluster 集群模式一般分為兩種,普通模式和鏡像模式。
- 普通模式:預設的集群模式,以兩個節點(rabbit01、rabbit02)為例來進行說明。對於 Queue 來說,消息實體只存在於其中一個節點 rabbit01(或者 rabbit02),rabbit01 和 rabbit02 兩個節點僅有相同的元數據,即隊列的結構。當消息進入 rabbit01 節點的 Queue 後,consumer 從 rabbit02 節點消費時,RabbitMQ 會臨時在 rabbit01、rabbit02 間進行消息傳輸,把 A 中的消息實體取出並經過 B 發送給 consumer。所以 consumer 應儘量連接每一個節點,從中取消息。即對於同一個邏輯隊列,要在多個節點建立物理 Queue。否則無論 consumer 連 rabbit01 或 rabbit02,出口總在 rabbit01,會產生瓶頸。當 rabbit01 節點故障後,rabbit02 節點無法取到 rabbit01 節點中還未消費的消息實體。如果做了消息持久化,那麼得等 rabbit01 節點恢復,然後才可被消費;如果沒有持久化的話,就會產生消息丟失的現象。
- 鏡像模式:將需要消費的隊列變為鏡像隊列,存在於多個節點,這樣就可以實現 RabbitMQ 的 HA 高可用性。作用就是消息實體會主動在鏡像節點之間實現同步,而不是像普通模式那樣,在 consumer 消費數據時臨時讀取。缺點就是,集群內部的同步通訊會占用大量的網路帶寬。
鏡像隊列實現了 RabbitMQ 的高可用性(HA),具體的實現策略如下所示:
ha-mode | ha-params | 功能 |
---|---|---|
all | 空 | 鏡像隊列將會在整個集群中複製。當一個新的節點加入後,也會在這 個節點上複製一份。 |
exactly | count | 鏡像隊列將會在集群上複製 count 份。如果集群數量少於 count 時候,隊列會複製到所有節點上。如果大於 Count 集群,有一個節點 crash 後,新進入節點也不會做新的鏡像。 |
nodes | node name | 鏡像隊列會在 node name 中複製。如果這個名稱不是集群中的一個,這不會觸發錯誤。如果在這個 node list 中沒有一個節點線上,那麼這個 queue 會被聲明在 client 連接的節點。 |
實例列舉:
queue_args("x-ha-policy":"all") //定義字典來設置額外的隊列聲明參數
channel.queue_declare(queue="hello-queue",argument=queue_args)
如果需要設定特定的節點(以rabbit@localhost
為例),再添加一個參數:
queue_args("x-ha-policy":"nodes",
"x-ha-policy-params":["rabbit@localhost"])
channel.queue_declare(queue="hello-queue",argument=queue_args)
可以通過命令行查看那個主節點進行了同步:
$ rabbitmqctl list_queue name slave_pids synchronised_slave_pids
以上內容主要參考:RabbitMQ 分散式集群架構
4. 搭建 RabbitMQ Server 高可用集群
理解了上面的概念之後,我們再搭建 RabbitMQ Server 高可用集群,就非常容易了。
預設.erlang.cookie
文件是隱藏的,ls
命令並不能查看,你也可以手動搜索下文件:
[root@node1 ~]# find / -name ".erlang.cookie"
/var/lib/rabbitmq/.erlang.cookie
[root@node1 ~]# cat /var/lib/rabbitmq/.erlang.cookie
LBOTELUJAMXDMIXNTZMB
將node1
伺服器中的.erlang.cookie
文件,拷貝到node2
伺服器上:
[root@node1 ~]# scp /var/lib/rabbitmq/.erlang.cookie root@node2:/var/lib/rabbitmq
先停止運行節點,然後以後臺方式啟動 RabbitMQ Server(node1
和node2
分別執行):
[root@node1 ~]# rabbitmqctl stop
[root@node1 ~]# rabbitmq-server -detached
然後我們以node1
作為集群中心,在node2
上執行加入集群中心命令(節點類型為磁碟節點):
[root@node1 ~]# rabbitmqctl stop_app
[root@node1 ~]# rabbitmqctl reset
[root@node1 ~]# rabbitmqctl join_cluster rabbit@node1
//預設是磁碟節點,如果是記憶體節點的話,需要加--ram參數
[root@node1 ~]# rabbitmqctl start_app
查看集群的狀態(包含node1
和node2
節點):
[root@node1 ~]# rabbitmqctl cluster_status
Cluster status of node rabbit@node1
[{nodes,[{disc,[rabbit@node1,rabbit@node2]}]},
{running_nodes,[rabbit@node2,rabbit@node1]},
{cluster_name,<<"rabbit@node1">>},
{partitions,[]},
{alarms,[{rabbit@node2,[]},{rabbit@node1,[]}]}]
我們可以從 RabbitMQ Web 管理界面,看到集群的信息:
5. 搭建 HAProxy 負載均衡
HAProxy 是一個免費的負載均衡軟體,可以運行於大部分主流的 Linux 操作系統上。
HAProxy 提供了 L4(TCP) 和 L7(HTTP) 兩種負載均衡能力,具備豐富的功能。HAProxy 的社區非常活躍,版本更新快速(最新穩定版 1.7.2 於 2017/01/13 推出)。最關鍵的是,HAProxy 具備媲美商用負載均衡器的性能和穩定性。它當前不僅僅是免費負載均衡軟體的首選,更幾乎成為了唯一選擇。
因為 RabbitMQ 本身不提供負載均衡,下麵我們就搭建 HAProxy,用作 RabbitMQ 集群的負載均衡。
HAProxy 安裝在node1
伺服器上,安裝命令:
[root@node1 ~]# rpm -ivh http://download.fedoraproject.org/pub/epel/6/i386/epel-release-6-5.noarch.rpm//
[root@node1 ~]# yum -y install haproxy
配置 HAProxy:
[root@node1 ~]# cp /etc/haproxy/haproxy.cfg /etc/haproxy/haproxy.cfg.bak
[root@node1 ~]# vi /etc/haproxy/haproxy.cfg
將下麵的配置添加到/etc/haproxy/haproxy.cfg
文件中:
global
log 127.0.0.1 local0 info
log 127.0.0.1 local1 notice
daemon
maxconn 4096
defaults
log global
mode tcp
option tcplog
option dontlognull
retries 3
option abortonclose
maxconn 4096
timeout connect 5000ms
timeout client 3000ms
timeout server 3000ms
balance roundrobin
listen private_monitoring
bind 0.0.0.0:8100
mode http
option httplog
stats refresh 5s
stats uri /stats
stats realm Haproxy
stats auth admin:admin
listen rabbitmq_admin
bind 0.0.0.0:8102
server node1 node1:15672
server node2 node2:15672
listen rabbitmq_cluster
bind 0.0.0.0:8101
mode tcp
option tcplog
balance roundrobin
server node1 node1:5672 check inter 5000 rise 2 fall 3
server node2 node2:5672 check inter 5000 rise 2 fall 3
然後啟動 HAProxy:
[root@node1 ~]# haproxy -f /etc/haproxy/haproxy.cfg
外部訪問的話,需要關閉下防火牆:
[root@node1 ~]# systemctl disable firewalld.service
rm '/etc/systemd/system/dbus-org.fedoraproject.FirewallD1.service'
rm '/etc/systemd/system/basic.target.wants/firewalld.service'
[root@node1 ~]# systemctl stop firewalld.service
HAProxy 配置了三個地址:
http://node1:8100/stats
:HAProxy 負載均衡信息地址,賬號密碼:admin/admin
。http://node1:8101
:RabbitMQ Server Web 管理界面(基於負載均衡)。http://node1:8102
:RabbitMQ Server 服務地址(基於負載均衡)。
通過訪問http://node1:8100/stats
,查看 HAProxy 負載均衡信息:
參考資料:
- 如何在CentOS 7上安裝RabbitMQ伺服器(有點坑,要結合下麵文章中的命令)
- Centos 6 通過 yum 安裝 Rabbitmq
- RabbitMQ集群安裝
- RabbitMQ分散式集群架構(推薦)
- RabbitMQ 分散式設置和高可用性討論
- RabbitMQ 高可用集群