你看见的日志中的异常信息真的是引发系统崩溃的原因吗?
实际案例:xxxx项目中,我们有一个向调用方提供日活千万级的接口。在项目运行的过程中按半个月周期性的出现过一些异常信息。
这个异常的信息表明redis连接超时了,当时我看到这个异常,以为是redis连接池设置小了或者是redis超时设置小了。我当时得出的可能结论是:
于是我更改了redis连接池的配置,不限定连接池的大小,同时将连接超时时间设置为30s。
可是一个周期过去了,该出现的问题还是出现了。因为错误量太大,上万的redis错误异常湮灭了真正的异常信息,只找到了java heap的异常,所以我猜测是可能是哪里出现了内存泄漏,将内存占用满了,但是在64为的jdk中,如果不是为现在应用程序使用的资源,java应用程序理论上不需要为了增加可使用的内存而去设置jvm的启动参数。这次周期没有发现什么有价值的异常,只知道内存泄漏导致gc异常,从而导致redis连接池获取不到资源,造成redis出现command timeout的异常。后来我在审计日志的时候发现,曾经出现过
这个异常,印证了内存泄漏的观点。后来又发现了由于内存不足导致的连接被挂起的异常等等,在证实了内存泄漏的问题之后,我开始审计代码,发现代码中之前为了留调用证据,给每次调用都记录了日志,后来又因为调用量太大,避免让数据库存按月以亿级增长的没啥意义的调用日志,就将存日志部分代码注释了,但是将日志信息放入队列的操作并没有注释掉,导致该队列无限增长,从而引起了内存泄漏。解决完这个之后,重新发布,问题没有再出现过。
这个案例中,系统首先出现的Bug是redis连接池抛出的异常,不能一头扎入某单个异常中,需要分析可能引起该异常的原因。找到能够合理解释的最终异常。