记录一次线上的服务崩溃事故

4月23日,部门上线了一个大版本

这次版本是两年来发布的最大规模的升级,由1.0升级为2.0,升级动作很大

发版后不出意外的出现了各种服务崩溃,性能卡顿的问题

我所负责的服务里有一个数据同步的服务一直cpu满负荷运行,容器内存也是打满状态

查看java的gc统计发现老年代回收平均时间300秒

查看内存对象发现entity和dto对象有200万个一直驻留在内存

第一直觉是有内存泄露,

过代码发现果然对象中有几个map和list是用私有变量存储的,使用的是手动释放的方式回收内存,然而,由于集成方法有新老两个接口,老方法调用的地方没有手动释放,所以严重怀疑是这个地方造成了内存泄露

补丁发上去以后,观察了半个小时,内存和cpu又上去了

继续排查

查看java的运行线程,发现有二十几个业务线程一直驻留在一段sql解析的代码上

之前检查过这块代码

数据库中的这个表的记录条数总共只有几百条,返回结果不可能需要转换这么长时间

这个时候mysql监控的地方发现有几个慢sql,加载了十几万条数据

忽然恍然大悟,这里面的两个in字句,后面跟的列表长度超过了10万个,导致cpu会一直在这个地方解析sql,由于前面的请求超时,后面的调用会重试,所以出现了二十几个线程一直卡在这里,把cpu打满,同时每个线程的内存中都驻留了二十几万的对象不能释放

经过业务分析,第一个id判断完全可以去掉,第二个key判断可以通过去重把数量缩小到十几个,修改后上线,问题解决

暂无评论

发表评论