一次线上OOM的定位排查解决记录

我靠,怎么服务一直OOM啊!!!
钉钉群里时不时来一个grafana的服务重启告警,一看总是这一个服务隔一段时间就OOM重启。奇怪,也没改什么代码啊,怎么会OOM呢。
想到之前为了解决服务经常503的问题,加大了tomcat线程池的最大数量(默认200加到了500),并加大了tomcat的连接最大请求复用数(默认还是200),这样加大服务的处理能力,并且同步增加了堆内存从2G-4G。
server:
tomcat:
threads:
max: 500
min-spare: 50
max-keep-alive-requests: 1000
keep-alive-timeout: 30000
后面观察503问题确实得到了解决。但是一个问题解决另一个更严重的问题来了,OOM。为什么会OOM呢,线程增加了内存不够?继续加加到4.5G。咦,还是OOM。
观察了一下老年堆,一直在缓慢增加,有内存泄漏?
看看先,话不多说。
直接上服务器终端 一执行 curl 'http://localhost/actuator/heapdump' -O ,哇哦,dump数据下来了。每天dump一次,再用工具一分析不就知道了有没有对象一直存活,内存泄漏了吗。
直接下载一个Eclipse的memory analysis tool(MAT)
再搜一个教程 https://cloud.tencent.com/developer/article/1803708 咔咔一顿操作,发现除了几个本地缓存一直存活外,其他也没有内存泄漏(常见ThreadLocal未关闭导致)啊。
看看其他项目配置,怎么就可以呢。
晕,其他项目加了新生代配置比例?我也加一个
XX:G1NewSizePercent=40 -XX:G1MaxNewSizePercent=50 -
加了加了,这下总行了吧。
看看,靠,怎么还OOM,都加到4.5G了,比其他项目qps低一些,内存分配的高一些怎么还OOM呢。
顶不住了,谁来救救我。
AI:听说你找我?
直接把配置一放
AI:你这配置一看就有问题,怎么不设置并发标记比例呢?
。。。。。。

jvm配置未设置G1垃圾回收器新生代比例(默认5%-60%动态调整),在高并发下小新生代Young GC 频繁,老年代晋升很快,老年代内存缓慢增加。且未配置并发标记回收比例,默认45%,在内存配置大(4G)的时候,老年堆进行MixedGC的时间(老年堆差不多到1.8G)也延后很多,到达MixedGC时间点时,由于老年堆对象已经很大且之前未经过任何MixedGC预热,回收的速度赶不上并发标记速度,导致老年堆一直缓慢增长,最后OOM。
解决方案:设置新生代比例40%-50%范围,减少YoungGC次数,避免对象过早晋升老年代。配置并发标记回收比例为30%,并减少最小最大堆内存(减少到3.5G),老年堆提前MixedGC释放垃圾和内存)
解决后:容器内存占用分配内存80%左右,每4-6小时进行一次MixedGC(老年堆对象到堆内存的30%,约1G时),回收约400M垃圾,老年代存活约600M长期对象,老年堆内存不再一直缓慢增加直至OOM,已解决服务频繁OOM问题

就这啊?胡言乱语一顿解释,同事直接叫我大佬了?

posted @ 2026-01-06 20:56  流年LL  阅读(21)  评论(0)    收藏  举报