场景

原有集群为 Rabbitmq 3.7.9,因业务需要,要使用 Rabbitmq 3.8 的新队列属性 x-single-active-consumer 且不能影响原有集群的运转,但资源有限,需要使用不同的端口启动新集群,故使用二进制部署方式。

惯例,介绍下这个:
x-single-active-consumer 属性用于控制队列的行为,确保在任何给定时间只有一个消费者可以活跃地从队列中消费消息。

这个特性对于某些特定的用例非常有用,比如:

  1. 避免消息重复处理:在某些应用场景中,你可能希望确保每条消息只被处理一次,即使在消费者崩溃或重启的情况下也是如此。
  2. 提高消息处理的确定性:在需要严格顺序处理消息的场景中,x-single-active-consumer 可以确保消息按照它们到达的顺序被单个消费者处理。
  3. 简化消费者实现:消费者实现可以简化,因为它们不需要处理消息的去重或确保消息的唯一性。
  4. 提高资源利用率:在某些情况下,如果有多个消费者竞争同一个队列中的消息,可能会导致资源浪费。使用 x-single-active-consumer 可以减少这种竞争。

当启用 x-single-active-consumer 属性时,RabbitMQ 会跟踪当前活跃的消费者,并确保只有当这个消费者断开连接时,其他消费者才能开始消费消息。
如果队列中没有消费者,消息将不会被消费,直到有一个新的消费者连接到队列。

这个属性的工作原理如下:

  • 当一个消费者订阅到启用了 x-single-active-consumer 的队列时,如果队列中没有其他活跃的消费者,它将成为活跃消费者,并开始接收消息。
  • 如果队列中已经有活跃的消费者,新的消费者将不会接收到任何消息,直到当前的活跃消费者断开连接。
  • 当活跃消费者断开连接时,如果有其他消费者订阅了队列,其中一个消费者将自动成为新的活跃消费者,并开始接收消息。

部署

无特殊说明的,3台机器做同样操作

准备工作

3 台机器,配置好 hosts

vim /etc/hosts
10.5.1.40 node1
10.5.1.41 node2
10.5.1.42 node3

创建目录,下载相关资源

mkdir -p /data/rabbitmq-3.8 && cd /data/rabbitmq-3.8
mkdir erlang_24.2
wget https://erlang.org/download/otp_src_24.2.tar.gz
wget https://github.com/rabbitmq/rabbitmq-server/releases/download/v3.8.34/rabbitmq-server-generic-unix-3.8.34.tar.xz

编译安装 erlang

初始环境

yum groupinstall -y "Development Tools"
yum install -y epel-release
yum install -y wxBase wxGTK3 wxGTK3-devel
yum install -y mesa-libGL-devel mesa-libGLU-devel
yum install -y ncurses-devel openssl-devel
yum install -y fop xsltproc unixODBC-devel

cd /usr/bin/
ln -sf wx-config-3.0 wx-config

编译安装

cd /data/rabbitmq-3.8/
tar xvf otp_src_24.2.tar.gz && cd otp_src_24.2
./configure --prefix=/data/rabbitmq-3.8/erlang_24.2
make && make install

部署 rabbitmq-3.8

编写 node1 机器配置文件和启动文件

# 解压
cd /data/rabbitmq-3.8/
tar xvf rabbitmq-server-generic-unix-3.8.34.tar.xz && cd rabbitmq_server-3.8.34

# 编写env配置文件
vim rabbitmq-env-3.8.conf
# 设置RabbitMQ节点的名称,用于集群中标识该节点
NODENAME=rabbitmq38@node1
# 设置RabbitMQ节点监听的AMQP协议默认端口
NODE_PORT=5673
# 定义Mnesia数据库的基础数据目录
RABBITMQ_MNESIA_BASE=/data/rabbitmq-3.8/rabbitmq_server-3.8.34/base
# 定义Mnesia数据库的文件存储目录
RABBITMQ_MNESIA_DIR=/data/rabbitmq-3.8/rabbitmq_server-3.8.34/base/mnesia
# 指定RabbitMQ的配置文件路径
RABBITMQ_CONFIG_FILE=/data/rabbitmq-3.8/rabbitmq_server-3.8.34/rabbitmq-3.8.conf
# 定义RabbitMQ日志文件的存储目录
RABBITMQ_LOG_BASE=/var/log/rabbitmq-3.8

# 编写配置文件
vim rabbitmq-3.8.conf
# 设置RabbitMQ监听的TCP端口,默认情况下与NODE_PORT相同
listeners.tcp.default = 5673
# 设置RabbitMQ管理界面的HTTP API监听端口,用于访问管理控制台
management.listener.port = 15673
# 定义日志文件的存放目录
log.dir = /var/log/rabbitmq-3.8
# 定义日志文件的名称,包括节点名称和版本号
log.file = rabbitmq38@node1-3.8.log

# 编写启动文件
vim start-rabbitmq-3.8.sh
#!/bin/bash
# 将Erlang的bin目录添加到PATH环境变量中,确保可以从任何位置调用Erlang相关的命令
export PATH=/data/rabbitmq-3.8/erlang_24.2/bin:$PATH
# 设置RABBITMQ_CONF_ENV_FILE环境变量,指向RabbitMQ的环境配置文件
export RABBITMQ_CONF_ENV_FILE=/data/rabbitmq-3.8/rabbitmq_server-3.8.34/rabbitmq-env-3.8.conf
# 启动RabbitMQ服务器,使用-detached选项使服务在后台运行
/data/rabbitmq-3.8/rabbitmq_server-3.8.34/sbin/rabbitmq-server -detached

# 创建相关目录、授权
mkdir -p /data/rabbitmq-3.8/rabbitmq_server-3.8.34/base
mkdir -p /var/log/rabbitmq-3.8
chown rabbitmq:rabbitmq /data/rabbitmq-3.8/rabbitmq_server-3.8.34/base
chown rabbitmq:rabbitmq /var/log/rabbitmq-3.8
chmod +x start-rabbitmq-3.8.sh

编写 node2 机器配置文件和启动文件

# 解压
cd /data/rabbitmq-3.8/
tar xvf rabbitmq-server-generic-unix-3.8.34.tar.xz && cd rabbitmq_server-3.8.34

# 编写env配置文件
vim rabbitmq-env-3.8.conf
# 设置RabbitMQ节点的名称,用于集群中标识该节点
NODENAME=rabbitmq38@node2
# 设置RabbitMQ节点监听的AMQP协议默认端口
NODE_PORT=5673
# 定义Mnesia数据库的基础数据目录
RABBITMQ_MNESIA_BASE=/data/rabbitmq-3.8/rabbitmq_server-3.8.34/base
# 定义Mnesia数据库的文件存储目录
RABBITMQ_MNESIA_DIR=/data/rabbitmq-3.8/rabbitmq_server-3.8.34/base/mnesia
# 指定RabbitMQ的配置文件路径
RABBITMQ_CONFIG_FILE=/data/rabbitmq-3.8/rabbitmq_server-3.8.34/rabbitmq-3.8.conf
# 定义RabbitMQ日志文件的存储目录
RABBITMQ_LOG_BASE=/var/log/rabbitmq-3.8

# 编写配置文件
vim rabbitmq-3.8.conf
# 设置RabbitMQ监听的TCP端口,默认情况下与NODE_PORT相同
listeners.tcp.default = 5673
# 设置RabbitMQ管理界面的HTTP API监听端口,用于访问管理控制台
management.listener.port = 15673
# 定义日志文件的存放目录
log.dir = /var/log/rabbitmq-3.8
# 定义日志文件的名称,包括节点名称和版本号
log.file = rabbitmq38@node2-3.8.log

# 编写启动文件
vim start-rabbitmq-3.8.sh
#!/bin/bash
# 将Erlang的bin目录添加到PATH环境变量中,确保可以从任何位置调用Erlang相关的命令
export PATH=/data/rabbitmq-3.8/erlang_24.2/bin:$PATH
# 设置RABBITMQ_CONF_ENV_FILE环境变量,指向RabbitMQ的环境配置文件
export RABBITMQ_CONF_ENV_FILE=/data/rabbitmq-3.8/rabbitmq_server-3.8.34/rabbitmq-env-3.8.conf
# 启动RabbitMQ服务器,使用-detached选项使服务在后台运行
/data/rabbitmq-3.8/rabbitmq_server-3.8.34/sbin/rabbitmq-server -detached

# 创建相关目录、授权
mkdir -p /data/rabbitmq-3.8/rabbitmq_server-3.8.34/base
mkdir -p /var/log/rabbitmq-3.8
chown rabbitmq:rabbitmq /data/rabbitmq-3.8/rabbitmq_server-3.8.34/base
chown rabbitmq:rabbitmq /var/log/rabbitmq-3.8
chmod +x start-rabbitmq-3.8.sh

编写 node3 机器配置文件和启动文件

# 解压
cd /data/rabbitmq-3.8/
tar xvf rabbitmq-server-generic-unix-3.8.34.tar.xz && cd rabbitmq_server-3.8.34

# 编写env配置文件
vim rabbitmq-env-3.8.conf
# 设置RabbitMQ节点的名称,用于集群中标识该节点
NODENAME=rabbitmq38@node3
# 设置RabbitMQ节点监听的AMQP协议默认端口
NODE_PORT=5673
# 定义Mnesia数据库的基础数据目录
RABBITMQ_MNESIA_BASE=/data/rabbitmq-3.8/rabbitmq_server-3.8.34/base
# 定义Mnesia数据库的文件存储目录
RABBITMQ_MNESIA_DIR=/data/rabbitmq-3.8/rabbitmq_server-3.8.34/base/mnesia
# 指定RabbitMQ的配置文件路径
RABBITMQ_CONFIG_FILE=/data/rabbitmq-3.8/rabbitmq_server-3.8.34/rabbitmq-3.8.conf
# 定义RabbitMQ日志文件的存储目录
RABBITMQ_LOG_BASE=/var/log/rabbitmq-3.8

# 编写配置文件
vim rabbitmq-3.8.conf
# 设置RabbitMQ监听的TCP端口,默认情况下与NODE_PORT相同
listeners.tcp.default = 5673
# 设置RabbitMQ管理界面的HTTP API监听端口,用于访问管理控制台
management.listener.port = 15673
# 定义日志文件的存放目录
log.dir = /var/log/rabbitmq-3.8
# 定义日志文件的名称,包括节点名称和版本号
log.file = rabbitmq38@node3-3.8.log

# 编写启动文件
vim start-rabbitmq-3.8.sh
#!/bin/bash
# 将Erlang的bin目录添加到PATH环境变量中,确保可以从任何位置调用Erlang相关的命令
export PATH=/data/rabbitmq-3.8/erlang_24.2/bin:$PATH
# 设置RABBITMQ_CONF_ENV_FILE环境变量,指向RabbitMQ的环境配置文件
export RABBITMQ_CONF_ENV_FILE=/data/rabbitmq-3.8/rabbitmq_server-3.8.34/rabbitmq-env-3.8.conf
# 启动RabbitMQ服务器,使用-detached选项使服务在后台运行
/data/rabbitmq-3.8/rabbitmq_server-3.8.34/sbin/rabbitmq-server -detached

# 创建相关目录、授权
mkdir -p /data/rabbitmq-3.8/rabbitmq_server-3.8.34/base
mkdir -p /var/log/rabbitmq-3.8
chown rabbitmq:rabbitmq /data/rabbitmq-3.8/rabbitmq_server-3.8.34/base
chown rabbitmq:rabbitmq /var/log/rabbitmq-3.8
chmod +x start-rabbitmq-3.8.sh

启动集群

每个节点都启动

# 3个节点一样操作
/data/rabbitmq-3.8/rabbitmq_server-3.8.34/start-rabbitmq-3.8.sh

修改 erlang.cookie 文件

# 查看node1的,直接复制
cat /root/.erlang.cookie
KZFHWZQPIFEONDOOZUMY

# 把内容复制到node2和node3上
vim /root/.erlang.cookie
KZFHWZQPIFEONDOOZUMY

node2node3 加入集群

# 两个节点一样操作,先停止服务
export PATH=/data/rabbitmq-3.8/erlang_24.2/bin:$PATH
export RABBITMQ_CONF_ENV_FILE=/data/rabbitmq-3.8/rabbitmq_server-3.8.34/rabbitmq-env-3.8.conf
/data/rabbitmq-3.8/rabbitmq_server-3.8.34/sbin/rabbitmqctl stop

# 重新启动服务
/data/rabbitmq-3.8/rabbitmq_server-3.8.34/start-rabbitmq-3.8.sh

# 把node2和node3加入集群
/data/rabbitmq-3.8/rabbitmq_server-3.8.34/sbin/rabbitmqctl stop_app
/data/rabbitmq-3.8/rabbitmq_server-3.8.34/sbin/rabbitmqctl reset
/data/rabbitmq-3.8/rabbitmq_server-3.8.34/sbin/rabbitmqctl join_cluster rabbitmq38@node1
/data/rabbitmq-3.8/rabbitmq_server-3.8.34/sbin/rabbitmqctl start_app

验证

集群配置

配置 web 页面、配置用户、配置镜像队列策略

# 随便一个节点上操作
# 配置环境变量
export PATH=/data/rabbitmq-3.8/erlang_24.2/bin:$PATH
export RABBITMQ_CONF_ENV_FILE=/data/rabbitmq-3.8/rabbitmq_server-3.8.34/rabbitmq-env-3.8.conf
# 创建用户
/data/rabbitmq-3.8/rabbitmq_server-3.8.34/sbin/rabbitmqctl add_user cloud 'cloud'
# 设置用户标签
/data/rabbitmq-3.8/rabbitmq_server-3.8.34/sbin/rabbitmqctl set_user_tags cloud administrator
# 设置权限
/data/rabbitmq-3.8/rabbitmq_server-3.8.34/sbin/rabbitmqctl set_permissions -p / cloud ".*" ".*" ".*"
# 检查用户和权限
/data/rabbitmq-3.8/rabbitmq_server-3.8.34/sbin/rabbitmqctl list_users
/data/rabbitmq-3.8/rabbitmq_server-3.8.34/sbin/rabbitmqctl list_permissions -p /
# 开启web管理插件
/data/rabbitmq-3.8/rabbitmq_server-3.8.34/sbin/rabbitmq-plugins enable rabbitmq_management
# 配置镜像队列策略
/data/rabbitmq-3.8/rabbitmq_server-3.8.34/sbin/rabbitmqctl  set_policy ha-queues "^.*" '{"ha-mode":"exactly","ha-params":3,"ha-sync-mode":"automatic"}'

web 访问验证

打开浏览器访问 http://<node-ip>:15673,使用 cloud 用户登录。检查集群状态和配置情况,确保 x-single-active-consumer 属性可用。

image.png

image.png

image.png

从图中可看到,集群部署完成、镜像队列策略配置完成、需要的队列属性 x-single-active-consumer 也有了,任务完成!


总结

通过以上步骤,我们成功在三台机器上部署了 RabbitMQ 3.8 集群,并启用了 x-single-active-consumer 特性。
这个特性确保在任何时间只有一个消费者活跃地消费消息,从而避免消息重复处理、提高处理确定性、简化消费者实现和提高资源利用率。

部署过程的要点

  1. 环境准备:确保三台机器配置一致,下载必要资源并安装依赖。
  2. 编译安装:安装 ErlangRabbitMQ,配置相关文件。
  3. 集群配置:启动服务,同步 erlang.cookie 文件,将节点加入集群。
  4. 功能验证:通过 Web 界面检查集群状态和新特性配置。

这个部署方案不仅满足了业务需求,还确保了原有集群的正常运行,充分利用了有限的资源。


文章作者: Runfa Li
本文链接:
版权声明: 本站所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明来自 Linux 小白鼠
Linux 消息队列 rabbitmq 二进制部署 运维 Centos7 Linux
觉得文章不错,打赏一点吧,1分也是爱~
打赏
微信 微信
支付宝 支付宝