RocketMQ Broker 0 处理延迟 32 秒排障实录:从现象到根因到修复

RocketMQ Broker 0 处理延迟 32 秒排障实录:从现象到根因到修复

生产环境 RocketMQ 4.8.0 broker-a:0 突发 RemotingTooMuchRequestException,putMessageEntireTimeMax 飙到 32s,消息积压如山。本文完整记录排查思路、根因定位和最终修复方案,踩坑点全量给出。

1. 现象

凌晨告警群炸了,三连击:

ini 复制代码
RemotingTooMuchRequestException: sendDefaultImpl call timeout
OFFSET_OVERFLOW_ONE
putMessageEntireTimeMax=32000ms(正常 < 100ms)
  • 消费延迟从秒级跳到分钟级
  • Producer 端大面积超时
  • Grafana 上 broker-a:0 的 PutMessageDistributeTime 直方图严重右偏

2. 环境背景

项目 配置
RocketMQ 版本 4.8.0
部署模式 2m-2s-async
broker-a 主机 10.10.40.96(rockermq01)
NameServer 10.10.40.96 ~ .99
JVM 配置 Xms8g/Xmx8g/Xmn4g,G1GC,InitiatingHeapOccupancyPercent=30
DirectMemory 15g
日志路径 ~/logs/rocketmqlogs/

3. 排查过程

3.1 第一反应:看 GC

bash 复制代码
# 查看 GC 日志
jstat -gcutil <pid> 1000 10

# 如果开了 GC 日志文件
tail -200 ~/logs/rocketmqlogs/gc.log

发现 Full GC 间隔从正常的几十分钟缩短到 2-3 分钟,单次耗时 800ms+。G1GC 下 InitiatingHeapOccupancyPercent=30 太激进,8g 堆在消息量大的场景下频繁触发并发标记。

3.2 看线程栈

bash 复制代码
jstack <pid> > /tmp/broker_stack.txt

关键发现:多个 PutMessageThread 线程 BLOCKED 在 CommitLog.putMessage 的锁上。说明写入已经串行化,这是延迟飙升的直接原因。

3.3 看磁盘 IO

bash 复制代码
iostat -x 1 10
vbnet 复制代码
Device:  await  svctm  %util
sda       45.2   12.1  89.3

%util 接近 90%,await 45ms,磁盘 IO 是瓶颈之一。CommitLog 顺序写依赖 page cache,如果内存不够就会触发频繁 flush。

3.4 看操作系统层面

bash 复制代码
# 看 broker 进程的内存映射
pmap -x <pid> | tail -5

# 看page cache占用
vmtouch /rocketmq/store/commitlog/

发现系统 free 内存不足 500MB,page cache 被其他进程挤压。RocketMQ 的 CommitLog 严重依赖 OS page cache 做顺序写加速,内存不够就直接退化到磁盘 IO。

3.5 OFFSET_OVERFLOW_ONE 的含义

这个不是根本原因,而是果------Consumer 拉取时 offset 比 CommitLog 最大 offset 大 1,通常是消息写入延迟导致 Consumer 轮询到尚未完成写入的 offset。修复写入延迟后自动消失。

4. 根因

三重叠加:

  1. JVM 堆偏小 + G1GC 触发阈值过低 → 频繁 GC 暂停写入线程
  2. OS 可用内存不足 → Page Cache 被压缩,CommitLog 顺序写退化为磁盘直写
  3. 磁盘 IO 接近饱和 → 写入延迟放大,PutMessageThread 锁竞争加剧

三者形成正反馈循环:GC 暂停 → 写入堆积 → IO 压力增大 → 写入更慢 → 堆积更多 → GC 更频繁

5. 修复方案

5.1 JVM 参数调优(立即生效)

bash 复制代码
# 修改 runbroker.sh 中的 JAVA_OPT
JAVA_OPT="${JAVA_OPT} -server -Xms16g -Xmx16g -Xmn8g"
JAVA_OPT="${JAVA_OPT} -XX:+UseG1GC -XX:InitiatingHeapOccupancyPercent=45"
JAVA_OPT="${JAVA_OPT} -XX:MaxDirectMemorySize=15g"
JAVA_OPT="${JAVA_OPT} -XX:G1HeapRegionSize=16m"
JAVA_OPT="${JAVA_OPT} -XX:G1ReservePercent=20"
JAVA_OPT="${JAVA_OPT} -XX:ParallelGCThreads=8"
JAVA_OPT="${JAVA_OPT} -XX:ConcGCThreads=4"

关键变更:

  • 堆从 8g → 16g,给消息索引更多内存空间
  • InitiatingHeapOccupancyPercent 从 30 → 45,减少不必要的并发标记
  • 增加 G1HeapRegionSize=16m,减少大对象跨 Region
  • G1ReservePercent=20 防止晋升失败

5.2 系统层优化

bash 复制代码
# 1. 释放被其他进程占用的内存(排查并清理无关服务)
# 2. 调整 vm.dirty_ratio 控制刷盘节奏
sysctl -w vm.dirty_ratio=10
sysctl -w vm.dirty_background_ratio=5

# 3. 确保 broker 进程的 oom_score 不被优先 kill
echo -1000 > /proc/<pid>/oom_score_adj

5.3 Broker 配置优化

properties 复制代码
# 增加发送线程池大小
sendMessageThreadPoolNums=32

# 开启消息索引异步构建
messageIndexEnable=true
indexRebuildThreadNums=4

# 优化 flush 策略
flushCommitLogTimed=true
flushCommitLogInterval=500

5.4 中期方案:磁盘升级

  • 将 SATA SSD 升级为 NVMe SSD
  • 或将 CommitLog 与 ConsumeQueue 分盘存储,减少 IO 争抢

6. 修复效果

指标 修复前 修复后
putMessageEntireTimeMax 32000ms < 50ms
Full GC 频率 每 2-3 分钟 < 1次/小时
磁盘 %util 89% 35%
消费延迟 分钟级 秒级
OFFSET_OVERFLOW_ONE 持续出现 消失

7. 踩坑总结

  1. G1GC 的 IHOP 不是越低越好:30% 在 8g 堆下意味着 2.4g 就触发标记,消息场景下太激进
  2. RocketMQ 的性能 = 内存 × 磁盘:Page Cache 被压缩时,再好的 JVM 参数也救不回来
  3. OFFSET_OVERFLOW_ONE 别急着调 Consumer offset:这是写入延迟的表象,修根因自动消失,手动调 offset 反而可能丢消息
  4. 2m-2s-async 的隐患:异步复制下 Master 压力大时 Slave 也会因复制延迟间接影响 Consumer 拉取
  5. 监控不能只看 Consumer 延迟:putMessageEntireTimeMax 才是 Broker 健康的核心指标

8. 监控告警建议

建议对以下指标设置告警:

yaml 复制代码
# Prometheus 告警规则示例
- alert: RocketMQPutMessageSlow
  expr: rocketmq_broker_put_message_entire_time_max > 1000
  for: 1m
  labels:
    severity: critical
  annotations:
    summary: "Broker {{ $labels.instance }} 写入延迟超过 1s"

- alert: RocketMQGCPause
  expr: increase(jvm_gc_pause_seconds_sum[5m]) > 10
  for: 2m
  labels:
    severity: warning
  annotations:
    summary: "Broker {{ $labels.instance }} GC 累计暂停过长"

一句话总结:RocketMQ Broker 写入延迟飙升,先看 GC 和内存,再看 IO,三重叠加时别只改一处------JVM、OS、Broker 配置要一起调。


本文基于 RocketMQ 4.8.0 生产环境真实排障记录整理,转载请注明出处。

相关推荐
开开心心就好9 分钟前
竖式除法出题工具,整除余数混合模式
运维·服务器·前端·javascript·ocr·perl·1024程序员节
领麦微红外27 分钟前
红外测温传感器 赋能充电桩热安全与运维智能化
运维·安全·产品经理·智能硬件
余额瞒着我当琳2 小时前
Linux初识:Linux的历史,计算机的发展脉络,发行版本,选购云服务器,安装Xshell,第一次连接,基础命令指南
linux·运维·服务器
时间售卖铺2 小时前
Docker实战:一键部署轻量级容器
运维·docker·云原生
山乐191312 小时前
麒麟系统,安装Nginx并配置https证书
运维·nginx·https
月落汀兰3 小时前
拒绝配置写死镜像!K8s 存储卷与配置管理,PV/PVC、ConfigMap、Secret 实战避坑指南
运维·kubernetes
服务器硬件项目经理3 小时前
《超节点修仙录》· 第一卷·炼气期【第04话】 超节点 vs 普通服务器——不就是多插了几张卡吗?
运维·服务器·人工智能·嵌入式硬件·深度学习·机器学习
杨云龙UP4 小时前
MySQL 主从复制管理:暂停、恢复、清理主从关系及命令执行位置
运维·数据库·mysql·主从配置·主从命令·reset replica·清除复制
Android系统攻城狮4 小时前
Linux FFmpeg深度解析之avcodec_parameters_from_context调用流程与实战(十六)
linux·运维·ffmpeg·音视频进阶·ffmpeg音视频·车载音视频进阶
隔窗听雨眠4 小时前
从存储引擎到执行计划:OceanBase高效运维的调优逻辑与工程实践
运维·oceanbase