Bootstrap

RabbitMQ详解——RabbitMQ架构部署(四)

RabbitMQ服务端搭建(RabbitMQ 3.9.8)

单一模式

单一模式就是单节点模式,不具备可靠性和高可用性

安装(docker方式)

#拉取最新的镜像

docker pull rabbitmq:management

查看本地镜像

docker images

创建并运行rabbitmq镜像

docker run -di --hostname rabbit1 --name='myrabbit1' -p 15673:15672 -p 5673:5672 -e RABBITMQ_ERLANG_COOKIE='rabbitcookie' -e RABBITMQ_DEFAULT_USER=admin -e RABBITMQ_DEFAULT_PASS=admin rabbitmq:management

普通集群模式

RabbitMQ的集群模式通过增加多个节点缓解单个节点的服务和资源压力,做到可以横向扩展。RabbitMQ默认集群模式并不保证队列的高可用性,尽管交换机、绑定这些可以复制到集群里的任何一个节点,但是队列内容不会复制。他的消费机制:对于消费者来说,若消息进入A节点的队列中,当从B节点拉取时,rabbit会将消息从A中取出,并经过B发送给消费者。虽然该模式解决一项目组节点压力,但队列节点宕机直接导致该队列无法应用,只能等待重启

安装(接上文的单一模式增加两个节点)

docker run -di --hostname rabbit2 --name myrabbit2 -p 15674:15672 -p 5674:5672 --link myrabbit1:rabbit1 -e RABBITMQ_ERLANG_COOKIE='rabbitcookie' -e RABBITMQ_DEFAULT_USER=admin -e RABBITMQ_DEFAULT_PASS=admin rabbitmq:management

docker run -di --hostname rabbit3 --name myrabbit3 -p 15675:15672 -p 5675:5672 --link myrabbit1:rabbit1 --link myrabbit2:rabbit2 -e RABBITMQ_ERLANG_COOKIE='rabbitcookie' -e RABBITMQ_DEFAULT_USER=admin -e RABBITMQ_DEFAULT_PASS=admin rabbitmq:management

集群必须有相同的erlang的cookie在RabbitMQ集群集群中,必须至少有一个磁盘节点,否则队列元数据无法写入到集群中,当磁盘节点宕掉时,集群将无法写入新的队列元数据信息查看容器

docker ps|grep rabbit

以第一个节点 rabbit1 作为主节点,把rabbit2和rabbit3 加入到rabbit1进入rabbit1容器

docker exec -ti 0df1da7318d4 bash
# 依次执行命令
# 停止服务
rabbitmqctl stop_app
# 离开所在的集群
rabbitmqctl reset
# 启动服务
rabbitmqctl start_app
# 退出容器
exit

进入rabbit2容器


docker exec -ti c991ded3668b bash
# 依次执行命令
# 停止服务
rabbitmqctl stop_app
# 离开所在的集群
rabbitmqctl reset
# 加入集群
rabbitmqctl join_cluster rabbit@rabbit1
# 启动服务
rabbitmqctl start_app
# 退出容器
exit

进入rabbi3容器

docker exec -ti efbd7557a264 bash
# 依次执行命令
# 停止服务
rabbitmqctl stop_app
# 离开所在的集群
rabbitmqctl reset
# 加入集群,ram参数表示内存节点,默认磁盘节点(disc)
rabbitmqctl join_cluster --ram rabbit@rabbit1
# 启动服务
rabbitmqctl start_app
# 退出容器
exit

进入任何一个节点下查看集群信息

rabbitmqctl cluster_status

至此,rabbitmq的普通集群已经搭建好了,可以很好的提升性能

消息生产消费执行时序

集群中各节点有相同的队列结构,但消息只会存在于集群中的一个节点。对于消费者来说,若消息进入A节点的队列中,当从B节点拉取时,rabbit会将消息从A中取出,并经过B发送给消费者

主备模式

  • 主备模式,也称之为Warren模式,即主节点如果挂了,切换到从节点继续提供服务

  • 主备模式的简单架构模型,主要是利用HaProxy去做的主备切换,当主节点挂掉时,HaProxy会自动进行切换,把备份节点升级为主节点

镜像集群模式

集群模式虽然可以提升服务端的性能,但是高可用还差一点,主节点挂了话,整个集群都不能使用了,单个节点宕机会导致部分节点不可用,所以要想真正高可用,还需扩展为镜像模式的集群,集群模式就是,就要复制队列内容到集群里的每个节点,所以必须要创建镜像队列进入主节点的容器,执行命令,将所有queue都进行镜像(配置不同参数可以选择queue)

配置

  • 方式一

rabbitmqctl set_policy ha-all "^" '{"ha-mode":"all"}'

  • 方式二通过界面进行配置

消息生产消费执行时序

镜像队列设置后,会分一个主节点和多个从节点,如果主节点宕机,从节点会有一个选为主节点,原先的主节点起来后会变为从节点。queue和message虽然会存在所有镜像队列中,但客户端读取时不同的节点都会把请求转到内部选取出来的主节点,然后主节点再将queue和message的状态同步给从节点,因此多个客户端连接不同的镜像队列不会产生同一message被多次接受的情况

主节点的查看方式

远程集群模式(Shovel)

远程模式是一个可以实现双活的一种模式,简称Shovel模式,所谓Shovel就是我们可以把消息进行不同数据中心的复制工作,我们可以跨地域的让两个MQ集群互连,下文介绍常用的多活架构模式(federation),所以本集群模式不做实践

多活模式(Federation)

Shovel 远程模式其实就是将 RabbitMQ Server 根据不同的地域,部署到了不同的地域位置,从而实现对 RabbitMQ Server 的远程调用,但是,这种远程调用方式配置起来过于繁琐,会花费很长的时间,这有点得不偿失。所以,RabbitMQ 官方考虑到了这一弊端,才会有今天的 Federation 多活集群模式

部署架构

部署

基于前文,我们使用rabbit4 和rabbit5 两台机器做federation模式的实践实现从rabbit5往rabbit4上同步

  • 需要安装federation的插件


rabbitmq-plugins enable rabbitmq_federation

rabbitmq-plugins enable rabbitmq_federation_management

  • 一般我们不用admin做同步的用户,所以我们单独创建federation不通的用户,在两个rabbitmq 节点上分别创建用户创建用户 :fed_test 指定tag:administrator同时我们创建两个不同的vhost

  • vhost绑置用户权限

  • 在rabbit4和rabbit5上配置需要交换的交换机

  • 在rabbit4和rabbit5上配置交换的队列同时绑定到交换机上

  • 在rabbit4上配置upstream

URI配置格式

amqp://fed_user[用户名]:fed_user[密码]@172.168.1.36:5677 [拉取的上游地址]

  • rabbit4上添加policy

  • 配置成功后在rabbit4上会看到如下的同步状态

  • 在上游的机器队列中会看到对了 (同时消息可以同步过来),也可以配置双向的同步

负载均衡策略

bbitMQ自身没有负载均衡的能力,所以要结合其他的中间件做负载均衡和故障转移这样的能力做到消息服务的最终的高可用,可以在一些客户端层面去做,也可以使用一些提供负载均衡能力的中间件去完成这样的工作,目前大部分公司使用的方案是Haproxy+KeepAlived的方案,本文也主要介绍这种方案的环境搭建

执行时序

  • 当我们的应用程序,或者生产者需要使用我们的 RabbitMQ Server 时,就会向我们的 RabbitMQ Server 发送请求,由图可知,该请求会被我们所配置的负载均衡策略所截获,同时,负载均衡策略会根据请求的内容,来将请求分发到相应的地域节点中的 RabbitMQ Server 中。

  • Federation 多活集群模式与 Shovel 远程调用集群模式最大的不同之处在于,Shovel 远程调用集群模式需要指定主区域,即可以理解为主节点,但是 Federation 多活集群模式不需要指定,它的每一个节点都相当于是主节点,每一个节点都是活跃的, 请求只会根据不同的负载均衡策略来分发到不同的地域节点上而已

RabbitMQ高可用集群架构图