一行日志引发的生产事故
事故现象
发版后整个系统不可用,错误日志:Could not get JDBC Connection。
定位问题
-
根据错误日志首先想到的就是查看连接池信息,发现服务启动后,进行一些正常的业务流程操作, 连接池中的可用连接马上被用完,之后就出现了无法获取连接的错误日志了。
-
一边操作一边查看连接数,发现每次执行某个动作的时候,连接数就会+1,定位到问题可能出现的具体接口。
-
通过git查看当前版本修改的内容,发现相比上个版本多打了一行debug级别的日志。
log.debug(JSON.toJSONString(dataSource));
原因
fastjson的toJSONString方法会调用对象中的Getter来获取对象的filed和value。 由于日志打印了dataSource,所以每打印一次就会调用一次getConnection方法,进而导致数据库连接耗尽。
总结
- 不要轻易将一个不熟悉(了如指掌)的对象传入JSON.toJSONString()。
- 即使是熟悉的类也尽量不要用JSON.toJSONString()来转成字符串,因为你不知道你的同事会在这个类里面写什么方法, 除非目标就是转成json字符串。
- 尽量通过重写toString()来将对象转换成字符串,最原始的方法就是最简单的方法,最简单的方法就是安全的方法。