news 2026/8/27 10:36:39

记一次线上OOM排查,JVM调优全过程

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
记一次线上OOM排查,JVM调优全过程

周三下午,正在摸鱼,突然钉钉群里炸了:

[告警] 订单服务 POD重启 [告警] 订单服务 POD重启 [告警] 订单服务 POD重启

3个Pod连续重启,打开监控一看,内存直接打满然后被K8s杀掉了。

经典的OOM。

现象

  • 服务:订单服务(Java,Spring Boot)
  • 部署:K8s,3个Pod,每个限制4G内存
  • 现象:内存缓慢增长,到达4G后被OOM Kill
  • 频率:每隔2-3小时重启一次

第一反应:加内存?

领导说:内存不够就加嘛。

我:…加内存治标不治本,得找到根因。

排查过程

1. 先看GC日志

# JVM参数里加上GC日志-XX:+PrintGCDetails -XX:+PrintGCDateStamps -Xloggc:/logs/gc.log

等了一个小时,服务挂了,捞出GC日志:

[Full GC (Allocation Failure) 3800M->3750M(4096M), 5.234 secs] [Full GC (Allocation Failure) 3780M->3760M(4096M), 5.567 secs] [Full GC (Allocation Failure) 3790M->3785M(4096M), 6.012 secs]

Full GC后内存几乎没释放,说明有内存泄漏,有东西一直占着不放。

2. dump内存

在容器里加了个脚本,OOM前自动dump:

# JVM参数-XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=/logs/heap.hprof

但K8s的OOM Kill太快了,还没来得及dump就被杀了。

换个方式,手动dump:

# 找到Java进程PIDjps# 手动dump(等内存涨到3G左右时执行)jmap -dump:format=b,file=/logs/heap.hprof<pid>

dump出来一个3G的文件。

3. 分析heap dump

把文件拷到本地,用MAT(Memory Analyzer Tool)打开。

Leak Suspects Report: Problem Suspect 1: 256,789 instances of "com.xxx.OrderDTO" 占用内存:2.1 GB (54%)

25万个OrderDTO对象?这订单量也没这么大啊。

点进去看引用链:

java.util.concurrent.ConcurrentHashMap -> com.xxx.cache.LocalCache -> OrderDTO (256789 instances)

LocalCache,本地缓存。

4. 定位代码

// LocalCache.javapublicclassLocalCache{privatestaticfinalMap<String,OrderDTO>cache=newConcurrentHashMap<>();publicstaticvoidput(StringorderId,OrderDTOorder){cache.put(orderId,order);}publicstaticOrderDTOget(StringorderId){returncache.get(orderId);}// 没有remove方法// 没有过期机制// 没有大小限制}

经典错误:只往缓存里放,不清理。

一查代码提交记录,是3个月前一个同事为了"优化性能"加的,从那之后这个服务就开始间歇性OOM。

5. 修复

方案一:直接删掉这个缓存(最简单)

方案二:换成带过期的缓存

// 用Caffeine替代privatestaticfinalCache<String,OrderDTO>cache=Caffeine.newBuilder().maximumSize(10000)// 最多1万条.expireAfterWrite(5,TimeUnit.MINUTES)// 5分钟过期.build();publicstaticvoidput(StringorderId,OrderDTOorder){cache.put(orderId,order);}publicstaticOrderDTOget(StringorderId){returncache.getIfPresent(orderId);}

上线后,内存稳定在1.5G左右,再也没OOM过。

JVM参数调优

趁这个机会,把JVM参数也优化了一下。

之前的配置

-Xms2g -Xmx4g# 就这两个参数...

优化后的配置

# 堆内存-Xms4g -Xmx4g# 初始和最大一样,避免动态调整-XX:NewRatio=2# 年轻代:老年代 = 1:2# GC选择(JDK11+推荐G1)-XX:+UseG1GC -XX:MaxGCPauseMillis=200# 目标停顿时间200ms-XX:G1HeapRegionSize=8m# Region大小# 元空间-XX:MetaspaceSize=256m -XX:MaxMetaspaceSize=256m# GC日志-Xlog:gc*:file=/logs/gc.log:time,level,tags:filecount=5,filesize=100m# OOM时dump-XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=/logs/# 容器感知(JDK8u191+)-XX:+UseContainerSupport -XX:MaxRAMPercentage=75.0# 使用容器内存的75%

监控指标

加了几个关键监控:

# Prometheus指标-jvm_memory_used_bytes-jvm_gc_pause_seconds_sum-jvm_gc_pause_seconds_count-jvm_classes_loaded_classes_total

设置告警:

  • 老年代使用率 > 80% 持续5分钟
  • Full GC 频率 > 1次/分钟
  • GC停顿时间 > 1秒

排查工具汇总

场景工具命令
查看堆内存jmapjmap -heap
dump内存jmapjmap -dump:format=b,file=heap.hprof
分析dumpMAT图形界面
实时监控jstatjstat -gcutil 1000
查看线程jstackjstack
在线分析Arthasdashboard/heapdump

Arthas神器

推荐用Arthas,在线诊断特别方便:

# 下载启动curl-O https://arthas.aliyun.com/arthas-boot.jar java -jar arthas-boot.jar# 选择要attach的进程后:# 查看堆内存dashboard# 查看最占内存的对象heapdump --live /tmp/heap.hprof# 查看某个类的实例数sc -d com.xxx.OrderDTO vmtool --action getInstances --className com.xxx.OrderDTO --limit10# 查看方法调用watchcom.xxx.LocalCache put'{params, returnObj}'-x2

远程调试

这次OOM排查还好在公司,能直接连到服务器。

如果在家收到告警,K8s集群在公司内网,怎么办?

之前的方案是远程专线,但经常断,而且手机上操作kubectl很难受。

后来用星空组网把电脑和跳板机组到一起,在家也能kubectl进容器排查了。

总结

这次OOM排查的经验:

步骤工具/方法
1. 确认OOM监控告警、GC日志
2. dump内存jmap / HeapDumpOnOutOfMemoryError
3. 分析dumpMAT / jhat
4. 定位代码引用链分析
5. 修复上线代码修改
6. 加固监控JVM监控指标

常见的内存泄漏原因:

  • 缓存无限增长(本次)
  • 静态集合持续添加
  • 未关闭的连接/流
  • ThreadLocal使用不当
  • 监听器未注销

最后,写缓存的时候一定要想清楚:

  • 什么时候过期?
  • 最大存多少?
  • 怎么清理?

不然就等着半夜被电话叫醒吧。


有JVM相关问题欢迎评论区交流。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/8/26 20:10:45

股票基础-第33课-长期投资策略与财富增长

一、长期投资理念 1.1 长期持有的优势 优势: 充分利用复利 减少交易成本 避免情绪干扰 分享公司成长 1.2 复利的威力 原理: 利滚利 时间越长,威力越大 长期收益可观 案例: 10万元,年化12%,30年后174.5万 时间是最宝贵的资源 1.3 避免频繁交易 问题: 增加成本 情绪化…

作者头像 李华
网站建设 2026/8/25 7:20:25

LangFlow镜像实测:降低AI开发门槛的图形化LangChain工具

LangFlow镜像实测&#xff1a;降低AI开发门槛的图形化LangChain工具 在大模型技术席卷各行各业的今天&#xff0c;构建一个能调用语言模型、处理用户输入并联动外部系统的智能应用&#xff0c;似乎变得触手可及。然而现实是&#xff0c;即便有了强大的LLM和成熟的框架如LangCha…

作者头像 李华
网站建设 2026/8/27 8:42:19

PLC 与步进电机的运动控制编程设计

第一章 系统方案规划 本系统以 “精准定位、平稳调速、多轴协同” 为核心目标&#xff0c;采用 “PLC 步进驱动器” 架构&#xff0c;实现步进电机的位置控制、速度控制与多轴联动&#xff0c;适配机床进给、自动化装配线等场景。核心控制单元选用三菱 FX3U-48MT PLC&#xff…

作者头像 李华
网站建设 2026/8/26 23:00:01

电商客服效率提升300%的秘密武器(Open-AutoGLM自动回复技术深度解析)

第一章&#xff1a;电商客服效率提升的行业挑战在当前电商平台竞争日益激烈的背景下&#xff0c;客服作为连接用户与商家的核心枢纽&#xff0c;其响应速度和服务质量直接影响转化率与客户满意度。然而&#xff0c;多数企业仍面临客服人力成本高、响应延迟、重复问题处理繁琐等…

作者头像 李华
网站建设 2026/8/26 9:21:24

Open-AutoGLM实战指南(电商自动化报名全解析)

第一章&#xff1a;Open-AutoGLM实战指南&#xff08;电商自动化报名全解析&#xff09;在电商业务场景中&#xff0c;活动报名流程常涉及大量重复性操作&#xff0c;如商品信息提取、资质校验、表单填充与提交等。Open-AutoGLM 作为一款基于大语言模型的自动化工具&#xff0c…

作者头像 李华