问题描述:
废话不多说,直接上一段异常日志:
The last packet successfully received from the server was 30,135,680 milliseconds ago. The last packet sent successfully to the server was 30,135,690 milliseconds ago. is longer than the server configured value of 'wait_timeout'. You should consider either expiring and/or testing connection validity before use in your application, increasing the server configured values for client timeouts, or using the Connector/J connection property 'autoReconnect=true' to avoid this problem.
通过字面意思知道,当前请求超过所建立的连接已超时,超的是mysql 默认的wait_timeout,也就是28800s=8h;
原因分析:
似乎异常给出的原因和解决方法都很明确,increasing the server configured values for client timeouts, or using the Connector/J connection property 'autoReconnect=true' to avoid this problem. 但是线上环境真的能这么干吗?
如果说你把wait_timeout设置的无限大,那到了那个时间不一样会出问题,况且wait_timeout有个最大限制,肯定不能这么干,但是为了还原问题,我可以在mysql的my.ini文件中添加或者修改
wait_timeout=300
interactive_timeout=300
也就是把 wait_timeout 设置成五分钟,因为我就算找到一个解决方法也不可能等八小时再去测试吧,注意这里只设置wait_timeout无效。随后问题就在本地被还原了。
解决方案:
我这里用的是dbcp,项目从一开始便进行了以下配置(#后是注释说明):
#设置最大连接数和老的参数maxActive一致: tomcat-jdbc是maxActive dbcp 则改成 maxTotal
#值为-1表示不限制 ,官方默认为8
maxTotal=500
#获取连接的最长等待时间,单位是毫秒,不宜过大,当连接池满了以后,等待太长只能导致用户页面无法展现,5-30秒合适
maxWaitMillis=10000
#设置某个数据库连接闲置的秒数;removeAbandonedTimeout指定的时间还未归还的连
#建议为5分钟左右
removeAbandonedTimeout=300
#对于被占用的连接,进行检查,当超过removeAbandonedTimeout指定的时间还未归还的连接,则抛弃,并打印日志,
removeAbandoned=true
removeAbandonedOnBorrow=true
#连接空闲时候对空闲连接定期检查,无效的连接被剔除,保证连接的有效性,单位是毫秒
#建议5-30秒定期检查
timeBetweenEvictionRunsMillis=10000
所以应该不会再出现超时的问题,这里给人的感觉像是配置没有生效,然后就沿着这个思路继续找问题,经过一番思索,发现项目引入的是
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-dbcp2</artifactId>
<version>2.1.1</version>
</dependency>
而我的配置文件中是 maxTotal、maxWaitMillis、maxWaitMillis等一系列参数,我晕,原来全是dbcp2的参数名
果然,替换pom引用后,问题得以解决,这这里对dbcp2和dbcp几个参数做一下记录:
dbcp:
maxIdle,最大空闲数,数据库连接的最大空闲时间。超过空闲时间,数据库连接将被标记为不可用,然后被释放。设为0表示无限制。
MaxActive,连接池的最大数据库连接数。设为0表示无限制。
maxWait ,最大建立连接等待时间。如果超过此时间将接到异常。设为-1表示无限制。
dbcp 2:maxTotal,maxWaitMillis,lifo,maxConnLifetimeMillis。