使用docker 搭建RabbitMQ集群
RabbitMQ集群中节点包含内存节点(RAM)、磁盘节点(Disk,消息持久化)、集群中至少有一个Disk节点。集群分为两种集群模式普通模式 和 镜像模式。
普通模式(默认)
对于普通模式,集群中各节点有相同的队列结构,但消息只会存在于集群中的一个节点,对于消费者来说,若消息进入A节点的Queue中,当从B节点拉取时,RabbitMQ会将消息从A中取出,并经过B发送给消费者。
应用场景:该模式更适合于消息无需持久化的场景,如日志队列。当队列非持久化,且创建该队列的节点宕机,客户端才可以重连集群其他节点,并重新创建队列。若为持久化,只能等故障节点恢复。缺点:无法解决单点故障问题。
镜像模式
与普通模式不同之处时消息实体会主动在镜像节点见同步,而不是在取数据时临时拉取,高可用;该模式下 镜像队列(mirror queue)有一套选举算法,即1个master、n个slaver。 生产者、消费者的请求都会转至master。
应用场景:可靠性要求较高场合,如下单、库存队列。缺点:若镜像队列过多,且消息体量大,集群内部网络带宽将会被此种同步通讯所消耗。
1、使用docker安装rabbitMQ
#拉取镜像,指定带有“mangement”的版本(包含web管理页面),该版本包含了web控制页面
docker pull rabbitmq:management
查看拉取的镜像
docker images
2、构建RabbitMQ集群
使用Docker启动3个RabbitMQ节点
docker run -d --hostname myRabbit1 --name rabbit1 -p 15672:15672 -p 5672:5672 -e RABBITMQ_ERLANG_COOKIE='rabbitcookie' rabbitmq:management
docker run -d --hostname myRabbit2 --name rabbit2 -p 5673:5672 --link rabbit1:myRabbit1 -e RABBITMQ_ERLANG_COOKIE='rabbitcookie' rabbitmq:management
docker run -d --hostname myRabbit3 --name rabbit3 -p 5674:5672 --link rabbit1:myRabbit1 --link rabbit2:myRabbit2 -e RABBITMQ_ERLANG_COOKIE='rabbitcookie' rabbitmq:management
注意:
- -e RABBITMQ_ERLANG_COOKIE='rabbitcookie' 必须设置为相同,因为 Erlang节点间是通过认证Erlang cookie的方式来允许互相通信的。
- --link rabbit1:myRabbit1 --link rabbit2:myRabbit2 不要漏掉,否则会 一直处在 Cluster status of node rabbit@myRabbit3 ... 没有反应
启动完成之后,使用docker ps
命令查看运行情况,确保RabbitMQ都已经启动。
3、加入集群
内存节点和磁盘节点的选择:
每个RabbitMQ节点,要么是内存节点,要么是磁盘节点。内存节点将所有的队列、交换器、绑定、用户等元数据定义都存储在内存中;而磁盘节点将元数据存储在磁盘中。单节点系统只允许磁盘类型的节点,否则当节点重启以后,所有的配置信息都会丢失。如果采用集群的方式,可以选择至少配置一个节点为磁盘节点,其余部分配置为内存节点,,这样可以获得更快的响应。所以本集群中配置节点1位磁盘节点,节点2和节点3位内存节点。
集群中的第一个节点将初始元数据代入集群中,并且无须被告知加入。而第2个和之后加入的节点将加入它并获取它的元数据。要加入节点,需要进入Docker容器,重启RabbitMQ。
将RabbitMQ节点加入到集群
#进入rabbitmq01容器,重新初始化一下,如果是新安装则reset可以忽略重置。
docker exec -it rabbit1 bash
rabbitmqctl stop_app
rabbitmqctl reset
rabbitmqctl start_app
exit
#进入rabbitmq02容器,重新初始化一下,将02节点加入到集群中
docker exec -it rabbit2 bash
rabbitmqctl stop_app
rabbitmqctl reset
rabbitmqctl join_cluster --ram rabbit@myRabbit1 #参数“--ram”表示设置为内存节点,忽略该参数默认为磁盘节点。
rabbitmqctl start_app
exit
#进入rabbitmq03容器,重新初始化一下,将03节点加入到集群中
docker exec -it rabbit3 bash
rabbitmqctl stop_app
rabbitmqctl reset
rabbitmqctl join_cluster --ram rabbit@myRabbit1
rabbitmqctl start_app
exit
集群测试访问
4. 配置镜像队列
镜像队列工作原理:在非镜像队列的集群中,消息会路由到指定的队列。当配置为镜像队列之后,消息除了按照路由规则投递到相应的队列外,还会投递到镜像队列的拷贝。也可以想象在镜像队列中隐藏着一个fanout交换器,将消息发送到镜像的队列的拷贝。
进入任意一个RabbitMQ节点,执行如下命令:
#随便进入一个容器
docker exec -it rabbit1 bash
#设置策略匹配所有名称是amp开头的队列都存储在2个节点上的命令如下
rabbitmqctl set_policy -p / ha "^amp*" '{"ha-mode":"exactly","ha-params":2}'
#或者
#设置策略匹配所有名称的队列都进行高可用配置
rabbitmqctl set_policy -p / ha "^" '{"ha-mode":"all","ha-sync-mode":"automatic"}'
#查询策略
rabbitmqctl list_policies -p / #查看vhost下的所有的策略(policies )
可以看出设置镜像队列,一共有四个参数,每个参数用空格分割。
- 参数一:策略名称,可以随便填,此外我们命名为ha(高可用);
- 参考二:-p / 设置哪个虚拟主机,可以使用rabbitmqctl list_policies -p / 查看vhost 下所有的策略(policies )。
- 参数三:队列名称的匹配规则,使用正则表达式表示;
- 参数四:为镜像队列的主体规则,是json字符串,分为三个属性:ha-mode | ha-params | ha-sync-mode,分别的解释如下:
- ha-mode:镜像模式,分类:all/exactly/nodes,all存储在所有节点;exactly存储x个节点,节点的个数由ha-params指定;nodes指定存储的节点上名称,通过ha-params指定;
- ha-params:作为参数,为ha-mode的补充;
- ha-sync-mode:镜像消息同步方式:automatic(自动),manually(手动);
至此rabbitmq集群算是搭建完毕,查看集群的状态:
rabbitmqctl cluster_status
查看镜像队列
rabbitmqctl list_policies
删除镜像队列
rabbitmqctl clear_policy