线上OutOfMemory问题,线上宕机问题处理

线上OutOfMemory问题,线上宕机问题处理

抛出问题?

有没有遇到过程序启动后就宕机的情况?

有没有遇到过程序被请求几次后CPU飙升,内存震荡严重的,接口数据响应超级慢然后紧接着502 Bad Gateway?

解决问题

线上问题排查常用命令?

1
2
3
4
5
1. jps 显示java进程,PS: Docker容器部署通过这个命令看是不准确的,最好可以通过启动日志查看服务状态。
2. jinfo -flags pid 显示java进程参数配置。
3. jstack pid 检查线程栈的使用情况,该命令处理死锁的时候需要使用。
4. jstat -gc pid time times 查看系统垃圾收集情况,系统卡顿、系统慢的时候可以使用这个命令检查是否发生了STW。多数是STW引起的。
5. jmap -heap pid 查看系统堆使用详情,这个命令不建议使用。因为CMS收集器在遇到该命令的时候会导致进程挂起,建议配置OOMPath打印oom日志。

排查过程

配置最大堆内存大小,设置oom日志;

  1. 观察启动后系统资源占用情况,如下图:
    初始资源使用情况
    可见并无异常。
  1. 请求接口打印GC回收情况如下图:
    GC回收

可见FullGC回收频繁,这是导致系统卡顿的主要原因。观察内存震荡验证,如下图;代码原因,要么系统中处理了大量数据、要么系统中存在无法回收的资源,怎么确认?
等一会看下会不会资源回收,如果回收了就不是有不能回收的资源。过了一个观察内存回落如下图:
程序被我刷的卡死几次,为了截图我也不敢刷太厉害。凑合着看吧。
资源回收情况

  1. 狂刷接口指导产生OOM,查看Dump文件如下图:
    已产生dump文件:
    Dump文件

dump文件概览:
Dump概览

堆文件:
堆文件

  1. 分析OOM查看资源占用排名,优化高资源占用逻辑。
    4.1 修改JSON转换逻辑,因为JSON转换中使用了大量的HashMap;
    4.2 修改参数传递,因为参数大小影响循环线程栈的深度;
    4.3 调整BigDecimal精度处理逻辑。

  2. 再次运行观察资源占用,问题解决。如下图:
    实现

  3. 是否可以进一步优化?
    新生代回收频繁,内存震荡严重?
    加大新生代内存、设置最大最小内存减少震荡?
    是否会导致增加GC回收时间?
    是不是因为有临时的大对象?
    分页减少临时的大数据量?
    调整新生代到老年代的晋升年龄?
    是否有大量的老年代数据?
    增加老年代内存?
    是否会引起更长的STW?

  4. 到底怎么弄?
    根据实际服务情况调整。