Skip to content

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 status
text
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_management
text
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单节点,最快可丢的普通任务
quorumRaft 复制,多数派确认生产推荐,要求不丢
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 consumers
text
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 dlq
text
order.dlq       184

DLQ 有积压说明有消息处理失败,要找原因而不是直接清空。

六、集群 ​

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_app
text
Clustering node rabbit@mq-2 with rabbit@mq-1 ...
bash
rabbitmqctl cluster_status
text
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: 943

limit: 1024 说明没生效。systemd 里设:

ini
# /etc/systemd/system/rabbitmq-server.service.d/limits.conf
[Service]
LimitNOFILE=65535
bash
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