一、项目介绍
lz_rec_push_kafka_consume
该项目通过kafka与算法进行交互,通过push推荐平台(lz_rec_push_platform)预生成消息体。
二、问题背景
发现项目的k8s容器会出现重启现象,重启时间刚好是push扩量,每小时push数据量扩大5倍左右。
发生问题时,容器配置:CPU:4个,内存:堆内3G,堆外1G。
三、问题排查流程:望-闻-问-切
望:查看监控系统,观察重启发生时,容器实例的资源情况
注:容器重启机制:k8s监控发现“实例”内存使用超过申请时,会对容器进行重启。该动作是直接使用kill -9的,而非通过jvm指令对虚拟机进行重启,所以此处别想dump堆。
一开始怀疑是内存,但是内存不足的话,应该是出现oom的情况。所以先排除堆内内存不足的问题。将实例内存扩大至:6G,堆内5G,堆外1G。发现重启现象没有丝毫改善。
闻:检查项目的健康情况:线程、堆内内存使用、堆外内存使用。
-
通过jstack、jstat二连,查看项目线程情况及垃圾回收情况,无线程突增情况,无fullGC及频繁youngGC情况。
-
通过top命令发现res使用比jstat命令显示的堆大小大许多(忘了保留现场了),此时怀疑是堆外内存泄漏导致的。为了确定是堆外泄漏而非堆内,分析GC日志文件。
- 借助easygc对GC日志进行分析:无fullGC情况(图中四次fullGC为手动触发测试的:jmap -histo:live ),且每次youngGC能正常回收对象。
- 借助easygc对GC日志进行分析:无fullGC情况(图中四次fullGC为手动触发测试的:jmap -histo:live ),且每次youngGC能正常回收对象。
-
修改启动脚本,将-Xmx参数和-Xms参数置为4G,且增加dump堆参数(-XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=/data/logs/ ),如果堆内发生oom则能拿到我们心心念念的堆文件进行分析。
但是事与愿违,容器多次发生重启的时候,并没有发生项目堆内oom,也就是说,并没有dump下堆现场。此时更加确定,应该是堆外内存泄漏。 -
配置堆外参数:-XX:MaxDirectMemorySize 用