RabbitMQ部署指南
RabbitMQ部署指南
1.单机部署
我们在Centos7虚拟机中使用Docker来安装。
1.1.下载镜像
方式一:在线拉取
docker pull rabbitmq:3.8-management
方式二:从本地加载
在课前资料已经提供了镜像包:

上传到虚拟机中后,使用命令加载镜像即可:
docker load -i mq.tar
1.2.安装MQ
执行下面的命令来运行MQ容器:
docker run \
-e RABBITMQ_DEFAULT_USER=itcast \
-e RABBITMQ_DEFAULT_PASS=123321 \
-v mq-plugins:/plugins \
--name mq \
--hostname mq1 \
-p 15672:15672 \
-p 5672:5672 \
-d \
rabbitmq:3.8-management
2.安装DelayExchange插件
官方的安装指南地址为:https://blog.rabbitmq.com/posts/2015/04/scheduling-messages-with-rabbitmq
上述文档是基于linux原生安装RabbitMQ,然后安装插件。
因为我们之前是基于Docker安装RabbitMQ,所以下面我们会讲解基于Docker来安装RabbitMQ插件。
2.1.下载插件
RabbitMQ有一个官方的插件社区,地址为:https://www.rabbitmq.com/community-plugins.html
其中包含各种各样的插件,包括我们要使用的DelayExchange插件:

大家可以去对应的GitHub页面下载3.8.9版本的插件,地址为https://github.com/rabbitmq/rabbitmq-delayed-message-exchange/releases/tag/3.8.9这个对应RabbitMQ的3.8.5以上版本。
课前资料也提供了下载好的插件:

2.2.上传插件
因为我们是基于Docker安装,所以需要先查看RabbitMQ的插件目录对应的数据卷。如果不是基于Docker的同学,请参考第一章部分,重新创建Docker容器。
我们之前设定的RabbitMQ的数据卷名称为mq-plugins
,所以我们使用下面命令查看数据卷:
docker volume inspect mq-plugins
可以得到下面结果:

接下来,将插件上传到这个目录即可:

也可以使用cp命令
cp /volume1/docker/mqhaha/rabbitmq_delayed_message_exchange-3.8.9-0199d11c.ez /volume1/@docker/volumes/mq-plugins/_data/rabbitmq_delayed_message_exchange-3.8.9-0199d11c.ez
2.3.安装插件
最后就是安装了,需要进入MQ容器内部来执行安装。我的容器名为mq
,所以执行下面命令:
执行时,请将其中的 -it
后面的mq
替换为你自己的容器名.
docker exec -it mq bash
修该权限
chmod 777 /plugins/rabbitmq_delayed_message_exchange-3.8.9-0199d11c.ez
进入容器内部后,执行下面命令开启插件:
rabbitmq-plugins enable rabbitmq_delayed_message_exchange
结果如下:

2.4.使用插件



3.集群部署
接下来,我们看看如何安装RabbitMQ的集群。
3.1.集群分类
集群分类
在RabbitMQ的官方文档中,讲述了两种集群的配置方式:
- 普通模式:普通模式集群不进行数据同步,每个MQ都有自己的队列、数据信息(其它元数据信息如交换机等会同步)。
例如我们有2个MQ:mq1,和mq2,如果你的消息在mq1,而你连接到了mq2,那么mq2会去mq1拉取消息,然后返回给你。如果mq1宕机,消息就会丢失。
- 镜像模式:与普通模式不同,队列会在各个mq的镜像节点之间同步,因此你连接到任何一个镜像节点,均可获取到消息。而且如果一个节点宕机,并不会导致数据丢失。不过,这种方式增加了数据同步的带宽消耗。
3.2.普通集群
普通集群
我们先来看普通模式集群,我们的计划部署3节点的mq集群:
主机名 | 控制台端口 | amqp通信端口 |
---|---|---|
my-rabbit1 | 15672 ---> 15672 | 5672 ---> 5672 |
my-rabbit2 | 15673 ---> 15672 | 5673 ---> 5672 |
my-rabbit3 | 15674 ---> 15672 | 5674 ---> 5672 |
集群中的节点标示默认都是:rabbit@[hostname]
,因此以上三个节点的名称分别为:
rabbit@my-rabbit1
rabbit@my-rabbit2
rabbit@my-rabbit3
主机名字非常重要,直接可以用来通讯
如果之前配置启动了容器,可以删除 接下来,停止并删除当前的mq容器,我们重新搭建集群。
docker rm -f mq
清理无用的数据卷
docker volume prune

提前准备 rabbitmq:3.8-management 镜像
依次执行下列命令,启动3个节点:
节点1
docker run -d --hostname my-rabbit1 --name rabbit1 -p 5672:5672 -p 15672:15672 -e RABBITMQ_ERLANG_COOKIE='rabbitcookie' rabbitmq:3.8-management
节点2
docker run -d --hostname my-rabbit2 --name rabbit2 -p 5673:5672 -p 15673:15672 -e RABBITMQ_ERLANG_COOKIE='rabbitcookie' --link rabbit1:my-rabbit1 rabbitmq:3.8-management
节点3
docker run -d --hostname my-rabbit3 --name rabbit3 -p 5674:5672 -p 15674:15672 -e RABBITMQ_ERLANG_COOKIE='rabbitcookie' --link rabbit1:my-rabbit1 --link rabbit2:my-rabbit2 rabbitmq:3.8-management
注意:由于Erlang节点间通过认证
Erlang cookie
的方式来允许互相通信,所以RABBITMQ_ERLANG_COOKIE必须设置为相同的
。
启动完成之后,使用docker ps
命令查看运行情况,确保RabbitMQ都已经启动。


内存节点和磁盘节点的选择:
- 每个RabbitMQ节点,要么是内存节点,要么是磁盘节点。
- 内存节点将所有的队列、交换器、绑定、用户等元数据定义都存储在内存中;而磁盘节点将元数据存储在磁盘中。
- 单节点系统只允许磁盘类型的节点,否则当节点重启以后,所有的配置信息都会丢失。
- 如果采用集群的方式,可以选择至少配置一个节点为磁盘节点,其余部分配置为内存节点,这样可以获得更快的响应。
所以本集群中配置节点1位磁盘节点,节点2和节点3位内存节点。
集群中的第一个节点将初始元数据代入集群中,并且无须被告知加入。而第2个和之后加入的节点将加入它并获取它的元数据。要加入节点,需要进入Docker容器,重启RabbitMQ。
设置节点1:
docker exec -it rabbit1 bash
rabbitmqctl stop_app
rabbitmqctl reset
rabbitmqctl start_app
exit
设置节点2:
docker exec -it rabbit2 bash
rabbitmqctl stop_app
rabbitmqctl reset
rabbitmqctl join_cluster --ram rabbit@my-rabbit1
rabbitmqctl start_app
exit
组成集群
rabbitmqctl join_cluster <clusternode> [--ram]
clusternode
:表示要加入的接点[–ram]
表示节点的存储模式,这个表示内存[–disk]
表示磁盘存储模式
设置节点3:
docker exec -it rabbit3 bash
rabbitmqctl stop_app
rabbitmqctl reset
rabbitmqctl join_cluster --ram rabbit@my-rabbit1
rabbitmqctl start_app
exit
image
节点设置完成之后,在浏览器访问
- 服务器ip:15672、
- 服务器ip:15673和
- 服务器ip:15674中任意一个,都会看到RabbitMQ集群已经创建成功 👇


5.测试

在my-rabbit1
这个节点上添加一个队列:

如图,在my-rabbit2
和my-rabbit3
两个控制台也都能看到:

5.1.数据共享测试
点击my-rabbit1
这个队列,进入管理页面:

然后利用控制台发送一条消息到这个队列:

结果在my-rabbit2
、my-rabbit3
上都能看到这条消息:

5.2.可用性测试
我们让其中一台节点my-rabbit1
宕机:
docker stop my-rabbit1

然后登录my-rabbit2或my-rabbit3的控制台,发现node1.queue
也不可用了:

说明数据并没有拷贝到mq2和mq3。
3.3.镜像模式
镜像模式
在刚刚的案例中,一旦创建队列的主机宕机,队列就会不可用。不具备高可用能力。如果要解决这个问题,必须使用官方提供的镜像集群方案。
官方文档地址:https://www.rabbitmq.com/ha.html
1.镜像模式的特征
默认情况下,队列只保存在创建该队列的节点上。而镜像模式下,创建队列的节点被称为该队列的主节点,队列还会拷贝到集群中的其它节点,也叫做该队列的镜像节点。
但是,不同队列可以在集群中的任意节点上创建,因此不同队列的主节点可以不同。甚至,一个队列的主节点可能是另一个队列的镜像节点。
用户发送给队列的一切请求,例如发送消息、消息回执默认都会在主节点完成,如果是从节点接收到请求,也会路由到主节点去完成。镜像节点仅仅起到备份数据作用。
当主节点接收到消费者的ACK时,所有镜像都会删除节点中的数据。
总结如下:
- 镜像队列结构是一主多从(从就是镜像)
- 所有操作都是主节点完成,然后同步给镜像节点
- 主宕机后,镜像节点会替代成新的主(如果在主从同步完成前,主就已经宕机,可能出现数据丢失)
- 不具备负载均衡功能,因为所有操作都会有主节点完成(但是不同队列,其主节点可以不同,可以利用这个提高吞吐量)
2. 镜像模式的配置
镜像模式的配置有3种模式:
ha-mode | ha-params | 效果 |
---|---|---|
准确模式exactly | 队列的副本量count | 集群中队列副本(主服务器和镜像服务器之和)的数量。count如果为1意味着单个副本:即队列主节点。count值为2表示2个副本:1个队列主和1个队列镜像。换句话说:count = 镜像数量 + 1。如果群集中的节点数少于count,则该队列将镜像到所有节点。如果有集群总数大于count+1,并且包含镜像的节点出现故障,则将在另一个节点上创建一个新的镜像。 |
all | (none) | 队列在群集中的所有节点之间进行镜像。队列将镜像到任何新加入的节点。镜像到所有节点将对所有群集节点施加额外的压力,包括网络I / O,磁盘I / O和磁盘空间使用情况。推荐使用exactly,设置副本数为(N / 2 +1)。 |
nodes | node names | 指定队列创建到哪些节点,如果指定的节点全部不存在,则会出现异常。如果指定的节点在集群中存在,但是暂时不可用,会创建节点到当前客户端连接到的节点。 |
代码操作
这里我们以rabbitmqctl命令
作为案例来讲解配置语法。
语法示例:
1.exactly模式
exactly:精确地
rabbitmqctl set_policy ha-two "^two\." '{"ha-mode":"exactly","ha-params":2,"ha-sync-mode":"automatic"}'
rabbitmqctl set_policy
:固定写法ha-two
:策略名称,自定义"^two\."
:匹配队列的正则表达式,符合命名规则的队列才生效,这里是任何以two.
开头的队列名称'{"ha-mode":"exactly","ha-params":2,"ha-sync-mode":"automatic"}'
: 策略内容"ha-mode":"exactly"
:策略模式,此处是exactly模式,指定副本数量"ha-params":2
:策略参数,这里是2,就是副本数量为2,1主1镜像"ha-sync-mode":"automatic"
:同步策略,默认是manual,即新加入的镜像节点不会同步旧的消息。如果设置为automatic,则新加入的镜像节点会把主节点中所有消息都同步,会带来额外的网络开销
docker中任意一个节点配置

往镜像1添加队列,观察是否镜像

将节点一停止,观察是否可用

2.all模式
可以设置镜像队列,"^"表示匹配所有队列,即所有队列在各个节点上都会有备份。在集群中,只需要在一个节点上设置镜像队列,设置操作会同步到其他节点。
rabbitmqctl set_policy ha-all "^all\." '{"ha-mode":"all"}'

ha-all
:策略名称,自定义"^all\."
:匹配所有以all.
开头的队列名'{"ha-mode":"all"}'
:策略内容"ha-mode":"all"
:策略模式,此处是all模式,即所有节点都会称为镜像节点

查看集群的状态:
rabbitmqctl cluster_status
3.nodes模式
rabbitmqctl set_policy ha-nodes "^nodes\." '{"ha-mode":"nodes","ha-params":["rabbit@nodeA", "rabbit@nodeB"]}'
rabbitmqctl set_policy
:固定写法ha-nodes
:策略名称,自定义"^nodes\."
:匹配队列的正则表达式,符合命名规则的队列才生效,这里是任何以nodes.
开头的队列名称'{"ha-mode":"nodes","ha-params":["rabbit@nodeA", "rabbit@nodeB"]}'
: 策略内容"ha-mode":"nodes"
:策略模式,此处是nodes模式"ha-params":["rabbit@mq1", "rabbit@mq2"]
:策略参数,这里指定副本所在节点名称
3.4 仲裁队列
仲裁队列
从RabbitMQ 3.8版本开始,引入了新的仲裁队列,他具备与镜像队里类似的功能,但使用更加方便。
代码操作
1.添加仲裁队列
在任意控制台添加一个队列,一定要选择队列类型为Quorum类型。

在任意控制台查看队列:
可以看到,仲裁队列的 + 2字样。代表这个队列有2个镜像节点。
因为仲裁队列默认的镜像数为5。如果你的集群有7个节点,那么镜像数肯定是5;而我们集群只有3个节点,因此镜像数量就是3.
2.测试
可以参考对镜像集群的测试,效果是一样的。