消费服务堆从 2G 涨到 5.1G,GC 后也降不下来,jmap 直方图里 ConsumerRecord 和 byte[] 占了七成,重启后一小时又涨回去。第一次遇到会往复杂处想,其实漏掉的多是个小前提。

# consumer.properties
fetch.max.bytes=8388608
max.partition.fetch.bytes=1048576
max.poll.records=200
jmap -histo:live 21455 | head -20

单次 fetch 最多拉 50MB,多个分区并行时每个分区都攒一批,业务处理慢导致记录在堆里排队。max.poll.records 只限制条数,不限制字节数。这一点先确认清楚,后面就不用反复试。

「Kafka 批量拉取内存」这个问题文档写得含糊,实际行为以当前版本为准,别照旧版本的结论套。把这次用到的命令存进笔记,比记住结论有用,换个环境还能照着走。

改完隔一天再看一次,当场正常不代表能稳住。测试环境和线上的差别,往往就在版本号和那几行被忽略的配置上。

线上出问题先对时间点,跟发布、备份、任务执行的时刻排一排,能省掉一半功夫。

具体做法是,把 fetch.max.bytes 调到 8MB 单次别拉太多;max.partition.fetch.bytes 同步调小到 1MB;处理完的记录及时释放引用 不要在本地列表里攒批;用 jmap -histo 对比调整前后的 byte[] 占用。

改完照着核一遍,稳定运行两小时堆占用维持在 3G 以下 GC 后能回落到 1.5G 左右。

作者 9823189