一、rabbitmq选型背景:
我们有个业务,业务特点是需要顺序消费队列消息,并且对可靠性和低延迟有高要求,同时我们的业务消息量不大,每秒2000以内,于是我们调研后选择rabbitmq来作为消息队列的载体,本片记录下,搭建的过程,后续会陆续更新,核心原理和设计理念
二、rabbitmq普通集群搭建过程:
1. 准备服务器 :
选择二台或多台服务器,配置尽量相同,如 CPU、内存、磁盘等。
2. 安装 Erlang 和 RabbitMQ :
在每个节点上安装相同版本的 Erlang 和 RabbitMQ 软件。
3. 配置 Erlang Cookie :
确保集群中所有节点的 Erlang Cookie 一致。默认情况下,Erlang Cookie 文件位于 /var/lib/rabbitmq/.erlang.cookie 。可以将其中一个节点的 .erlang.cookie 文件复制到其他节点的相同目录下,并确保文件权限为 600,即只有 rabbitmq 用户可读写。
chmod 600 .erlang.cookie
如何确认当前使用的cookie地址:
[@test-rabbitmq-4tiz.novalocal ~]# cat /proc/$(pgrep -f rabbitmq)/environ | tr '\0' '\n' | grep 'HOME'
HOME=/home/rabbitmq
4. 启动RabbitMQ服务 :
在每个节点上启动 RabbitMQ 服务。
4.1、启动命令
1)启动rabbitmq集群和erlang(把 Erlang 虚拟机 + RabbitMQ 应用 整个进程拉起来)
/data/rabbitmq_server-3.13.7/sbin/rabbitmq_server
2)已经运行的 Erlang 虚拟机里 把 RabbitMQ 应用 重新启动
rabbitmqctl start_app
4.2、关闭命令
1)直接把
RabbitMQ应用 + Erlang VM
全部关掉,进程消失
/data/rabbitmq_server-3.13.7/sbin/rabbitmqctl stop
2)仅关闭RabbitMQ应用
rabbitmqctl stop_app
5、加入集群
5.1、停止RabbitMQ应用
在要加入集群的节点上,使用 rabbitmqctl stop_app 命令停止 RabbitMQ 应用。
注意在
RabbitMQ 3.8 以后,可以不用先stop_app,直接join_cluster即可,CLI 会自动帮你做如下所示的过程:
1)你敲 rabbitmqctl join_cluster …
2)CLI 会
先把当前节点的应用停掉(相当于帮你执行一次 stop_app)
3)再去执行加入逻辑
4)最后
自动把应用重新拉起来(相当于执行 start_app)
所以
RabbitMQ 3.8 以后, 当你执行join_cluster的时候,
已经悄悄地帮你停了再启。
如果想手动控制,仍可以显式执行,如下所示:
rabbitmqctl stop_app
rabbitmqctl join_cluster rabbit@<other-node>
rabbitmqctl start_app
5.2、加入集群 :
使用 rabbitmqctl join_cluster 命令让节点加入集群。如 rabbitmqctl join_cluster rabbit@ ,其中 是主节点的主机名或 IP 地址。可添加 --ram 参数使节点以 RAM 节点身份加入,否则默认为磁盘节点。
[@test-rabbitmq-4tiz.novalocal ~]# su - rabbitmq
Last login: Sun Aug 10 00:20:32 CST 2025 on pts/1
[@test-rabbitmq-4tiz.novalocal ~]$ rabbitmqctl join_cluster rabbit@10.2.1.71
Clustering node rabbit@10.2.1.30 with rabbit@10.2.1.71
6. 验证集群状态 :
在任意节点上执行 rabbitmqctl cluster_status 命令,查看集群中各节点的状态。
7、修改节点类型:
7.1、磁盘节点将元数据(如队列、交换器、绑定关系等)存储在磁盘和内存中,支持集群状态持久化,每个集群至少需要一个磁盘节点。
7.2、内存节点仅将元数据存储在内存中,性能较高,但重启后数据丢失,适合对性能要求高但数据持久化要求低的场景。
rabbitmqctl stop_app
rabbitmqctl change_cluster_node_type ram #修改成内存类型
rabbitmqctl change_cluster_node_type disc #修改成磁盘类型
rabbitmqctl start_app
至此普通rabbitmq集群安装完毕,接下来配置镜像集群
三、搭建镜像集群
首先说明一点,镜像集群是依赖于普通集群,甚至镜像和普通集群在搭建上没有区别,镜像集群只是在普通集群上针对某个虚拟机,或者某个队列添加一下策略即可,换句话说镜像集群其实是针对某个虚拟机或者某个队列而言的,并不是broker节点级别的差距。
在 RabbitMQ 中,
镜像队列(Mirrored Queues) 是在普通集群的基础上,针对特定的虚拟主机(Virtual Host)或队列进行配置的。镜像队列并不是在 Broker 节点级别进行配置,而是通过策略(Policy)来指定哪些队列需要进行镜像。
2.1、创建虚拟主机 :
在主节点上使用 rabbitmqctl add_vhost 命令创建虚拟主机。
2.2、 设置镜像策略 :
使用 rabbitmqctl set_policy 命令为指定虚拟主机设置镜像策略。如 rabbitmqctl set_policy ha-all --vhost "" "^" '{"ha-mode":"all"}' ,表示将该虚拟主机下所有队列镜像到集群中的所有节点。
备注:如果没有显式指定 --apply-to,RabbitMQ 会有一个默认值:queues
rabbitmqctl set_policy ha_global_always "^" \
'{
"ha-mode": "all",
"ha-sync-mode": "automatic",
"ha-promote-on-failure": "always",
"ha-promote-on-shutdown": "always"
}' \
--apply-to queues \
--vhost "crm"
四、rabbitmq服务参数配置:
4.1、服务器内核参数修改:
# 持久写入
echo "fs.file-max = 1048576" >> /etc/sysctl.conf
echo "fs.nr_open = 2097152" >> /etc/sysctl.conf # 一般保持是 nofile 的 2 倍
sysctl -p # 立即生效
echo "* soft nofile 524288" >> /etc/security/limits.conf
echo "* hard nofile 524288" >> /etc/security/limits.conf
4.2、rabbitmq配置修改:
4.2.1、自定义配置文件目录:
1)rabbitmq-env.conf 是一个环境变量配置文件,用于设置 RabbitMQ 的运行时环境变量。这些变量可以覆盖默认的配置值。
rabbitmq-env.conf 文件的优先级高于默认配置文件 rabbitmq.conf,但低于命令行参数。可以在rabbitmq-env.conf文件中指定rabbitmq.conf的文件的路径。
2)rabbitmq.conf 是 RabbitMQ 的主配置文件,用于定义 RabbitMQ 服务和插件的设置。它是一个标准的 Erlang 配置文件,必须符合 Erlang 配置文件的标准
3)使用环境变量的方式指定rabbitmq的自定义配置文件的路径:
在安装rabbitmq的用户下,配置环境变量,指定RABBITMQ_CONF_ENV_FILE的文件路径。然后rabbitmq-env.conf文件里面可以配置具体的rabbitmq的配置文件rabbitmq.conf的路径
[@test-rabbitmq-4tiz.novalocal ~]$ id
uid=1002(rabbitmq) gid=1002(rabbitmq) groups=1002(rabbitmq)
[@test-rabbitmq-4tiz.novalocal ~]$ cat .bash_profile
# .bash_profile
# Get the aliases and functions
if [ -f ~/.bashrc ]; then
. ~/.bashrc
fi
# User specific environment and startup programs
PATH=$PATH:$HOME/.local/bin:$HOME/bin:/data/rabbitmq_server-3.13.7/sbin
export PATH
export RABBITMQ_CONF_ENV_FILE=/data/rabbitmq/etc/rabbitmq/rabbitmq-env.conf #指定rabbitma环境变量配置文件的路径
[@test-rabbitmq-4tiz.novalocal ~]$ cat /data/rabbitmq/etc/rabbitmq/rabbitmq-env.conf
NODENAME=rabbit@10.2.1.30 #节点的名字,建议使用长名字
RABBITMQ_SERVER_ADDITIONAL_ERL_ARGS="-name ${NODENAME}" #把节点名硬塞给 Erlang VM,解决默认短名问题
RABBITMQ_USE_LONGNAME=true #确保长名生效,否则节点名字使用ip会报错
CONFIG_FILE=/data/rabbitmq/etc/rabbitmq/rabbitmq.conf #指定rabbitmq主配置文件
RABBITMQ_MNESIA_BASE=/data/rabbitmq/mnesia #指定数据文件和mnesia数据存放的目录
[@test-rabbitmq-4tiz.novalocal ~]$
[@test-rabbitmq-4tiz.novalocal ~]$ cat /data/rabbitmq/etc/rabbitmq/rabbitmq.conf
cluster_name= test-rabbitmq
# 默认监听所有 IPv4 接口的 5672 端口
listeners.tcp.default = 0.0.0.0:5672
#选择当前拥有最少队列主节点(master)的节点
queue_leader_locator = balanced
# 接收连接进程数
num_acceptors.tcp = 15
num_acceptors.ssl = 15
# 允许 guest 用户远程登录(测试环境可用,生产请自建用户)
loopback_users.guest = false
# 内存高水位:物理内存的 40 %,内存触发流控
vm_memory_high_watermark.relative = 0.5
# 内存分页水位:高水位的 50 %,RabbitMQ 开始把消息 page 到磁盘的阈值
vm_memory_high_watermark_paging_ratio = 0.6
# 磁盘低水位:剩余磁盘 < 2 GB 时阻塞生产者
disk_free_limit.absolute = 2GB
# 日志级别:debug / info / warning / error
log.file.level = info
# 日志文件路径(默认在 $RABBITMQ_HOME/var/log)
log.file = /data/rabbitmq/logs/rabbitmq/rabbitimq.log
# 控制台输出
log.console = true
log.console.level = info
# HTTP 管理界面
management.tcp.port = 15672
management.tcp.ip = 0.0.0.0
# 统计粒度(none / coarse / fine)
collect_statistics = coarse
collect_statistics_interval = 5000
# 集群节点发现:静态列表示例,与 rabbitmq-env.conf 里的 NODENAME 完全一致,RabbitMQ 启动时就知道“我应该去跟哪几台机器组成集群
cluster_formation.classic_config.nodes.1 = rabbit@10.2.1.30
cluster_formation.classic_config.nodes.2 = rabbit@10.2.1.71
# 网络分区处理策略,优先保证服务连续性,可能丢数据
cluster_partition_handling = autoheal
# 可选值:ignore / pause_minority / autoheal / pause_if_all_down
tcp_listen_options.backlog = 512
tcp_listen_options.nodelay = true
tcp_listen_options.linger.on = true
tcp_listen_options.linger.timeout = 0
tcp_listen_options.keepalive = true
channel_max = 3047 # 最大通道数
frame_max = 131072 # 最大帧大小(字节)
heartbeat = 60 # 心跳秒数,每 heartbeat/2 秒发一次空帧;两次收不到即判定失效
max_message_size = 16777216 # 单条消息最大 16 MB
# 小于该字节数的消息直接嵌入队列索引
queue_index_embed_msgs_below = 4096
# 预取计数:控制消费者一次获取的消息数量(默认 300)
cluster_keepalive_interval =10000
4.3、rabbitmq启动命令配置成service
[@test-rabbitmq-x5xm.novalocal /etc/systemd/system]# cat rabbitmq.service
[Unit]
Description=RabbitMQ Messaging Server
After=network.target
[Service]
Type=notify
User=rabbitmq
Group=rabbitmq
Environment="RABBITMQ_CONF_ENV_FILE=/data/rabbitmq/etc/rabbitmq/rabbitmq-env.conf"
ExecStart=/data/rabbitmq_server-3.13.7/sbin/rabbitmq-server
ExecStop=/data/rabbitmq_server-3.13.7/sbin/rabbitmqctl stop
Restart=on-failure
RestartSec=10
LimitNOFILE=65536
[Install]
WantedBy=multi-user.target
4.4、启动管理平台插件:
注意如果需要使用rabbitmq的管理后台,需要安装如下插件,然后才可以使用
rabbitmq-plugins enable rabbitmq_management
五、rabbitmq的相关端口介绍:
RabbitMQ(3.13.x)默认或常用端口速览
六、创建虚拟机和账号管理:
6.1、创建管理员账号:注意管理账号也不能看到所有的队列数据,只能看到已经授权的队列的数据
[@test-rabbitmq-x5xm.novalocal ~]$ rabbitmqctl add_user admin Xikounan#sohu123
Adding user "admin" ...
Done. Don't forget to grant the user permissions to some virtual hosts! See 'rabbitmqctl help set_permissions' to learn more.
[@test-rabbitmq-x5xm.novalocal ~]$ rabbitmqctl set_user_tags admin administrator
Setting tags for user "admin" to [administrator] ...
[@test-rabbitmq-x5xm.novalocal ~]$ rabbitmqctl set_permissions -p / admin ".*" ".*" ".*" #授权根虚拟机的所有队列的所有权限
Setting permissions for user "admin" in vhost "/" ...
6.2、创建业务虚拟机和账号:
[@test-rabbitmq-x5xm.novalocal ~]$ rabbitmqctl add_vhost crm #针对crm业务创建虚拟机
Adding vhost "crm" ...
[@test-rabbitmq-x5xm.novalocal ~]$ rabbitmqctl add_user crm Lkjsldfjlsjk.123Lkd #创建账号并指定密码
Adding user "crm" ...
Done. Don't forget to grant the user permissions to some virtual hosts! See 'rabbitmqctl help set_permissions' to learn more.
[@test-rabbitmq-x5xm.novalocal ~]$ rabbitmqctl set_user_tags crm management #授权crm账号可以访问管理后台
Setting tags for user "crm" to [management] ...
[@test-rabbitmq-x5xm.novalocal ~]$ rabbitmqctl set_permissions -p crm crm ".*" ".*" ".*" #授权crm账号可以管理和读写crm虚拟机下的队列的权限
Setting permissions for user "crm" in vhost "crm" ...