Kubernetes-POD生成 java dump文件
背景
在今天的线上业务中,某服务频繁重启。经过排查日志和事件信息,确认是由于 OOM(Out of Memory)导致服务重启。为了方便研发团队定位 OOM 的具体原因,我们决定在 OOM 发生时自动生成内存快照(heap dump),供后续分析使用。
关于 OOM 的详细介绍,可以参考这篇博客:https://www.cnblogs.com/klvchen/articles/12448436.html
JVM 提供了一些参数,能在发生 OOM 时自动生成 heap dump:
-XX:+HeapDumpOnOutOfMemoryError
-XX:HeapDumpPath=/logs/heapdump.hprof
然而,目前还存在两个问题:
- 多次重启可能导致 heap dump 覆盖。例如,如果程序发生了两次 OOM,第二次生成的 heap dump 会覆盖第一次的。
- 这个参数仅适用于 JVM 内部的 OOM,而 K8s 主动重启服务时并不能生成 heap dump。我们通过
kubectl describe pod
查看重启原因,发现是因为健康检查未响应,K8s 自动重启服务。这类情况并非 JVM 的 OOM,因此上述参数无法帮助生成内存快照。
为了解决 K8s 重启时无法导出 heap dump 的问题,我们可以通过配置 preStop
钩子,在容器停止前生成内存快照。相关命令如下:
- 获取进程 ID 为 10 的程序的堆栈信息:
jstack -F 10 >> /logs/thread.dump
- 生成堆内存快照:
jmap -dump:format=b,file=/usr/src/logs/dump.hprof 10
通过这样的优化,既能避免 heap dump 被覆盖,又能在 K8s 重启时生成有用的内存快照,帮助排查问题。
配置钩子函数
在command增加
jstack -F $(jps |grep -v Jps | awk '{print $1}') | tee -a /usr/src/logs/thread.dump && jmap -dump:format=b,file=/usr/src/logs/$(date +'%Y-%m-%d_%H%M%S').hprof $(jps |grep -v Jps | awk '{print $1}')"
lifecycle:
preStop:
exec:
command: ["/bin/sh", "-c", "curl -X PUT \"http://eureka-service:8761/eureka/apps/${POD_NAME}/${POD_IP}:pi6000-mdl-web:8080/status?value=DOWN\" && sleep 30 && jstack -F $(jps |grep -v Jps | awk '{print $1}') | tee -a /usr/src/logs/thread.dump && jmap -dump:format=b,file=/usr/src/logs/$(date +'%Y-%m-%d_%H%M%S').hprof $(jps |grep -v Jps | awk '{print $1}')"]
验证
手动执行 kubectl delete pod,可以查看到生成的文件了
本文来自博客园,作者:&UnstopPable,转载请注明原文链接:https://www.cnblogs.com/Unstoppable9527/p/18422492
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· 阿里巴巴 QwQ-32B真的超越了 DeepSeek R-1吗?
· 如何调用 DeepSeek 的自然语言处理 API 接口并集成到在线客服系统
· 【译】Visual Studio 中新的强大生产力特性
· 2025年我用 Compose 写了一个 Todo App