一次压缩引发堆外内存过高的教训

一、项目介绍

lz_rec_push_kafka_consume
该项目通过kafka与算法进行交互,通过push推荐平台(lz_rec_push_platform)预生成消息体。

二、问题背景

发现项目的k8s容器会出现重启现象,重启时间刚好是push扩量,每小时push数据量扩大5倍左右。
发生问题时,容器配置:CPU:4个,内存:堆内3G,堆外1G。

三、问题排查流程:望-闻-问-切

望:查看监控系统,观察重启发生时,容器实例的资源情况

图片1.png
注:容器重启机制:k8s监控发现“实例”内存使用超过申请时,会对容器进行重启。该动作是直接使用kill -9的,而非通过jvm指令对虚拟机进行重启,所以此处别想dump堆。
图片2.png
一开始怀疑是内存,但是内存不足的话,应该是出现oom的情况。所以先排除堆内内存不足的问题。将实例内存扩大至:6G,堆内5G,堆外1G。发现重启现象没有丝毫改善。

闻:检查项目的健康情况:线程、堆内内存使用、堆外内存使用。

  1. 通过jstack、jstat二连,查看项目线程情况及垃圾回收情况,无线程突增情况,无fullGC及频繁youngGC情况。

  2. 通过top命令发现res使用比jstat命令显示的堆大小大许多(忘了保留现场了),此时怀疑是堆外内存泄漏导致的。为了确定是堆外泄漏而非堆内,分析GC日志文件。

    • 借助easygc对GC日志进行分析:无fullGC情况(图中四次fullGC为手动触发测试的:jmap -histo:live ),且每次youngGC能正常回收对象。图片5.png图片6.png
  3. 修改启动脚本,将-Xmx参数和-Xms参数置为4G,且增加dump堆参数(-XX:+HeapDumpOnOutOfMemoryError  -XX:HeapDumpPath=/data/logs/  ),如果堆内发生oom则能拿到我们心心念念的堆文件进行分析。
    但是事与愿违,容器多次发生重启的时候,并没有发生项目堆内oom,也就是说,并没有dump下堆现场。此时更加确定,应该是堆外内存泄漏。

  4. 配置堆外参数:-XX:MaxDirectMemorySize 用

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值