最近做到的项目中,有着庞大的日数据处理量(大概1天200W条),都需要通过MQ来传递数据,并进行解析持久化。所以接触了下Rabbitmq的镜像集群搭建,记录下方便以后再次用到。
先讲下整体的架构,计划打算使用3台MQ服务器,然后用2台haproxy服务器进行负载均衡处理,再使用keepalived来处理两台负载均衡处理器的单点问题,以期实现高可用高负载的MQ集群。本片只涉及前两部分。
涉及服务器均为
CentOS7 64位
所使用到的Rabbitmq版本
rabbitmq-server-generic-unix-3.6.15.tar.xz
在进行Rabbitmq集群搭建之前,首先需要在3台MQ服务器上部署单机Rabbitmq。
1.安装Erlang
因为Rabbitmq是依赖Erlang的,所以需要先安装Erlang。
(1)安装编译环境,如果已经安装过就不需要再安一次了。
yum -y install make gcc gcc-c++ kernel-devel m4 ncurses-devel openssl-devel
(2)安装ncurses
yum -y install ncurses-devel
(3)安装unixODBC
yum install unixODBC unixODBC-devel
(4)下载安装erlang
//进入想要安装的目录,假设我这里是想把erlang安装在/home目录下
cd /home
wget http://erlang.org/download/otp_src_20.3.tar.gz
解压
tar -zxvf otp_src_20.3.tar.gz
初始化
//进入解压完的文件夹
cd otp_src_20.3
//指定不用java编译,填不填无所谓,就是不写会报个警告,无影响
./configure --prefix /home/erlang --without-javac
安装
make
make install
安装完毕后配置下环境变量
vim /etc/profile
添加
export PATH=$PATH:/home/erlang/bin/
保存退出,并执行
source /etc/profile
试下能否使用erlang
erl
2.在xx.xx.2.1
,xx.xx.2.2
,xx.xx.2.3
3台MQ服务器上安装Rabbitmq。
(1)下载rabbitmq-server-generic-unix-3.6.15.tar.xz
cd /home
wget http://www.rabbitmq.com/releases/rabbitmq-server/v3.6.15/rabbitmq-server-generic-unix-3.6.15.tar.xz
解压
tar -xvf rabbitmq-server-generic-unix-3.6.15.tar.xz
该方式下载解压后可以直接使用,无需再编译安装
设置环境变量
vim /etc/profile
添加
export PATH=/home/rabbitmq_server-3.6.15/sbin/:$PATH
保存退出并执行
source /etc/profile
进入安装目录
cd /home/rabbitmq_server-3.6.15/sbin/
开启后台管理工具
./rabbitmq-plugins enable rabbitmq_management
启动Rabbitmq
./rabbitmq-server -detached #后台运行rabbitmq
#注,我在用该方式启动Rabbitmq时会报错,所以我用的是这个方法启动
./rabbitmq-server start &
可以查看下进程或者stats看下是否启动
ps -ef|grep rabbitmq
rabbitmqctl status
可以看到上面我涂掉的status of node xxxx
这个xxxx就是该rabbitmq节点的名称,之后在集群设置中会用到,这里可以记录下xx.xx.2.1
的节点名。
这样RabbitMq就算是启动了,但是还需要设置新的用户和开放端口供外部访问。
开放端口
iptables -I INPUT -p tcp --dport 15672 -j ACCEPT
添加用户
rabbitmqctl add_user admin 123456 #用户名 密码
添加权限
./rabbitmqctl set_permissions -p "/" admin ".*" ".*" ".*"
修改用户角色
./rabbitmqctl set_user_tags admin administrator
然后就可以通过15672端口访问网页控制台了
访问的地址为 http://xx.xx.2.1:15672 前半段为MQ服务器ip地址,或者外网映射地址。
使用刚才的用户密码就可以登入了。
然后在xx.xx.2.2和xx.xx.2.3上重复一遍安装Rabbitmq。
通过上一步,已经成功在3台MQ服务器上安装了单机的Rabbitmq,并保证有同一用户名密码的用户。
现在,使用xx.xx.2.1
作为’主节点’
1.xx.xx.2.1
的.erlang.cookie
文件的拷贝复制
首先找到该文件
find -name .erlang.cookie
上面涂掉的是我复制出来的同一个文件,找到该文件后复制一份,然后替换掉xx.xx.2.2
和xx.xx.2.3
上的同文件,使得3台MQ服务器上的该文件都为xx.xx.2.1
的。
即三台服务器必须具有相同的cookie,如果不相同的话,无法搭建集群(注:该文件为隐藏文件,复制拷贝的时候还要注意各台服务器上该文件的权限,一定要保证替换完后的权限和替换前一致)
2.在xx.xx.2.2
和xx.xx.2.3
服务器上执行如下操作加入到MQ集群
abbitmqctl stop_app
rabbitmqctl join_cluster --ram rabbit@h-ncdrdcs7
#rabbit@h-ncdrdcs7是rabbitmq node name,上面在查看rabbitmq运行情况时我
#有提到,这里都使用xx.xx.2.1上的rabbitmq node name就行
rabbitmqctl start_app
#其中--ram代表是内存节点,如果希望是磁盘节点则不用加--ram,
#在rabbitmq集群中,至少需要一个磁盘节点
查看集群状态
rabbitmqctl cluster_status
当然也可以通过15672从页面上查看
这里我使用http://xx.xx.2.1:15672
来查看,如下状态就表示集群已经搭建好了
设置成镜像队列
rabbitmqctl set_policy ha-all "^test\." '{"ha-mode":"all"}'
#意思表示以test.开头的queue都会复制到各个节点 ["^"匹配所有],这个大家自行修改
至此,Rabbitmq镜像集群搭建完毕。
PS:
这里我遇到一个大坑,稍微提一下,就是2,3两台MQ服务器在加入1时,出现无法解析服务器名的问题,然后这里需要在3台服务器的/etc/hosts文件中添加机器名-ip,然后需要将3台MQ都重启一下才能够加入(是整个重启,单纯重启app没用的)。
在xx.xx.1.1
上安装Haproxy
yum install haproxy
安装过程中会提示是否安装,输入y
,回车
即可
安装完毕后需要修改配置
vim /etc/haproxy/haproxy.cfg
在末尾添加内容如下
#---------------------------------------------------------------------
# my
#---------------------------------------------------------------------
listen rabbitmq
bind 0.0.0.0:5672
mode tcp
option tcplog
balance roundrobin
#option tcpka
server rabbit1 xx.xx.1.1:5672 check inter 5s rise 2 fall 3
server rabbit2 xx.xx.1.2:5672 check inter 5s rise 2 fall 3
server rabbit3 xx.xx.1.3:5672 check inter 5s rise 2 fall 3
然后运行Haproxy
haproxy -f /etc/haproxy/haproxy.cfg
重启的方式是
service haproxy restart
PS:
如果在运行时出现need mode http什么的错误的话,可以尝试注释掉default中的mode http,按理来说在监听节点中不存在设置时会自动使用默认设置,如果存在则会负载默认设置,但不知道为什么,我在启动时出现了默认设置覆盖实际设置的问题,不过只要注掉默认设置即可,问题不大。
然后可以尝试用生产者端或者消费者端向xx.xx.1.1
负载服务器上发/收消息,然后15672查看queue状态即可,或者在haproxy配置文件中加入15672端口的监听,直接访问
http://xx.xx.1.1:15672
,如果可以访问并能通过设置的用户名密码登入,则表示负载均衡配置成功。
另一台负载均衡服务器也可以做相同的配置,然后使用keepalived来检测两台负载服务器的单点问题即可。以后有时间我会把这部分补充完整。当然现阶段使用单负载服务器直接访问集群也是可以的。