RabbitMQ - 集群搭建教程附带集群原理解析(Docker模式)

使用的环境信息如下: 

Docker Engine: 18.09.5

Linux: CentOS Linux release 7.6.1810 (Core)

RabbitMQ: 3.11.2

一、安装前的环境准备

1、获取RabbitMQ的镜像

执行一下命令:

docker pull rabbitmq:3.11.2-management

镜像拉去之后,需要重新TAG后上传到Harbor中,该流程省略。上传到Harbor中的镜像为:

10.18.245.184/rabbitmq/release:3.11.2-management

2、为节点准备服务器资源

RabbitMQ集群有多种不同类型的节点,它们的行为都不太一样。当向集群中添加节点时,它必须是磁盘节点或者内存节点。磁盘节点将集群的运行时状态会同时存储在内存和磁盘上。在RabbitMQ中,运行时状态包括集群、队列、绑定、虚拟主机、用户和策略等信息的定义。鉴于此,如果集群拥有大量的运行时状态时,相比内存节点,磁盘节点更容易受到磁盘I/O问题的困扰。

内存节点仅将运行时状态信息存储在内存数据库中。

节点类型和消息持久化问题

不论是哪种节点类型都不会影响消息持久化的行为。当通过消息属性delivery-mode将一条消息标记为持久化时,这条消息会被写入磁盘,而无关乎节点类型。因此,考虑磁盘I/O对RabbitMQ集群节点的影响就显得很尤为重要。如果需要持久化消息的话,你应当提供磁盘子系统来满足集群节点中队列写入速度的要求。

节点类型与崩溃行为

当节点或者集群崩溃时,在磁盘节点启动并重新加入集群时,会被用来重建集群的运行时状态。而对于内存节点来说,当加入集群时则不会包含任何运行时状态数据。在重新加入集群时,集群中的其他节点会将诸如队列定义等信息发送给它。

当创建集群时,确保至少存在一个磁盘型节点。当集群中拥有多个磁盘节点时,就能在发生硬件故障时更加游刃有余。但多个磁盘节点在某些故障场景下是一把双刃剑。当集群中有多个节点故障时,如果其中两个磁盘节点对集群的共享状态不一致,那么你在尝试将集群恢复至先前状态时就会遇到困难。假设这事儿真的发生了,那么建议将整个集群关闭并按顺序重启节点。启动那个持有最多正确状态数据的磁盘节点,然后再添加其他节点。本章后面部分,我们将讨论故障排除与集群恢复的其他策略

状态节点

如果你使用rabbitmq管理插件的话,那么你可以使用另一种节点类型,即统计节点(Stats node)。它只能和磁盘节点搭配使用。统计节点负责收集集群中每个节点的全部统计数据和状态数据。在任意时刻,一个集群只能有一个统计节点。对于大型集群设置来说,最佳策略是配置专门的管理节点,即主磁盘节点和统计节点,并再至少配置一个磁盘节点以提供故障转移的能力(见图7.3)。

图7.3 带有备用磁盘节点和两个内存节点的集群

根据管理API的使用频率和用途以及RabbitMQ中使用的资源数量,运行管理API可能会带来较高的CPU成本。运行专们用于管理的节点服务器可确保消息投递和统计数据收集这两之间互不影响。

在拥有两个磁盘节点的集群拓扑设置中,如果主节点发生故障的话,统计节点将会被指派给备用磁盘节点。当主磁盘节点恢复并重新加入集群后,它并不会重新获得统计节点,除非被指派为统计节点的备用节点停止运行或者离开集群。

在RabbitMQ集群的管理方面统计节点扮演着重要的角色。要是没有了RabbitMQ管理插件和统计节点的话,获取集群范围内的性能、连接、队列深度和运营问题等数据将变得十分困难。

 基于以上观点,节点服务器如下:

IP节点类型
10.18.247.55磁盘节点(统计节点、状态节点)
10.18.247.53磁盘节点
10.18.247.48内存节点
10.18.247.46内存节点

因为RabbitMQ节点使用短域名或全限定域名 (FQDN) 相互寻址,所以以上四台服务器都要设置如下解析。

cat >> /etc/hosts <<'EOF'
10.18.247.55 node01
10.18.247.53 node02
10.18.247.48 node03
10.18.247.46 node04
EOF

二、集群搭建

1、Erlang Cookie的配置

RabbitMQ使用Erlang內建的多节点通信机制来实现节点间的通信。Erlang和RabbitMQ进程使用共享的安全文件cookie。Erlang cookie文件包含在RabbitMQ的数据目录下。在*NIX平台上,该文件通常位于/var/lib/rabbitmq/.erlang.cookie中,不同的版本间会有所差异。cookie文件包含了一个短字符串。集群中的每个节点的这个短字符串都是相同的。如果集群中的每个节点上的cookie文件都不一样的话,那么它们之间就不能相互通信了。

在首次启动RabbitMQ时或者该文件丢失时,cookie文件会被创建出来。在设置集群时,请确保RabbitMQ没有运行,并在再次启动RabbitMQ前将共享的cookie文件覆盖原有的那个cookie文件。

PS:使用rabbitmqctl是添加和删除集群节点的简单方法。我们也可以用它来将节点在磁盘节点和内存节点间来回切换。rabbitmqctl本质上包装了Erlang应用程序。该程序负责和RabbitMQ通信。正因如此,它需要访问Erlang cookie。当以root用户身份运行命令时,rabbitmqctl知道如何找到并使用cookie文件。如果你在产品环境中使用rabbitmqctl时遇到问题,请确保你运行rabbitmqctl的用户拥有访问RabbitMQ Erlang cookie的权限,或者在home目录下存有该文件的副本

接下来我们进行erlang.cookie的配置步骤,登录10.18.247.55,以该服务器第一次生成的Cookie为集群统一Cookie配置。

登录服务器后,拉取镜像:

docker pull 10.18.245.184/rabbitmq/release:3.11.2-management

拉取完成后执行,开始运行容器:

docker run --name rabbitmqNode01 --hostname=node01 \
-v /home/rabbitmq/data:/var/lib/rabbitmq \
--net=host \
-d 10.18.245.184/rabbitmq/release:3.11.2-management

重点参数解释如下:

  1. --hostname: RabbitMQ节点使用短域名或全限定域名 (FQDN) 相互寻址。因此,所有集群成员的主机名必须可以从所有集群节点以及可能使用rabbitmqctl等命令行工具的机器上解析。解析可以使用任何标准操作系统提供的方法,例如:DNS记录、主机解析文件(/etc/hosts)。docker启动方式设置之后,需要在/etc/hosts中默认添加 10.18.247.55 node01 解析记录;
  2. -v:挂在文件夹路径;
  3. --net=host:网络模式使用host。
  4. 5672端口:5672, 5671 (AMQP 0-9-1 without and with TLS)AMQP 是 Advanced Message Queuing Protocol 的缩写,一个提供统一消息服务的应用层标准高级消息队列协议,是应用层协议的一个开放标准,专为面向消息的中间件设计。基于此协议的客户端与消息中间件之间可以传递消息,并不受客户端/中间件不同产品、不同的开发语言等条件的限制。Erlang 中的实现有 RabbitMQ 等;
  5. 15672端口:(if management plugin is enabled)通过 http://serverip:15672 访问 RabbitMQ 的 Web 管理界面,默认用户名密码都是 guest。(注意:RabbitMQ 3.0之前的版本默认端口是55672);
  6. 4369端口:集群通信端口。

复制Cookie信息:

docker cp rabbitmqNode01:/var/lib/rabbitmq/.erlang.cookie /home/rabbitmq/data/.erlang.cookie

获取信息并在其他服务器节点创建Cookie信息:

cat /home/rabbitmq/data/.erlang.cookie

复制上面命令展示的内容后,依次在相关节点创建/home/rabbitmq/data/.erlang.cookie,设置相同的Cookie就可以了。

PS:如果在容器启动的状态下,修改了Cookie信息,在进入容器使用rabbitmqctl命令时候会报错,如果遇到这种情况,删除容器后,在此启动就可以了;记得docker run中--hostname的值要指定当前宿主机的ip解析配置;--name的值尽量命名为rabbiamqNode01、rabbitmqNode02、rabbitmqNode03.....

2、容器节点加入集群

上面也说了,以10.18.247.55为统计节点,我们需要进入该容器中,来重置节点,将 RabbitMQ 节点返回到其原始状态。

# 进入第一个rabbitmq节点容器
docker exec -it rabbitmqNode01 /bin/bash
# rabbitmqctl stop 会将 Erlang 虚拟机关闭,rabbitmqctl stop_app只关闭RabbitMQ 服务
rabbitmqctl stop_app
# 重置节点,将 RabbitMQ 节点返回到其原始状态。
rabbitmqctl reset
# 只启动应用服务
rabbitmqctl start_app
# 退出容器
exit

分别进入到10.18.247.53、10.18.247.48、10.18.247.46服务器中,执行以下命令:

// 进入容器
docker exec -it rabbitmqNode02 /bin/bash
// 停止
rabbitmqctl stop_app
// 重置
rabbitmqctl reset
// 加入集群
rabbitmqctl join_cluster rabbit@node01
// 启动
rabbitmqctl start_app
// 推出容器
exit

这里对以上的操作命令进行解释:

  1. rabbitmqctl stop_app 不会停止RabbitMQ服务器进程本身,而是使用rabbitmq来指示RabbitMQ停止Erlang中的内部进程;
  2. rabbitmqctl reset 清除RabbitMQ节点的状态,包括任何运行时配置数据和状态;特别是节点之前单独运行,后来需要加入到某个集群的情况,如果不清除相关数据,可能会导致节点数据不一致等问题;
  3. rabbitmqctl join_cluster rabbit@node01 加入主节点集群;
  4. rabbitmqctl start_app 启动服务;

每执行完一台服务器之后,我们可以执行以下命令查看集群状态:

rabbitmqctl cluster_status

全部执行完成之后,我们会看到如下信息:

三、RabbitMQ Management的使用

1、设置用户

# 进入任一节点容器创建
# 创建账号
rabbitmqctl add_user admin admin123
# 设置用户角色
rabbitmqctl set_user_tags admin administrator
# 设置用户权限
rabbitmqctl set_permissions -p "/" admin ".*" ".*" ".*"

设置完成之后,可访问地址如下:

http://10.18.247.55:15672/

http://10.18.247.53:15672/

http://10.18.247.48:15672/

http://10.18.247.46:15672/

用户就是上面设置的用户。

四、移除节点操作

# 在要关闭的节点上操作
$ rabbitmqctl  stop_app
# 在主节点上操作: 删除要移除的节点:-->例如要移除node02的操作如下
$ rabbitmqctl forget_cluster_node rabbit@node02

五、RAM(内存)节点与磁盘节点的修改

 主要区别为:

  • 磁盘节点:保存所有数据信息。
  • 内存节点:仅在RAM中存储内部数据库表。这不包括消息、消息存储索引、队列索引和其他节点状态。

理论上俩讲,应用中使用rabbitMQ的场景都是基于数据一致性的场景;RAM节点如果出现故障,节点中的消息将会丢失(当然是非HA的场景,也就是delivery-mode设置为2时,RAM节点一样不会丢失数据,但是性能将会下降,这个根据具体的实际场景而定),目前官方的建议是最好集群中全部都是磁盘节点。

修改内存节点的方法如下:

// 停止服务
rabbitmqctl stop_app
// 修改节点类型为 RAM
rabbitmqctl change_cluster_node_type ram
// 启动服务
rabbitmqctl start_app

使用rabbitmqctl cluster_status来查看修改结果:

  

问题整理

1、因为某些原因调整防火墙后报错

详细错误信息如下:

docker: Error response from daemon: driver failed programming external connectivity on endpoint rabbitmqNode02 (7309c7aae79cda2135fbf44de850cce723ceec77068aaa962ed9b75369c4c09c):  (iptables failed: iptables --wait -t nat -A DOCKER -p tcp -d 0/0 --dport 15672 -j DNAT --to-destination 172.17.0.2:15672 ! -i docker0: iptables: No chain/target/match by that name.
 (exit status 1)).

导致该问题的原因如下:

容器和物理机的通信是通过内核转发实现的,具体体现为iptables里添加的nat规则。之前没有安装iptables直接搭docker也会在iptables生成关于docker的nat规则,因为系统自带了iptables,只不过没有以服务的方式启动。 重新安装iptables会覆盖掉之前的规则,导致docker运行报错。只需要重启一下docker就会重新生成iptables规则了。

解决方式如下:

// 停止docker服务
systemctl stop docker

// 保存iptables
iptables-save >  /etc/sysconfig/iptables

// 启动docker服务
systemctl start docker

// 设置开机重启
systemctl enable docker

以上流程操作完成之后,可以再次执行docker run了。

2、反复要证的过程中执行rabbitmqctl stop_app报错问题

如果有反复验证的小伙伴,可能会出现,执行rabbitmqctl stop_app报错问题。大致错误信息如下:

attempted to contact: [rabbit@node01]

rabbit@node01:
  * connected to epmd (port 4369) on node01
  * epmd reports: node 'rabbit' not running at all
                  no other nodes on node01
  * suggestion: start the node

Current node details:
 * node name: 'rabbitmqcli-761-rabbit@node01'
 * effective user's home directory: /var/lib/rabbitmq
 * Erlang cookie hash: sw8BWCJdrbFzTgkPibvwug==

这是由于我们之前启动容器的时候执行命令如下:

docker run --name rabbitmqNode01 --hostname=node01 \
-v /home/rabbitmq/data:/var/lib/rabbitmq \
--net=host \
-d 10.18.245.184/rabbitmq/release:3.11.2-management

其中有一段-v /home/rabbitmq/data:/var/lib/rabbitmq的配置,在反复验证的过程中生成的数据冲突导致,执行以下命令清除该文件后,重新启动容器即可:

rm -rf /home/rabbitmq/data/*

 参考《深入RabbitMQ》

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
好的,以下是用 Docker 搭建 RabbitMQ 集群的步骤: 1. 首先,确保已经安装了 DockerDocker Compose。 2. 在本地创建一个新的文件夹,用于存储 RabbitMQ 的配置文件和数据。 3. 在该文件夹中创建一个名为 docker-compose.yml 的文件,并将以下内容复制到该文件中: ``` version: '3' services: rabbitmq-node1: image: rabbitmq:3.8-management-alpine hostname: rabbitmq-node1 environment: RABBITMQ_ERLANG_COOKIE: "secret_cookie" RABBITMQ_DEFAULT_USER: "admin" RABBITMQ_DEFAULT_PASS: "admin" ports: - "5672:5672" - "15672:15672" volumes: - ./data/node1:/var/lib/rabbitmq - ./config/rabbitmq.conf:/etc/rabbitmq/rabbitmq.conf networks: rabbitmq-network: aliases: - rabbitmq-node1 rabbitmq-node2: image: rabbitmq:3.8-management-alpine hostname: rabbitmq-node2 environment: RABBITMQ_ERLANG_COOKIE: "secret_cookie" RABBITMQ_DEFAULT_USER: "admin" RABBITMQ_DEFAULT_PASS: "admin" volumes: - ./data/node2:/var/lib/rabbitmq - ./config/rabbitmq.conf:/etc/rabbitmq/rabbitmq.conf networks: rabbitmq-network: aliases: - rabbitmq-node2 rabbitmq-node3: image: rabbitmq:3.8-management-alpine hostname: rabbitmq-node3 environment: RABBITMQ_ERLANG_COOKIE: "secret_cookie" RABBITMQ_DEFAULT_USER: "admin" RABBITMQ_DEFAULT_PASS: "admin" volumes: - ./data/node3:/var/lib/rabbitmq - ./config/rabbitmq.conf:/etc/rabbitmq/rabbitmq.conf networks: rabbitmq-network: aliases: - rabbitmq-node3 networks: rabbitmq-network: driver: bridge ``` 该文件定义了一个 RabbitMQ 集群,由三个节点组成。每个节点都有一个名称、一个主机名、一个环境变量(Erlang cookie、默认用户名和密码)、端口映射、数据卷和网络别名。该文件还定义了一个网络,用于连接三个节点。 4. 在该文件夹中创建一个名为 config 的文件夹,并在其中创建一个名为 rabbitmq.conf 的文件。将以下内容复制到该文件中: ``` cluster_formation.peer_discovery_backend = rabbit_peer_discovery_classic_config cluster_formation.classic_config.nodes.1 = rabbit@rabbitmq-node1 cluster_formation.classic_config.nodes.2 = rabbit@rabbitmq-node2 cluster_formation.classic_config.nodes.3 = rabbit@rabbitmq-node3 ``` 该文件定义了 RabbitMQ 集群的配置,包括节点发现方式和节点列表。 5. 在该文件夹中创建一个名为 data 的文件夹,用于存储 RabbitMQ 节点的数据。 6. 在终端中导航到该文件夹,并运行以下命令: ``` 回复:搭建rabbitmq集群需要使用Docker,可以参考Docker官方文档:https://docs.docker.com/engine/examples/rabbitmq/。好的,以下是如何使用Docker搭建RabbitMQ集群的步骤: 1. 首先,确保您已经在本地安装了Docker,并且已经在命令行中登录到了Docker。 2. 在命令行中输入以下命令,以在Docker中下载和运行RabbitMQ镜像: ``` docker run -d --name rabbitmq-node1 -p 5672:5672 -p 15672:15672 rabbitmq:3.8-management ``` 这将下载最新版本的RabbitMQ,并将其运行在Docker容器中。这里我们指定了两个端口,一个用于AMQP通信(5672),另一个用于Web管理界面(15672)。 3. 等待RabbitMQ容器启动后,您可以使用以下命令在另一个容器中运行第二个RabbitMQ节点: ``` docker run -d --name rabbitmq-node2 -p 5673:5672 -p 15673:15672 --link rabbitmq-node1:rabbit1 rabbitmq:3.8-management ``` 这将启动第二个RabbitMQ容器,并将其链接到第一个容器,以便它们可以互相通信。请注意,我们使用了不同的端口(5673和15673),以便避免与第一个节点的端口冲突。 4. 接下来,您可以使用以下命令启动第三个节点: ``` docker run -d --name rabbitmq-node3 -p 5674:5672 -p 15674:15672 --link rabbitmq-node1:rabbit1 --link rabbitmq-node2:rabbit2 rabbitmq:3.8-management ``` 同样,我们指定了不同的端口,并将此容器链接到前两个容器,以创建一个RabbitMQ集群。 5. 等待第三个节点启动后,您可以使用以下命令检查集群状态: ``` docker exec -it rabbitmq-node1 rabbitmqctl cluster_status ``` 这将显示集群中所有节点的状态。 恭喜!您已经成功地在Docker中部署了一个RabbitMQ集群。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值