首页 > Python资料 博客日记

hiricacp 连接池校验机制

2024-09-30 01:00:11Python资料围观30

Python资料网推荐hiricacp 连接池校验机制这篇文章给大家,欢迎收藏Python资料网享受知识的乐趣

一、背景

项目发生告警,但是并没有影响业务,看了下日志,红框里面有循环调用了3次 ,一直以为是外部的重试在重试,但是外部确没有重试记录,就深扒了代码

 二、想法

我知道hikaricp获取连接之后会校验连接的有效性,就猜想如果校验失败了,那本次请求是不是就是失败了,如果这样的话,那就没校验的意义了,所以肯定有重试机制用以保证请求的完整性。

三、实践

HikariDataSource.class

@Override
   public Connection getConnection() throws SQLException
   {
      if (isClosed()) {
         throw new SQLException("HikariDataSource " + this + " has been closed.");
      }

      if (fastPathPool != null) {
         return fastPathPool.getConnection();
      }

      // See http://en.wikipedia.org/wiki/Double-checked_locking#Usage_in_Java
      HikariPool result = pool;
      if (result == null) {
         synchronized (this) {
            result = pool;
            if (result == null) {
               validate();
               LOGGER.info("{} - Starting...", getPoolName());
               try {
                  pool = result = new HikariPool(this);
                  this.seal();
               }
               catch (PoolInitializationException pie) {
                  if (pie.getCause() instanceof SQLException) {
                     throw (SQLException) pie.getCause();
                  }
                  else {
                     throw pie;
                  }
               }
               LOGGER.info("{} - Start completed.", getPoolName());
            }
         }
      }

      return result.getConnection();
   }
这里面调用了   result.getConnection();  result为hikariPool
HikariPool.class
public Connection getConnection() throws SQLException
{
   return getConnection(connectionTimeout);
}





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) > aliveBypassWindowMs && !isConnectionAlive(poolEntry.connection))) {
               closeConnection(poolEntry, poolEntry.isMarkedEvicted() ? EVICTED_CONNECTION_MESSAGE : DEAD_CONNECTION_MESSAGE);
                // elapsedMillis 方法是将当前时间戳-startTime 得出的时间差
               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();
      }
   }

方法整体流程

  1. 获取锁:确保线程安全。
  2. 记录开始时间:用于后续计算超时和统计。
  3. 尝试获取连接
    • 在给定的超时时间内循环尝试获取连接。   

      elapsedMillis 方法是将当前时间戳-startTime 得出的时间差

    • 如连接无效则关闭连接并继续尝试。
    • 如连接有效则记录统计信息并返回连接。
  4. 超时处理:如在规定时间内未能成功获取连接,记录超时统计信息并抛出 SQLException
  5. 异常处理:捕获 InterruptedException 并抛出相应的 SQLException
  6. 释放锁:确保锁被释放,即使在异常情况下

版权声明:本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:jacktools123@163.com进行投诉反馈,一经查实,立即删除!

标签:

相关文章

本站推荐