一次服务器事故处理过程及教训

java虚拟机内存查看相关命令: http://donald-draper.iteye.com/blog/2358771
Linux系统和用户线程数进程数限制查询: http://donald-draper.iteye.com/blog/2358761
Oracle性能查看: http://donald-draper.iteye.com/blog/2358935

项目简介:主要是定时任务增量更新数据,定时任务每天跑一次,任务是中有一个线程池,管理着3个增量更新线程,1个全量更新线程;
事发及处理过程:
   2017年02月23号,项目经理一声令下,哥屁颠屁颠地,跑了过去,服务器出问题了,日志从2017年01月27号之后,断了;这是怎么回事?让我去看看;哥的心,那忐忑的,七上八下;
到机房,看日志,日志到27号断了,用任务调试接口测试了一下发现定任务正常,有日志产生,哥就疑问了,那定时任务为什么不跑了呢?并且线程池中3个增量更新线程只有一个跑完,全量更新线程跑完,其他2个增量更新线程没跑完,很是疑问,线程池的问题吗?重启tomcat,调试任务,仍是上面的问题?(线程池中3个增量更新线程只有一个跑完,全量更新线程跑完,其他2个增量更新线程没跑完)
   查看的线程池的源码,看起来不太可能是线程池出问题;那是什么情况?
   再看日志发现1月18号之前,线程池中的4个线程全部跑完,但1月18号,日志显示有大量的数据更新,增量更新线程1跑完,增量线程2,跑了一部分,出现fush statement SQL异常;再查看18号以后的日志发现,增量更新线程1跑完,2,3没跑完,全量更新线程跑完;一直到27号,这又是什么原因呢?郁闷中,查看tomcat的Catalina日志发现18号发生out of memery 异常;堆空间不够用了,还是不能解决为什么定时任务跑到27号,就没了呢?
jmap -heap pid :查看堆内存,没问题够用,再调度任务,从日志来看老问题;
jmap -histo:live pid: 查看对象大小,没问题;
jstat -gcutil pid : 查看jvm的gc情况和内存使用情况,没问题;
jstack pid :查看jvm线程运行状态,是否有死锁现象等等信息,
看到定时任务调度器有10个线程,3个在跑,7个在等待;线程池中有两个在跑,状态为
从数据库Socket读取数据,没看明白真没回事;
    23号晚上,睡觉的时候,突然来了灵感,1月18,1月27,10个调度线程;
为什么1月27调度任务不跑呢?
    18号,堆内存异常,增量更新线程有一个执行完,一个执行更新中,另一状态不太清除;
27号定时任务不跑了,对了27-18+1=10;由于有2个增量更新线程一直没跑完,意味着有一个任务线程再跑,正好跑了10天,10个任务线程用完;
    那又为什么还有2个增量线程没跑完呢?jstack查看线程运行状态,发现处于运行状态,Socket从数据库读取数据;难道是数据库性能问题,读写太慢,查看数据库性能,果然,重启了一下数据库;一切正常。

教训:
当服务器出问题时,首先保护现场,查看虚拟机状态(内存,GC,线程),分析发生时间点,前后日志的不同,即时间点日志。

猜你喜欢

转载自donald-draper.iteye.com/blog/2358990