相信这个错误小伙伴们经常碰到,有得时候也没有去在意它,重启大法即可解决,但是在线上经常出现这个问题是一件很头痛的问题。
问题分析
这个报错从字面看是由于通信链路故障,告诉最后发送和接收数据包的时间,经排查是服务器端主动关闭连接,而连接池无法感知导致使用了实效的连接导致
主动关闭连接无非有两个原因
- 网络不稳定
- 防火墙主动关闭(这个很多服务喜欢配置5分钟内没有数据流动就自动关闭)
我碰到的场景就属于第二种,很坑
我的原始配置(只列出关键配置):
//初始连接数
initialSize:10
//连接池中可同时连接的最大的连接数,一些版本maxActive配置选项已重命名为maxTotal
maxActive: 100
//最小连接池数量, maxIdle已不再使用,配置了也没效果
minIdle:10
//最大等待毫秒数, 单位为 ms, 超过时间会出错误信息
maxWait:60000
//建议配置为true,不影响性能,并且保证安全性。申请连接的时候检测,如果空闲时间大于timeBetweenEvictionRunsMillis,执行validationQuery检测连接是否有效。
testWhileIdle:true
//在连接池返回连接给调用者前用来对连接进行验证的查询 SQL,要求为一条查询语句
validationQuery:select 1
//SQL 查询验证超时时间(秒),小于或等于 0 的数值表示禁用
validationQueryTimeout:30
解决方案
增加两个关键配置:
//连接池中连接可空闲的时间,单位为毫秒 针对连接池中的连接对象
minEvictableIdleTimeMillis:600000
//每timeBetweenEvictionRunsMillis毫秒检查一次连接池中空闲的连接,把空闲时间超过minEvictableIdleTimeMillis毫秒的连接断开,直到连接池中的连接数到minIdle为止
timeBetweenEvictionRunsMillis:60000
我新增这两个配置的含义是:
- 第一个配置是在minIdle:10中,每隔5分钟断开重新创建连接,保证都是未失效的连接
- 第二个每隔1分钟检查一次连接池中空闲的连接,把空闲时间超过5分钟的连接断开,直到连接池中的连接数到minIdle:10为止。
我这里的配置刚好配置的是5分钟(单位是:ms)
minEvictableIdleTimeMillis:600000
,也就是防火墙断开未使用连接频率.
其实还有一种配置timeBetweenEvictionRunsMillis:60000+minIdle:0
,对使用并发不高的应用可以这么配置,毕竟开启和关闭连接频率也不高