【踩坑记录】服务频繁重启问题排查

一、背景

在进行本地测试时,发现调用某个服务时会偶现调用失败的问题,报错信息如下:
image.png
从图中可知,是从注册中心未找到服务导致。一开始以为是有人在重新部署,后面发现这个问题出现的有些频繁,于是开始排查发布记录,发现近期并未有人重启服务,但是容器的重启次数高达 1521 次
【踩坑记录】服务频繁重启问题排查_第1张图片
【踩坑记录】服务频繁重启问题排查_第2张图片

二、问题跟进

首先想到两种原因:

  • 容器网络出现问题,导致健康检查失败,被 k8s 重新拉起
  • 容器因为某些原因挂掉了,导致无法响应请求(盲猜是 OOM 了)

第一种经过运维排查后排除。于是开始排查第二种情况,从监控上看到了 GC 回收时间高达 30s
【踩坑记录】服务频繁重启问题排查_第3张图片

由于是个老服务,且里面逻辑众多,又没有自动生成 dump 文件的配置,无法完全肯定是 oom 导致。于是修改了项目配置,将 Xms 和 Xmx 参数从 512m 修改为了 1024m,并添加上 oom 后自动 dump 的配置,重新发布了服务。

约半小时左右,服务又又又又重启了,这次捞到了对应的 dump 文件,开始进行分析。

三、问题分析

打开 jvisualvm ,将 dump 文件导入,看到了如下提示:
【踩坑记录】服务频繁重启问题排查_第4张图片
继续跟进,查看这个线程的状态,找到了对应的方法:
image.png
这是个简单的查询,根据 AgencyId 和 OrderId 进行查询,按照 id 进行倒序,然后在数据库中查询了下,发现由于没有创建索引,导致查询很慢。。。。
image.png
看似找到了问题,但有个疑问仍没有解决,一个慢 sql 是怎么导致整个服务 OOM 的?。。于是开始继续深挖代码。
【踩坑记录】服务频繁重启问题排查_第5张图片

四、问题解决

最终排查了下代码,找到了最终的原因:

  • 这个查询语句属于一个订单查询的定时任务,里面逻辑比较复杂,且这个任务每隔 2 分钟会执行一次
  • 由于是个老服务,之前的定时任务是 http 请求触发,每次执行之前不会判断上一次是否执行完成。。
  • 有个慢 sql (单次执行 18s 左右,定时任务中会循环执行这个 sql 查询数据),导致每次定时任务执行时间很长,约 190s 左右

image.png

综合以上特性,已经大致猜到了问题产生的原因:

由于慢 sql 导致执行一次定时任务耗时较长,然后每隔 2 分钟会重新触发一次定时任务,导致多个定时任务逻辑同时执行,由于内部逻辑复杂,最终导致内存耗尽,服务宕机,然后被 k8s 重启,循环往复。。。

dump 文件的内容,也证实了这个猜测,确定存在多个线程在执行这个定时任务,OOM 时总共有 12 个线程正在执行。。
【踩坑记录】服务频繁重启问题排查_第6张图片

解决办法也很简单粗暴,增加表索引,缩短每次定时任务的执行时间,避免出现多个线程同时执行定时任务撑爆内存。

别问为什么不优化代码。。老服务,改不动啊改不动。。。
【踩坑记录】服务频繁重启问题排查_第7张图片

你可能感兴趣的:(javajvm)