RabbitMQ集群
消息中間件rabbitmq,一般以集群方式部署,主要提供消息的接受和發送,實現各微服務之間的消息異步。本篇將以rabbitmq+HA方式進行部署。
一、原理介紹
rabbitmq是依據erlang的分布式特性(RabbitMQ底層是通過Erlang架構來實現的,所以rabbitmqctl會啟動Erlang節點,並基於Erlang節點來使用Erlang系統連接RabbitMQ節點,在連接過程中需要正確的Erlang Cookie和節點名稱,Erlang節點通過交換Erlang Cookie以獲得認證)來實現的,所以部署rabbitmq分布式集群時要先安裝erlang,並把其中一個服務的cookie復制到另外的節點。
rabbitmq集群中,各個rabbitmq為對等節點,即每個節點均提供給客戶端連接,進行消息的接收和發送。節點分為內存節點和磁盤節點,一般的,均應建立為磁盤節點,為了防止機器重啟后的消息消失;
RabbitMQ的Cluster集群模式一般分為兩種,普通模式和鏡像模式。消息隊列通過rabbitmq HA鏡像隊列進行消息隊列實體復制。
普通模式下,以兩個節點(rabbit01、rabbit02)為例來進行說明。對於Queue來說,消息實體只存在於其中一個節點rabbit01(或者rabbit02),rabbit01和rabbit02兩個節點僅有相同的元數據,即隊列的結構。當消息進入rabbit01節點的Queue后,consumer從rabbit02節點消費時,RabbitMQ會臨時在rabbit01、rabbit02間進行消息傳輸,把A中的消息實體取出並經過B發送給consumer。所以consumer應盡量連接每一個節點,從中取消息。即對於同一個邏輯隊列,要在多個節點建立物理Queue。否則無論consumer連rabbit01或rabbit02,出口總在rabbit01,會產生瓶頸。
鏡像模式下,將需要消費的隊列變為鏡像隊列,存在於多個節點,這樣就可以實現RabbitMQ的HA高可用性。作用就是消息實體會主動在鏡像節點之間實現同步,而不是像普通模式那樣,在consumer消費數據時臨時讀取。缺點就是,集群內部的同步通訊會占用大量的網絡帶寬。
二、部署方案
本方案中是在多台機器之間部署rabbitmq的cluster,要求如下:這幾個節點需要再同一個局域網內;這幾個節點需要有相同的erlang cookie,否則不能正常通信,為了實現cookie內容一致,采用scp的方式進行。
1、環境介紹
CentOS Linux release 7.5.1804 (Core)
192.168.0.170 ZFVM-APP-0-170
192.168.0.171 ZFVM-APP-0-171
192.168.0.172 ZFVM-APP-0-172
首先在/etc/hosts中,綁定三台機器的ip和主機名
在三台主機上安裝所需依賴的安裝包
# yum -y install make gcc gcc-c++ kernel-devel m4 ncurses-devel openssl-devel
先下載安裝RabbitMQ所需的的依賴軟件erlang
# wget http://distfiles.macports.org/erlang/otp_src_20.3.tar.gz # tar zxvf otp_src_20.3.tar.gz # mkdir -p /data/local/erlang # cd otp_src_20.3 # ./configure --prefix=/data/local/erlang --with-ssl --enable-threads --enable-smmp-support --enable-kernel-poll --enable-hipe --without-javac # make && make install # echo "export PATH=$PATH:/data/local/erlang/bin" >> /etc/profile # source /etc/profile # erl -version Erlang (SMP,ASYNC_THREADS,HIPE) (BEAM) emulator version 9.3
下載安裝RabbitMQ二進制包
# wget https://dl.bintray.com/rabbitmq/all/rabbitmq-server/3.7.7/rabbitmq-server-generic-unix-3.7.7.tar.xz # xz -d rabbitmq-server-generic-unix-3.7.7.tar.xz # tar xvf rabbitmq-server-generic-unix-3.7.7.tar -C /data/local/ # cd /data/local/ # mv rabbitmq_server-3.7.7 /data/local/rabbitmq-3.7.7 # echo "export PATH=$PATH:/data/local/rabbitmq-3.7.7/sbin" >> /etc/profile # source /etc/profile # rabbitmq-plugins enable rabbitmq_management ---------打開管理界面插件 # vim .erlang.cookie --------node2和node3與node1的一致 # rabbitmq-server -detached -------–后台啟動服務
# rabbitmqctl add_user admin 123456 --------添加用戶,密碼
# rabbitmqctl set_permissions -p "/" admin ".*" ".*" ".*"
# rabbitmqctl set_user_tags admin administrator
將節點node2連接到節點node1上
# rabbitmqctl stop_app ------關閉服務 # rabbitmqctl join_cluster rabbit@ZFVM-APP-0-170 # rabbitmqctl cluster_status ------查看狀態
在node3上重復上述動作,也連接到node1上
另外更改節點屬性可以用一下命令
# rabbitmqctl stop_app ------停止rabbitmq服務 # rabbitmqctl change_cluster_node_type disc/ram ----更改節點為磁盤或內存節點 # rabbitmqctl start_app -----開啟rabbitmq服務
分別在3台主機上查看連接的狀態
[root@ZFVM-APP-0-170 rabbitmq]# rabbitmqctl cluster_status Cluster status of node 'rabbit@ZFVM-APP-0-170' [{nodes,[{disc,['rabbit@ZFVM-APP-0-170','rabbit@ZFVM-APP-0-171', 'rabbit@ZFVM-APP-0-172']}]}, {running_nodes,['rabbit@ZFVM-APP-0-172','rabbit@ZFVM-APP-0-171', 'rabbit@ZFVM-APP-0-170']}, {cluster_name,<<"rabbit@ZFVM-APP-0-170">>}, {partitions,[]}, {alarms,[{'rabbit@ZFVM-APP-0-172',[]}, {'rabbit@ZFVM-APP-0-171',[]}, {'rabbit@ZFVM-APP-0-170',[]}]}] [root@ZFVM-APP-0-171 ~]# rabbitmqctl cluster_status Cluster status of node 'rabbit@ZFVM-APP-0-171' [{nodes,[{disc,['rabbit@ZFVM-APP-0-170','rabbit@ZFVM-APP-0-171', 'rabbit@ZFVM-APP-0-172']}]}, {running_nodes,['rabbit@ZFVM-APP-0-172','rabbit@ZFVM-APP-0-170', 'rabbit@ZFVM-APP-0-171']}, {cluster_name,<<"rabbit@ZFVM-APP-0-170">>}, {partitions,[]}, {alarms,[{'rabbit@ZFVM-APP-0-172',[]}, {'rabbit@ZFVM-APP-0-170',[]}, {'rabbit@ZFVM-APP-0-171',[]}]}] [root@ZFVM-APP-0-172 ~]# rabbitmqctl cluster_status Cluster status of node 'rabbit@ZFVM-APP-0-172' [{nodes,[{disc,['rabbit@ZFVM-APP-0-170','rabbit@ZFVM-APP-0-171', 'rabbit@ZFVM-APP-0-172']}]}, {running_nodes,['rabbit@ZFVM-APP-0-170','rabbit@ZFVM-APP-0-171', 'rabbit@ZFVM-APP-0-172']}, {cluster_name,<<"rabbit@ZFVM-APP-0-170">>}, {partitions,[]}, {alarms,[{'rabbit@ZFVM-APP-0-170',[]}, {'rabbit@ZFVM-APP-0-171',[]}, {'rabbit@ZFVM-APP-0-172',[]}]}]
可以刪除默認guest用戶
# rabbitmqctl delete_user guest
集群已搭建完成
鏡像模式:把需要的隊列做成鏡像隊列,存在於多個節點,屬於RabbitMQ的HA方案,在任意節點上執行
# rabbitmqctl set_policy ha-all "^" '{"ha-mode":"all"}' # rabbitmqctl list_policies