生产问题(十二)GC垃圾回收导致空指针

一、引言

        最近线上出现由于线程池任务执行超时导致的空指针,按道理说基本不会很多执行超时的,看了看监控,那个时间点发生了gc,gc时间超过5s。

        说明这次是gc垃圾回收导致的问题,实际上需要排查解决的是垃圾回收问题。表象总是和实际的原因差距很大。

7ac954103e0a40f6a7d0ac8d775de19e.png

二、环境

        操作系统、容器环境没什么好说的,主要是GC相关的

        jvm参数:

-Xmx12288m -Xms12288m -Xss256k -XX:MetaspaceSize=128m -XX:MaxMetaspaceSize=256m -XX:MaxGCPauseMillis=200 -XX:+UseG1GC -XX:-OmitStackTraceInFastThrow -XX:MinHeapFreeRatio=30 -XX:MaxHeapFreeRatio=50 -Djava.util.concurrent.ForkJoinPool.common.parallelism=4 -XX:CICompilerCount=3 -XX:MetaspaceSize=256m -XX:MaxMetaspaceSize=512m  -XX:ActiveProcessorCount=4 -XX:+PreserveFramePointer -XX:+PrintGC -XX:+PrintGCDetails -XX:+PrintGCDateStamps -XX:+UseGCLogFileRotation -XX:NumberOfGCLogFiles=5 -XX:GCLogFileSize=32M -XX:+HeapDumpOnOutOfMemoryError 

        gc收集器是g1

        最大堆大小:12288.00 MB

        最大非堆大小:1256.00 MB

        g1是整堆收集,收集他定义的region策略。所以监控上所有的gc时间都给到了young gc,达到5s,是让同事很疑惑的。其实监控显示的不太对,属于汇总时间。

b24045f16d434e5a94d3c53d4ab5cd82.png

三、分析-TCP丢包

        这个方向实际对不上这个问题,只是有一些特征显示有这种可能,后面被其他机器的现象排除了。

        但是这个猜测方向有没有必要呢,当然是有的。发现问题去排查解决本来就是根据原理先提出一些方向,对这些方向进行论证,排除错误的方向,留下可能的方向再去找依据支持这个论点,再通过实验解决问题。

        即使一个方向对不上这次的问题,只要他的理论没有问题,他就可能在下一次映射在其他的问题上。老话说的好:大胆猜测,小心求证。

1、丢包监控

        作者为什么会产生丢包影响gc的猜测呢?因为在监控上显示在对应的时间点发生了tcp丢包重传的问题,监控拉长之后这个突峰也是非常明显。

        但是这个现象为什么会联系到gc延长的问题呢?作者是这样思考的:TCP丢包重传默认上1s,如果是本来很快结束的请求因为重传而迟迟不结束,那么这个处理任务相关的所有对象都不能释放,不能被gc回收。      

        这也是之前作者的经验,丢包导致了请求延长,有兴趣的同学可以看看之前发生的问题

生产问题(五)TCP丢包排查_tcp connection lost怎么排查-CSDN博客

生产问题(五)TCP丢包解决_tcp丢包的解决方案-CSDN博客

95bac654e26145b79580538bcf320b2f.png

2、TCP参数

        有了猜测就看看当前的设置是不是这样,说不定重传设置的很低呢,在机器上输入

sysctl -a

        查看一下重传的retrans参数,的确是1s

c3c967810a1b42449f241397d317a162.png

3、其他机器

        接下来需要确认其他机器,是不是所有的发生这种gc延长的机器和对应的时间都有丢包重传的现象。

        很明显,作者发现其他机器或者其他时间点都没有,那就不是这个原因。也幸好有多个机器、多个时间点,不然这个可能性不能排查,也就需要更多的验证。

四、分析-GC日志

        工具还是挺全的,在机器发布的时候就会生成一份GC日志,后续不断写入,所以可以看到当时发生了什么。

        基本上每一个对应的机器和时间点都看到了Evacuation Failure,在region复制转移的时候,对象分配失败了,to-space exhausted也是一个比较明显的特征

67fdb8be43274c2b8da674e027b18018.png

五、分析-GC调优 

1、G1ReservePercent

        G1ReservePercent没有设置,那就是默认的10%预留空间给存活对象转移,这个比例是相对于整堆的,那么预留空间就有1.2g左右,这个看起来也是满了,因为Heap: 12115.1M(12288.0M)->10604.0M(12288.0M)。

        那么要不要调大G1ReservePercent呢,作者感觉是不需要的,1.2g不少了,这样还不行,再调大也没什么用处。比例应该没什么问题。

2、G1HeapRegionSize

         G1HeapRegionSize没有设置,通常情况下,G1 会将堆内存划分为 2048 个 Region,我们堆内存的大小为 12G ,那么每个 Region 的大小为 6MB左右。那么超过1/2Region大小的都会作为大对象准备放入Humongous区域,对象的大小为Region的几倍,会使用多个连续的Humongous区域来存储这个大对象。

        再结合当前的处理任务会产生大对象,每个大对象都会达到几十M,如果是region里面分配不下,然后需要整合几个Humongous存放,为了能找到连续的H区,有时候不得不启动Full GC,那么就比较符合这个现象了。

       这样看来就可以调整G1HeapRegionSize,把region放大,免得这些大对象放不下,需要整合多个Humongous。

六、总结

        这一次的问题涉及到网络、jvm、gc多方面的知识,需要经过多种原理剖析论证,锁定了方向之后就需要实验了,作者后续会把实验结果同步。

        发现问题去排查解决本来就是根据原理先提出一些方向,对这些方向进行论证,排除错误的方向,留下可能的方向再去找依据支持这个论点,再通过实验解决问题。

        即使一个方向对不上这次的问题,只要他的理论没有问题,他就可能在下一次映射在其他的问题上。老话说的好:大胆猜测,小心求证。有了解的同学也可以谈谈自己的想法,给我们多一些验证方向。

 

  • 31
    点赞
  • 26
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

胖当当技术

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值