线上系统消息堆积?先看看你的RabbitMQ怎么配的
上周同事小李值班,半夜被报警叫醒——订单处理延迟了二十分钟。查了一圈发现是消费者挂了,但奇怪的是重启后消息还是积压。最后翻到RabbitMQ管理界面才发现,队列里躺着八万多条未确认的消息。其实问题不在代码,而在配置。
基础配置别偷懒,vhost和用户权限得分开
很多人图省事,直接用默认的/ vhost,所有服务都连guest用户。生产环境这么干,出问题是早晚的事。不同业务应该用不同的vhost隔离,比如订单系统用/order,支付走/payment。用户也按需创建,给最小权限。
rabbitmqctl add_vhost order
rabbitmqctl add_user order_user order_pass
rabbitmqctl set_permissions -p order order_user ".*" ".*" ".*"这样就算某个服务的凭证泄露,也不会波及整个MQ集群。
队列设置要“防呆”,TTL和死信队列不能少
消息丢了没人管?设置个过期时间最实在。特别是那种临时任务,比如生成报表链接,超过5分钟就没意义了。
{
"arguments": {
"x-message-ttl": 300000,
"x-dead-letter-exchange": "dlx.order",
"x-dead-letter-routing-key": "order.failed"
}
}加上死信队列后,超时或消费失败的消息会自动转到指定队列,方便后续排查或重试。
网络波动常见,心跳和连接恢复得配好
云服务器偶尔抖一下,连接断了怎么办?客户端得能自己 reconnect。同时服务端也要设合理的心跳间隔,避免误判。
# rabbitmq.conf
heartbeat = 60
connection_timeout = 60000客户端这边以Spring Boot为例:
spring.rabbitmq.listener.simple.retry.enabled=true
spring.rabbitmq.listener.simple.retry.max-attempts=3
spring.rabbitmq.connection-timeout=15000这样短时间网络抖动不会直接把消费者搞崩。
监控不是摆设,关键指标得盯着
光看队列长度不够,还得关注消息速率、消费者数量、未确认数。我们用Prometheus抓取RabbitMQ的/exported接口,配上Grafana看板。某天发现未确认数持续上涨,一查是数据库慢查询拖慢了消费速度,及时扩容了消费者实例。
另外记得打开firehose做链路追踪(只在排查问题时开,性能损耗大):
rabbitmqctl trace_on磁盘和内存告警,资源限制要提前设
有一次测试环境跑着跑着突然不收消息了,进去一看,提示“disk space limit exceeded”。原来是默认配置下磁盘剩下一GB就拒绝写入。生产环境当然不能这么紧。
# 设置为物理内存的三倍作为阈值
disk_free_limit.relative = 3.0内存也是,别等OOM,提前设好软限制:
vm_memory_high_watermark.relative = 0.4到了40%就开始警告,60%开始丢弃消息或阻塞生产者。
这些配置不是抄完就完事,得结合自己的业务节奏调。比如大促前主动调高阈值,避免因为一条配置让系统卡住。