一次线上事故的处理流程和总结

一、事故问题:html

某个旧版本业务功能中运行了一个失败重试的job,因一位离职的同事编码时未考虑周全出现死循环,致使线上从24日下午2点一直到27日晚9点持续3天一直在刷日志。异常日志内容以下:redis

 

二、事故过程分析:缓存

    ①、根据异常日志内容,初步考虑为redis中缓存的token失效了,后检查token并与请求方token对比,发现token正确,故排除token过时缘由安全

    ②、经过grep命令查找更多日志内容后,依然没法显示更多有用信息(包括调用入口,更多代码中打印的日志信息等),因而核查全部可能的代码入口,并依次打印相关日志,结果均未打印有效信息。架构

    ③、考虑以前该服务已经接入公司自研的日志链调用分析系统,前后根据日志关键内容和traceid在系统中查询,结果发现traceId的调用链没法正常显示,依旧没法找到异常日志准确的入口,后找到故障缘由后,架构组同事猜想多是由于该调用链一直未调用结束,致使没法经过traceId来查找调用链。编码

    ④、因为持续重复调用同一个接口,开始觉得是安全问题怀疑被人刷接口(前段时间公司有进行安全验证),后看到全部日志内容均是由同一个线程所打印的,所以怀疑多是有死循环存在。后与同事确认,了解到旧版某个业务中有一个失败订单重试job,目前已经弃用了,理论上应该不存在问题,而后又找到该job的入口,使用grep命令查看第一行日志,发现仍未打印日志,因而排除了该job的入口。后来发现被迷惑了,由于该job是在7.24下午2点开始的,由于死循环该方法一直没调用完,因此到27号查找该日志内容时依然未打印。spa

        

⑤、后使用jstack命令经过线程名称最终查找到异常代码入口,肯定事故缘由是因为旧版业务的job致使,线程

         

        该job的部分代码以下:日志

          

  能够看到,最外层的for循环的终止条件只能依赖于xxList变量,而且token是在循环外层定义的(这也解释了为什么日志一直显示token校验失败了,由于token是24号的,正常状况token为1小时更新一次),而在job执行过程当中,token过时了,所以后面的query方法返   回的code一直不为0,因而进入死循环,致使一直刷日志。code

三、事故解决:

     找到问题后,重启了1台服务后观察一段时间,发现日志恢复正常,因而重启剩余2台机器,并在es-job中将该job禁用。

四、事故影响分析:

    因为只是打印日志,且日志量不大,未对平台核心相关服务产生明显影响,但因为重复请求服务方,致使对方机器磁盘爆满后发现了该问题。

五、事故总结:

    ①、使用for循环时,必须确保循环终止条件能达到,避免产生死循环。

    ②、良好的日志能有效提高问题定位的效率,有关日志打印规范,请参考阿里巴巴日志规约(http://www.cnblogs.com/dragonsuc/p/6937584.html

    ③、对于已经弃用的业务和功能,注意一些旧的job可能产生的影响,若有必要须要中止。

    ④、尽可能经过多角度快速定位问题,好比重复日志就要考虑是否有死循环,熟练使用jstack等命令快来速定位代码。

若有其余建议和意见,欢迎指出批评。

相关文章
相关标签/搜索