200字范文,内容丰富有趣,生活中的好帮手!
200字范文 > 记一次Hikari数据库连接池连接失败问题

记一次Hikari数据库连接池连接失败问题

时间:2019-05-24 17:18:27

相关推荐

记一次Hikari数据库连接池连接失败问题

HiKari数据库连接池

HiKari源于日语“光”的意思,HiKariCP顾名思义就是 和光速一样快,HiKariCP是数据库连接池的一个后起之秀,号称性能最好,稳定性也不错,完美地PK掉其他连接池。

这里提供一篇文章介绍主流Java数据库连接池比较及前瞻,文中重点介绍了当前主流开源数据库连接池(比如C3P0、DBCP、Tomcat Jdbc Pool、Druid和Hikaricp)的性能分析和功能比较,有一定的参考价值.

回归到本文正题,在开发一个新项目时遇到一个问题——在定时任务中需要向数据库进行查询,插入操作,在项目运行一段时间后,Hikaricp连接池获取不到连接数而连接不到数据库,导致请求失败。

具体异常如下:

-07-27T18:00:11.092+08:00 ERROR sam [Weather_task-1] [o.s.s.support.TaskUtils$LoggingErrorHandler:95] Unexpected error occurred in scheduled taskorg.springframework.transaction.CannotCreateTransactionException: Could not open JDBC Connection for transaction; nested exception is java.sql.SQLTransientConnectionException: HikariPool-1 - Connection is not available, request timed out after 10012ms.at org.springframework.jdbc.datasource.DataSourceTransactionManager.doBegin(DataSourceTransactionManager.java:305)at org.springframework.transaction.support.AbstractPlatformTransactionManager.startTransaction(AbstractPlatformTransactionManager.java:400)at org.springframework.transaction.support.AbstractPlatformTransactionManager.getTransaction(AbstractPlatformTransactionManager.java:373)at org.springframework.transaction.interceptor.TransactionAspectSupport.createTransactionIfNecessary(TransactionAspectSupport.java:573)at org.springframework.transaction.interceptor.TransactionAspectSupport.invokeWithinTransaction(TransactionAspectSupport.java:361)at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:118)at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186)at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.proceed(CglibAopProxy.java:749)at org.springframework.aop.framework.CglibAopProxy$DynamicAdvisedInterceptor.intercept(CglibAopProxy.java:691)at com.XXX.sample.service.weather.WeatherService$$EnhancerBySpringCGLIB$$5c6f938c.insertWeather(<generated>)at com.XXX.sample.service.task.WeatherTaskService.doSyn(WeatherTaskService.java:69)at com.XXX.sample.service.task.WeatherTaskService.synWeather(WeatherTaskService.java:45)at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)at java.lang.reflect.Method.invoke(Method.java:498)at org.springframework.scheduling.support.ScheduledMethodRunnable.run(ScheduledMethodRunnable.java:84)at org.springframework.scheduling.support.DelegatingErrorHandlingRunnable.run(DelegatingErrorHandlingRunnable.java:54)at org.springframework.scheduling.concurrent.ReschedulingRunnable.run(ReschedulingRunnable.java:93)at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:511)at java.util.concurrent.FutureTask.run$$$capture(FutureTask.java:266)at java.util.concurrent.FutureTask.run(FutureTask.java)at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.access$201(ScheduledThreadPoolExecutor.java:180)at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.run(ScheduledThreadPoolExecutor.java:293)at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)at java.lang.Thread.run(Thread.java:748)Caused by: java.sql.SQLTransientConnectionException: HikariPool-1 - Connection is not available, request timed out after 10012ms.at com.zaxxer.hikari.pool.HikariPool.createTimeoutException(HikariPool.java:695)at com.zaxxer.hikari.pool.HikariPool.getConnection(HikariPool.java:197)at com.zaxxer.hikari.pool.HikariPool.getConnection(HikariPool.java:162)at com.zaxxer.hikari.HikariDataSource.getConnection(HikariDataSource.java:128)at org.springframework.jdbc.datasource.DataSourceTransactionManager.doBegin(DataSourceTransactionManager.java:261)... 26 common frames omittedCaused by: org.postgresql.util.PSQLException: This connection has been closed.at org.postgresql.jdbc.PgConnection.checkClosed(PgConnection.java:783)at org.postgresql.jdbc.PgConnection.setNetworkTimeout(PgConnection.java:1556)at com.zaxxer.hikari.pool.PoolBase.setNetworkTimeout(PoolBase.java:560)at com.zaxxer.hikari.pool.PoolBase.isConnectionAlive(PoolBase.java:173)at com.zaxxer.hikari.pool.HikariPool.getConnection(HikariPool.java:186)... 29 common frames omitted

问题分析:

1、系统的并行环境并没有此异常,生产环境的差异只是数据库部署在不同的主机上;

2、访问数据库命令的网络耗时正常,数据库端收到连接请求,且该时段数据库连接数并没有耗尽;

3、数据库管理员在异常时间段查询得知,不存在慢sql语句,不存在不合理设置索引导致此异常

既然环境没有什么问题,那么只能充HiKari的配置上入手。

以下是异常的数据源配置:

<bean id="dataSource" class="com.zaxxer.hikari.HikariDataSource"><property name="driverClassName" value="${db.driver}"/><property name="jdbcUrl" value="${db.url}"/><property name="username" value="${db.username}"/><property name="password" value="${db.password}"/><!-- 配置连接池最小值、最大值 --><property name="minimumIdle" value="5" /><property name="maximumPoolSize" value="15" /><!-- 配置获取连接等待超时的时间 --><property name="connectionTimeout" value="10000" /><property name="idleTimeout" value="600000" /><property name="maxLifetime" value="83460000" /></bean>

后四个重要参数的解释:

1).connectionTimeout:等待连接池分配连接的最大时长(毫秒),超过这个时长还没可用的连接则发生SQLException, 缺省:10秒

2).idleTimeout:此属性控制允许连接在池中闲置的最长时间,此设置仅适用于minimumIdle设置为小于maximumPoolSize的情况 默认:600000(10分钟)

3).maxLifetime:一个连接的生命时长(毫秒),超时而且没被使用则被释放(retired),缺省:23.3小时,建议设置比数据库超时时长少30秒

4).maximumPoolSize:连接池中允许的最大连接数(包括空闲和正在使用的连接)。缺省值:10;

通过分析可以看到:

1.connectionTimeout采用默认值10s,应该不会有太大问题。

2.maximumPoolSize根据业务量的设置,不会有太大问题。

3.maxLifetime如果过长,且idleTimeout没有时间限制时,会导致连接数很大,空闲连接一直得不到释放,严重挤占资源,容易引起连接数不够的问题。

4.idleTimeout只有在minimumIdle设置为小于maximumPoolSize的情况下才生效,minimumIdle默认是等于maximumPoolSize,我已经设置了idleTimeout,应该也没问题。

5.未配置destroy-method=“close”,导致连接使用完以后,由于我配置的最大生存时间还未到期,没有释放该连接,导致连接池中的连接被耗尽,获取连接失败

优化后的配置:

<bean id="dataSource" class="com.zaxxer.hikari.HikariDataSource" destroy-method="close"><property name="driverClassName" value="${db.driver}"/><property name="jdbcUrl" value="${db.url}"/><property name="username" value="${db.username}"/><property name="password" value="${db.password}"/><!-- 配置连接池最小值、最大值 --><property name="minimumIdle" value="5" /><property name="maximumPoolSize" value="15" /><!-- 配置获取连接等待超时的时间 --><property name="connectionTimeout" value="60000" /><property name="connectionTestQuery" value="SELECT 1"/><property name="validationTimeout" value="5000"/><property name="poolName" value="CcosDataSource"/><property name="idleTimeout" value="60000" /><property name="maxLifetime" value="600000" /></bean>

相比较之前的配置,此次优化之处:

1、增加数据连接关闭方法,当从dataSource获取的连接使用完成后,调用close方法,以避免数据源对象仍然可用,造成连接泄露

2、连接空闲时间idleTimeout生效,减少空闲连接占用,尽快释放数据库连接

3、连接生命周期maxLifetime值设为100分钟,尽快释放数据库无效连接

4、增加连接池的用户定义名称

5、增加验证连接有效性的超时时间

6、增加连接有效性测试语句

修改完配置以后,再次部署运行:

目前系统暂未发生数据库连接异常现象,继续观察。

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。