外观
RabbitMQ:安装、vhost 与队列类型
RabbitMQ 的坑比 Kafka 集中:Erlang cookie、主机名解析、磁盘水位。配错任何一项,集群都起不来或突然阻塞生产者。
一、安装
bash
# Erlang 与 RabbitMQ 都用官方源(系统自带版本太老)
curl -s https://packagecloud.io/install/repositories/rabbitmq/erlang/script.rpm.sh | bash
curl -s https://packagecloud.io/install/repositories/rabbitmq/rabbitmq-server/script.rpm.sh | bash
yum install -y erlang rabbitmq-server
systemctl enable --now rabbitmq-server
rabbitmqctl statustext
Status of node rabbit@mq-1 ...
Runtime
OS PID: 41200
OS: Linux
Uptime (seconds): 42
RabbitMQ version: 3.13.7
Erlang configuration: Erlang/OTP 26 [erts-13.2.2]bash
rabbitmq-plugins enable rabbitmq_managementtext
Enabling plugins on node rabbit@mq-1:
rabbitmq_management
The following plugins have been configured:
rabbitmq_management
rabbitmq_management_agent
rabbitmq_web_dispatch
Applying plugin configuration to rabbit@mq-1...
started 3 plugins.控制台:http://10.0.0.31:15672,默认 guest/guest(只能本机登录)。
guest 只能本地登录
guest 用户被限制为 localhost 访问,远程登录会报 Login was refused using authentication mechanism PLAIN。生产必须新建管理员账号并删掉 guest,或至少改密码。
二、用户、vhost 与权限
bash
rabbitmqctl add_user admin 'AdminPass!2026'
rabbitmqctl set_user_tags admin administrator
rabbitmqctl add_vhost /shop
rabbitmqctl set_permissions -p /shop admin ".*" ".*" ".*"
rabbitmqctl add_user app 'AppPass!2026'
rabbitmqctl set_permissions -p /shop app "^order\..*" "^order\..*" "^order\..*"text
Adding user "admin" ...
Setting tags for user "admin" to [administrator] ...
Adding vhost "/shop" ...
Setting permissions for user "admin" in vhost "/shop" ...
Adding user "app" ...
Setting permissions for user "app" in vhost "/shop" ...set_permissions 三个正则依次是:
| 位置 | 管什么 |
|---|---|
| 第 1 个 | configure(声明/删除队列、交换机) |
| 第 2 个 | write(发消息) |
| 第 3 个 | read(消费消息) |
"^order\..*" 表示只能操作 order. 开头的资源。不要给业务账号 ".*" ".*" ".*"。
admin 标签决定能进控制台、能管用户:
| 标签 | 权限 |
|---|---|
administrator | 全部,含用户/vhost/策略管理 |
monitoring | 看控制台和指标 |
policymaker | 管策略和参数 |
management | 只能登录控制台 |
三、队列类型
| 类型 | 特点 | 适用 |
|---|---|---|
| classic | 单节点,最快 | 可丢的普通任务 |
| quorum | Raft 复制,多数派确认 | 生产推荐,要求不丢 |
| stream | 追加日志,可重复读 | 大吞吐、回放 |
bash
rabbitmqadmin -u admin -p 'AdminPass!2026' -V /shop \
declare queue name=order.created durable=true arguments='{"x-queue-type":"quorum"}'text
queue declared经典镜像队列已被移除
ha-mode: all 的经典镜像队列在 3.9 被标记废弃,4.0 起彻底移除。新部署直接用 quorum queue,不要照抄老文章的 set_policy ha-all。
quorum queue 的代价:
- 至少 3 个节点才有意义(多数派 = 2)。
- 吞吐比 classic 低(每次写要复制)。
- 不支持部分特性(如优先级队列、
x-expires)。
四、磁盘与内存水位
RabbitMQ 达到水位会阻塞所有生产者(不是丢消息,是暂停)。表现为应用端 publish 卡住。
bash
rabbitmqctl status | grep -A6 -i 'alarm\|memory\|disk'text
Memory
Total memory used: 1.2 GiB
High watermark: 0.6
...
Disk space
Low watermark: 50 MiB
Disk free limit: 50000000000 bytes
Disk free: 42.1 GiB配置:
ini
# /etc/rabbitmq/rabbitmq.conf
vm_memory_high_watermark.relative = 0.6
vm_memory_high_watermark.absolute = 4GB
disk_free_limit.absolute = 10GB
disk_free_limit.relative = 1.5| 配置 | 含义 |
|---|---|
vm_memory_high_watermark.relative | 内存用到 60% 就阻塞生产者 |
disk_free_limit.absolute | 剩余磁盘低于 10GB 就阻塞 |
阻塞的是生产者,不是消费者
水位触顶后,消费者可以继续消费、队列可以继续清空,但所有 publish 会阻塞。应用表现为接口超时,但日志里没有任何 RabbitMQ 错误——因为 TCP 连接还在,只是服务端不处理。
排查先看 rabbitmqctl status 的 alarm 段,或控制台的 "Connections → Blocked"。
五、常用命令
bash
rabbitmqctl list_queues -p /shop name messages consumerstext
Timeout: 60.0 seconds ...
Listing queues for vhost /shop ...
name messages consumers
order.created 12 2
order.paid 0 1
order.dlq 184 0| 命令 | 用途 |
|---|---|
rabbitmqctl list_queues name messages consumers memory | 队列积压 |
rabbitmqctl list_connections | 连接 |
rabbitmqctl list_channels | 信道 |
rabbitmqctl list_exchanges | 交换机 |
rabbitmqctl list_bindings | 绑定关系 |
rabbitmqctl list_consumers | 消费者 |
rabbitmqctl cluster_status | 集群状态 |
死信队列检查:
bash
rabbitmqctl list_queues -p /shop name messages | grep dlqtext
order.dlq 184DLQ 有积压说明有消息处理失败,要找原因而不是直接清空。
六、集群
bash
# 三台的 /var/lib/rabbitmq/.erlang.cookie 必须一致
cat /var/lib/rabbitmq/.erlang.cookie
# 在 node2、node3 上
rabbitmqctl stop_app
rabbitmqctl reset
rabbitmqctl join_cluster rabbit@mq-1
rabbitmqctl start_apptext
Clustering node rabbit@mq-2 with rabbit@mq-1 ...bash
rabbitmqctl cluster_statustext
Cluster status of node rabbit@mq-1 ...
Basics
Cluster name: rabbit@mq-1
Disk Nodes
rabbit@mq-1
rabbit@mq-2
rabbit@mq-3
Running Nodes
rabbit@mq-1
rabbit@mq-2
rabbit@mq-3主机名必须能互相解析
RabbitMQ 节点名是 rabbit@<hostname>。三台的 hostname 必须唯一,且 /etc/hosts 里要能互相解析到正确 IP。
改了主机名会导致:
- 节点名变化,旧数据目录对不上,起不来。
- cookie 校验失败。
部署前先把主机名和 hosts 定好,装完不要再改。
七、Ulimit
Erlang 默认只开 1024 个 fd,并发高时不够。
bash
rabbitmqctl status | grep -A5 'File Descriptors'text
File Descriptors
Total: 3, limit: 1024
Socket: 0, limit: 943limit: 1024 说明没生效。systemd 里设:
ini
# /etc/systemd/system/rabbitmq-server.service.d/limits.conf
[Service]
LimitNOFILE=65535bash
systemctl daemon-reload && systemctl restart rabbitmq-server八、常见故障
| 现象 | 原因 | 处置 |
|---|---|---|
| 远程登录 15672 失败 | 用的是 guest | 建新管理员 |
| 集群 join 失败 | cookie 不一致 | 同步 .erlang.cookie 后重启 |
| 节点名带随机后缀 | 主机名解析不到 | 修 /etc/hosts |
| 生产者全部阻塞 | 内存/磁盘水位 | 清队列、加磁盘、调水位 |
| 队列积压不消费 | 消费者断开 / prefetch 太小 | 看 consumers 数、调 prefetch_count |
| 消息重复 | 消费未 ack 就断开 | 消费端幂等 |
启动报 table ... already exists | 数据目录损坏 | 从备份恢复,或 reset 重建 |
| 控制台打不开 | 插件没启用 | rabbitmq-plugins enable rabbitmq_management |
九、踩过的坑
| 现象 | 根因 | 处置 |
|---|---|---|
| 改主机名后起不来 | 节点名变了 | 改回主机名,或重建数据 |
guest 远程登录被拒 | 安全限制 | 新建用户 |
| 所有生产者卡住 | 磁盘/内存水位 | 查 alarm 段 |
| 消费慢 | prefetch_count 默认 0(不限)或太小 | 设 50~300 |
| 消息进 DLQ 无人处理 | 没监控 DLQ | 监控 messages |
| 集群脑裂 | 网络分区 | 用 quorum queue,配 pause_minority |
| 队列无限增长 | 没有 x-max-length 和 TTL | 加长度限制 + DLQ |