问题
一个监控项目切换到mycat后,运行几天后系统直接异常报错,查看日志发现tomcat连接池耗尽了,Timeout: Pool empty. Unable to fetch a connection in 30 seconds, none available[size:100; busy:100; idle:0; lastwait:30000]
第一次出现这个异常时重启了系统,暂时恢复到了正常状态,过了三天有出现了相同问题,推测是tomcat数据库连接池配置问题,配置文件里参考以下配置增加了配置参数:
*上看是说spring-boot的1.4.1版本有一个更改,本来是spring.datasource.max-active=200的,现在得要根据具体情况来调整,比如用Tomact就是spring.datasource.tomcat.max-active=200。只不过我是1.4.3版本,我以为是向上兼容,没想到居然是向下兼容,改为不带Tomcat的就可以了,加上又看了一下连接池的配置,最终连接池的配置版本为
#连接池最大连接数
spring.datasource.max-active=200
#空闲池中最大连接数
spring.datasource.max-idle=50
#空闲池中最小连接数
spring.datasource.min-idle=10
spring.datasource.initial-size=10
#连接在池中空闲最小时间后被清除
spring.datasource.min-evictable-idle-time-millis=60000
#隔多久时间清回收废弃连接
spring.datasource.time-between-eviction-runs-millis=30000
#每次调用检测池里连接的可用性,假如连接池中的连接被数据库关闭了,应用通过连接池getConnection时会重新创建
spring.datasource.testOnBorrow=true
spring.datasource.validation-query=SELECT 1
#移除被遗弃的连接
spring.datasource.remove-abandoned=true
#设置超时时间
spring.datasource.tomcat.remove-abandoned-timeout=60
【连接池】Tomcat 连接池中 maxActive,maxWait,maxAge,testOnBorrow,testWhileIdle等选项的作用
前言
连接池本质作用是为客户端提供连接复用,提升连接效率,降低系统开销。Tomcat的连接池提供了maxActive,maxWait,maxIdle,minIdle,initialSize等参数,配置连接池的大小,用户根据自身业务需求配置这几个参数。同时,因为对端数据库服务器状态不受tomcat控制,所以tomcat需要有检查连接可用性的机制,通过testOnBorrow,testWhileIdle等选项用户可以告诉tomcat是否检查连接可用性以及如何检查。
1,连接池大小及性能选项
maxActive
:最主要参数,配置连接池同时能维持的最大连接数,如果客户端理论上需要100个连接,则这个值应超过100。maxIdle
:在客户端一段时间内不需要使用连接时,如果一直把所有连接池中的所有连接都维持在活动状态是很浪费资源的,maxIdle这个选项告诉tomcat,如果客户端没有需求,那么最多维持maxIdle个空闲连接。minIdle
:和maxIdle类似,maxIdle告诉tomcat最多维持多少个空闲连接,minIdle告诉tomcat即使客户端没有需求,也要至少维持多少个空闲连接,以应对客户端的突发需求。initialSize
:连接池启动时要初始化多少个连接,即使客户端这是没有需求,也会初始化空闲连接。maxWait
:连接池中没有连接可借出状态的超时时间,单位为毫秒,比如设为10000ms,连接池如果所有连接已借出,没有可用连接,这种状态超过10秒则会抛出异常PoolExhaustedException
。maxAge
:连接池中一个连接的寿命,连接池初始化一个连接后,会记下初始化的时间,以后每次出借,或有客户端归还这个连接时,连接池会检查 当前时间 - 初始化时间 > maxAge
,如果超过maxAge,连接池会删除这个连接。
2,连接检查选项
mysql5以后,如果连接长时间不活动 (34,247,052 ms≈ 9.5 小时),mysql数据库会断开连接,这会导致异常:MySQLNonTransientConnectionException: No operations allowed after connection closed,以下选项将会告诉连接池,主动检查连接可用性,避免这个异常发生。
validationQuery
:检查连接可用性的语句,一般来说mysql设置成SELECT 1
, oracle设置成select 1 from dual
, sql server设置成SELECT 1
,在检查连接可用性时,连接池会执行这些语句,如果返回结果不为空,则说明连接可用。validationQueryTimeout
:执行连接检查语句时的超时时间。
上面两个选项告诉连接池如何检查连接有效性,下面几个选项告诉连接池在何时检查连接有效性
testOnConnect
: 在连接初始化时执行连接可用性检查testOnBorrow
:在借出连接时检查连接可用性testOnReturn
:在客户端归还连接时检查连接可用性testWhileIdle
:在检查闲置连接时同时检查连接可用性
3,一个典型的连接池设置
<Resource name="jdbc/your-jndi-name" auth="Container" type="javax.sql.DataSource"
factory="org.apache.tomcat.jdbc.pool.DataSourceFactory"
maxActive="30"
maxIdle="10"
minIdle="5"
maxWait="100000"
initialSize="5"
testWhileIdle="true"
testOnBorrow="true"
testOnReturn="false"
validationQuery="SELECT 1"
validationInterval="30000"
timeBetweenEvictionRunsMillis="30000"
maxAge="14400000"
username="your-username" password="your-password"
driverClassName="com.mysql.cj.jdbc.Driver"
url="jdbc:mysql://host-address:3306/your-db-name?useUnicode=true&characterEncoding=utf-8&disableMariaDbDriver"/>