RabbitMQ是基于高级消息队列协议(AMQP)实现的开源消息代理软件,主要提供消息队列服务。这里介绍用Docker Compose搭建RabbitMQ高可用集群的过程。
RabbitMQ自身提供部署集群的功能,通过命令:
1 | $ rabbitmqctl -n rabbit@rmqha_node1 stop_app |
就可以很容易的将节点rabbit@rmqha_node1加入到集群rabbit@rmqha_node0中。--ram
选项表示节点以内存存储方式运行,读写速度快,重启后内容会丢失;不加--ram
选项,节点则以磁盘存储方式运行,虽然读写速度慢,但是内容一般可以持久保持。
在同一个RabbitMQ集群中,节点之间并没有主从之分,所有节点会同步相同的队列结构,队列内容(消息)则各自不同,不过消息会在节点间传递。这样的集群只是提高了应对大量并发请求的能力,整体可用性还是很低,因为某个节点宕机后,寄存在该节点上的消息不可用,而在其他节点上也没有这些消息的备份,若是该节点无法恢复,那么这些消息就丢失了。
为了解决这个问题,RabbitMQ提供镜像队列功能,通过命令:
1 | $ rabbitmqctl set_policy ha-all "^" '{"ha-mode":"all"}' |
可以设置镜像队列,"^"
表示匹配所有队列,即所有队列在各个节点上都会有备份。在集群中,只需要在一个节点上设置镜像队列,设置操作会同步到其他节点。
Docker Compose编排
这个编排主要实现一个磁盘节点、两个内存节点的RabbitMQ集群和一个HAProxy代理。
目录结构
1 | L--rabbitmq-ha-docker //主目录 |
docker-compose.yml
1 | version: "2" |
这里配置了四个容器服务,一个haproxy
,负责代理各个RabbitMQ服务;三个rabbitmq
,组成RabbitMQ集群。每个容器服务都指定了静态IP,即使服务重启也不会出现IP错乱问题,特殊的网络端口映射后面会介绍。
环境参数
parameters.env
1 | RMQHA_MASTER_NODE=rabbit |
RabbitMQ启动
这里RabbitMQ容器是使用Docker官方镜像生成的,节点rmqha_node0可以直接启动;而节点rmqha_node1和rmqha_node2需要加入到rmqha_node0集群里,所以需要需改入口文件。
volumes/rmqha_slave/cluster_entrypoint.sh
1 | !/bin/bash |
HAProxy配置
这里HAProxy容器也是使用Docker官方镜像生成的,启动前需要先准备配置文件。
volumes/rmqha_proxy/haproxy.cfg
1 | global |
实际运行
在主目录下执行docker-compose up -d
构建并运行整个Docker服务。
镜像队列
,在主目录下执行:
1 | $ sh ./scripts/rmqha_set_policy.sh |
实际上是执行了:
1 | $ docker exec -it rmqha_node0 rabbitmqctl set_policy ha-all '^' '{"ha-mode":"all"}' |
即在rmqha_node0集群中将所有队列设置为镜像队列,这个命令只需执行一次,除非重新构建整个Docker服务。
测试
用两个PHP脚本可以对RabbitMQ进行简单的测试,不过需要用到php-amqplib
库。
1 | $ composer require php-amqplib/php-amqplib |
发送消息脚本:
1 |
|
接受消息脚本:
1 |
|
SSL设置
为了RabbitMQ服务在网络传输中不泄漏信息,可以给HAProxy设置SSL传输(比对各个RabbitMQ服务设置SSL传输的性能消耗要小),这里简单的介绍一下自签证书:
1 | $ cd ./volumes/rmqha_proxy/ |
注意:生成证书签署请求时,需要填写一些信息,Common Name (eg, fully qualified host name)
应该写127.0.0.1
。
HAProxy配置中添加:
1 | # ssl for rabbitmq |
PHP中通过SSL连接HAProxy代理服务示例:
1 |
|
最后
建议
- 消息生产者可以通过HAProxy代理连接RabbitMQ服务,实现负载均衡;
- 消息处理者应该直接连接RabbitMQ服务主机,并且跟随RabbitMQ服务主机启动服务、停止服务。