前段时间部署的线上服务器出现的问题简单描述
PS:因为这是解决后隔了一个星期才有时间写的,所以全文靠描述。
一、问题
问题是在程序在线上跑了一段时间之后出现的问题,每隔多久以后程序就莫名奇妙的崩掉了,也不算崩,就是进入了一种假死状态。
对所有的请求没有反应,也没有日志输出之类的,使用ps查看程序进程的时候显示的是程序还在运行。
最开始的时候没有完这方面想,一直以为是那个地方的配置没配好,所以造成的假死。
二、排查MySql
最开始排查的是MySQL,因为发现程序没反应是和数据库的连接断掉了有关系,所以就查了一下MySQL的日志。
然后发现MySQL日志里面提示写的是数据库连接什么什么,断开连接
以为是数据库配置问题,然后开始排查,检查 my.cnf 的配置,感觉没啥问题,自动连接也配置了,所以就在程序里找来着。还是会跑跑就假死,然后再MySQL的url配置里加了 autoReconnect=true 参数,好多了,多跑了几个小时,之后还是会假死,只能把程序重启,重启之后就好了。
所以基本上可以确定应该不是MySQL的问题
三、检查JVM
开启程序的日志和MySQL的日志,然后进行排查,整个过程就是盯着程序,然后发现程序的堆爆了。
可能引起的原因是jvm的gc机制引起的,然后在网上查找相关方法进行了排查和解决,重新设置了一下运行时候的参数。
也有效果,程序跑的时间延长了,但是一段时间后还是会进入假死。
这个时候看日志,发现了一个问题,jvm的gc在回收的时候进行了报错,原因是处理数据过大导致的。
但是没有给出具体位置,不过程序也报错了,报错的位置是一个定时任务,错误信息是mysql数据连接中断。
由此确定了错误的位置。
四、造成假死的核心原因
这个定时任务写的时候逻辑上有一些问题,所以造成了没两个小时他会添加一千多条数据,数据经过不断的累计涨到了五十多万条数据,然后在定时任务中查询的时候会将这个表中的五十多玩条数据全部查出来,造成了堆的溢出。
因为对象的创建会在堆中分配空间,而五十多万条数据太多了,造成了堆的溢出。
之后jvm的gc机制在定时任务时因为堆中的数据太多,去进行了垃圾回收,但是回收不了。
MySQL由于使用堆来管理连接和相关数据结构,当堆溢出发生时,它可能会覆盖到MySQL连接对象。
PS: MySQL这里是个人猜测,但是应该是正确的,但是我不知道怎么验证,如果有大佬有方法验证,希望能留言教一下。万分感谢