数据库连接池hikari异常断开解决思路(整理的网上的资料)

  数据库连接池连接超时异常断开的问题。提出以下解决思路

  1.延长maxLifetime大小 

  注: maxLifetime 设置一个connection在连接池中的存活时间 默认30分钟 ,如果设置为0,表示存活时间无限大。如果不等于0且小于30秒则会被重置回30分钟。

  2.更改配置 allowPoolSuspension: true  

                     registerMbeans: true

效果 当池被暂停时,调用 getConnection()将不会超时,并将一直保持到池恢复为止。SQL执行都会被保留下来,软驱除现有连接之后,一直保持到池恢复Resume时,这些SQL依然会继续执行,也就是说并不会丢数据。缺点长期阻塞该参数存在让服务卡死的风险。

附 参数涉及到的相关代码

// 池中连接最长生命周期 设置最少3000
 if (maxLifetime != 0 && maxLifetime < SECONDS.toMillis(30)) {
    LOGGER.warn("{} - maxLifetime is less than 30000ms, setting to default {}ms.", poolName, MAX_LIFETIME);
    maxLifetime = MAX_LIFETIME;
 }
//连接允许在池中闲置的最长时间  要小于maxLifetime 池中连接最长生命周期
 if (idleTimeout + SECONDS.toMillis(1) > maxLifetime && maxLifetime > 0) {
    LOGGER.warn("{} - idleTimeout is close to or more than maxLifetime, disabling it.", poolName);
    idleTimeout = 0;
 }
 
创造新的poolEntry。如果配置了maxLifetime,则创建一个将来的结束生命任务,其方差为2.5%
 确保池中没有大量连接死亡的最大生存期时间
 */
private PoolEntry createPoolEntry()
{
   try {
      final PoolEntry poolEntry = newPoolEntry();

      final long maxLifetime = config.getMaxLifetime();
      if (maxLifetime > 0) {
         // variance up to 2.5% of the maxlifetime
         final long variance = maxLifetime > 10_000 ? ThreadLocalRandom.current().nextLong( maxLifetime / 40 ) : 0;
         final long lifetime = maxLifetime - variance;
         poolEntry.setFutureEol(houseKeepingExecutorService.schedule(
            () -> {
               if (softEvictConnection(poolEntry, "(connection has passed maxLifetime)", false /* not owner */)) {
                  addBagItem(connectionBag.getWaitingThreadCount());
               }
            },
            lifetime, MILLISECONDS));
      }

      return poolEntry;
   }
   catch (Exception e) {
      if (poolState == POOL_NORMAL) { // we check POOL_NORMAL to avoid a flood of messages if shutdown() is running concurrently
         LOGGER.debug("{} - Cannot acquire connection from data source", poolName, (e instanceof ConnectionSetupException ? e.getCause() : e));
      }
      return null;
   }
}
if (leakDetectionThreshold > 0 && !unitTest) {

   if (leakDetectionThreshold < SECONDS.toMillis(2) || (leakDetectionThreshold >



      maxLifetime && maxLifetime > 0)) {

      LOGGER.warn("{} - leakDetectionThreshold is less than 2000ms or more than maxLifetime, disabling it.", poolName);

      leakDetectionThreshold = 0;

   }

}
public Connection getConnection(final long hardTimeout) throws SQLException
{
   suspendResumeLock.acquire();
   final long startTime = currentTime();
   try {
      long timeout = hardTimeout;
      do {
         PoolEntry poolEntry = connectionBag.borrow(timeout, MILLISECONDS);
         if (poolEntry == null) {
            break; // We timed out... break and throw exception
         }
         final long now = currentTime();
         if (poolEntry.isMarkedEvicted() || (elapsedMillis(poolEntry.lastAccessed, now) > ALIVE_BYPASS_WINDOW_MS && !isConnectionAlive(poolEntry.connection))) {
            closeConnection(poolEntry, poolEntry.isMarkedEvicted() ? EVICTED_CONNECTION_MESSAGE : DEAD_CONNECTION_MESSAGE);
            timeout = hardTimeout - elapsedMillis(startTime);
         }
         else {
            metricsTracker.recordBorrowStats(poolEntry, startTime);
            return poolEntry.createProxyConnection(leakTaskFactory.schedule(poolEntry), now);
         }
      } while (timeout > 0L);
      metricsTracker.recordBorrowTimeoutStats(startTime);
      throw createTimeoutException(startTime);
   }
   catch (InterruptedException e) {
      Thread.currentThread().interrupt();
      throw new SQLException(poolName + " - Interrupted during connection acquisition", e);
   }
   finally {
      suspendResumeLock.release();
   }
}
public Connection getConnection() throws SQLException
{
   return getConnection(connectionTimeout);
}

 

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值