2020-11-18记录FullGC排查过程

  1. 系统突然发生宕机,由于前期已经发现系统卡顿现象,因此将GC日志打开了,登录服务器查看日志,top指令发现CPU占用100,java进程内存占用4.7G,疯狂打印FullGC日志;
  2. top -Hp pid查看,发现是垃圾回收的线程vmthread占用的,当然这过程需要十进制向十六进制转换pid,同时jstack查看线程信息;
  3. jmap导出dump文件,由于文件较大,且当前服务器下载速率较低,因此使用scp复制到190服务器,然后用winSCP下载到本地;
  4. 接着使用jvisualVM打开堆dump文件;
  5. 发现char[]占了3个G,同时POI的对象排在第二和第三;
  6. 通过分析字符串数组,发现大部分来自于session,同时查看session对象,系统中存在1w多的session对象;
  7. 存在着这么多的session对象的原因是,系统没有设置session有效期,并且web项目,用户都是直接关闭浏览器,不会点击注销的方式退出系统,因此服务器没有清理无用的session;
  8. 接着说第二个问题,由于服务器是集群,当其中一个发生宕机以后,迅速将问题服务器踢出nginx,用于问题排查,问题服务器经过一下午的FullGC以后,抛出OOM,然后恢复正常;
  9. 其实当然,此时的可用堆内存已经很小了,及时继续使用,也会很快继续FullGC,OOM打印的异常信息日志和POI有关,因此查看此处功能代码,数据导出有开始和结束日期,我怀疑有用户没有选择日期;
  10. 经过查看用户操作日志,果然有的用户没有选择日期,并且还点击了2次,这就是发生此问题的导火索;
  11. 解决办法,session设置有效期为1天,同时数据导出增加期限选择校验,并且最长6个月的流水导出,避免10多万条数据的全部导出,占用系统过多内存,而且用户肯定是忘记或者无意识,并不是要导出全部的流水;
  12. 对于字符串数组过多,其实问题很难排查,因为使用的地方太多了,但是dump中可以查看引用信息,也支持OQL(虽然我并没有用的上,而且也不太熟),因此基本满足问题的排查;
  13. 另外自己的思考心得就是,dump显示的占用内存大小,应该仅仅指的对象本身所对应的内存大小,并不是连对象内部的引用的对象大小也算上,所以这就是为什么问题不好排查的原因;
  14. 文章仅用于记录此次排查过程,不是技术分享,因此没有把技术点写的很详细,如果有遇到类似问题的小伙伴,需要帮助的话,可以评论联系,我会尽可能提供帮助的;

猜你喜欢

转载自blog.csdn.net/weixin_44182586/article/details/109787989