针对之前出现过的full gc情况,这里给出排查的流成性建议,以后如果出现此类事件的时候,希望能够按照流程一步一步排查,防止手忙脚乱~(勿喷)

A. 为了第一手确定full gc情况,先立即申请某一台主机权限。如果自己有dump的权限的话,先快速进行dump日志来观察一下具体的情况。

B. 10-20分钟无法找到原因并解决问题的话,联系PE协助。full gc频繁的话往往是因为内存的问题,但是有时候也可能某些线程运行不当出现代码BUG导致,所以如果此时没有解决问题的话需要快速重启服务器,但是需要保留2台问题机器,以便继续跟踪问题。

C. 拿到jmap和jstack的dump信息之后按照以下流程进行排解: 1.针对jstack的日志,需要确认是否有正在执行循环的线程,因为循环过程往往容易出现过多的中间数据对象。 2.针对jmap日志,基本上只要看top的几个信息就行,如果top1和top2的大小差一个数量级的话,基本上top2就不用看了,直接关注最大的即可。在基本了解了内存的对象情况之后开发自行确认能否立即定位问题。

D. 如果此时依然无法定位问题,查看监控平台,从自己服务的provider和consumer信息中查看是否有异常的调用情况(平均RT突增,调用曲线跟发生full gc的时间曲线吻合,响应异常突增等。),如果此时发现了异常的调用,则跟进异常的接口信息,从代码逻辑分析其与jmap日志的内存情况是否有直接关联。如果能从这里基本定位业务代码,则立马与相关的业务方开发进行联系,确定以下具体的影响面,如果影响不大的话考虑里面在SOA上先把服务禁掉,以保证自身服务的可用性,然后在降低影响的情况下自己再另行修改。如果影响比较大的话,则需要立马快速修改代码,并在修改点做好开关,防止修改引起的BUG,然后立马通知主管,联系PE上线发布。

E. 如果通过步骤C依然无法定位问题,则需要在D进行的同时并发执行另外一个操作,通过Eclipse Ememory Analyer查看更加详细的运行信息,然后结合D中分析到的内容进行问题排查。

F. 基本上到这里问题都能找到,然后优化后续的操作是必经的逻辑。最后容易遗漏的一点是,检查现在的JVM参数是否可以优化,因为JVM参数往往关系着full gc 的频率问题,如果参数合理的话可以有效的减少一些STW引起的停顿时间,所以这一步还是有必要进行的。

基本上在出现线上问题的时候容易慌乱,对于jvm的一些命令页容易生疏,网页上查找的各式各样的命令容易眼花缭乱,这里就总结一下在以上过程中可能用到的命令情况:

  • 查看内存中占用量前10的对象情况: jmap -histo:live pid | head -n 10
  • 生成堆内的dump文件:jmap -dump:live,format=b,file=/tmp/dump.hprof pid 如果dump文件过大不利用传输的话需要进行压缩,压缩命令:tar czvf /tmp/dump.tar /tmp/dump.hprof 解压命令:tar zxvf /tmp/dump.tar
  • 查看线程日志:jstack pid | grep -i "Deadlock" --color=auto 着重查看是否有死锁线程或者Waiting on condition(等待唤醒)或者Blocked(阻塞)或者Waiting on monitor entry(等待获取锁)线程。
  • 如果对于监控平台监控的细节比较模糊,可以使用jstat 命令监控详细的内存各个区域情况,下面给出参考性脚本(见下):
  • 在从远程服务器往本地拷贝文件的时候需要使用scp命令: scp username@remoteIp:/tmp/dump.hprof /temp/dump.hprof