博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
聊聊hikari连接池的validationTimeout
阅读量:5865 次
发布时间:2019-06-19

本文共 7499 字,大约阅读时间需要 24 分钟。

  hot3.png

本文主要研究下hikari连接池的validationTimeout

validationTimeout

默认是5秒 HikariCP/2.7.6/HikariCP-2.7.6-sources.jar!/com/zaxxer/hikari/pool/PoolBase.java

boolean isConnectionAlive(final Connection connection)   {      try {         try {            setNetworkTimeout(connection, validationTimeout);            final int validationSeconds = (int) Math.max(1000L, validationTimeout) / 1000;            if (isUseJdbc4Validation) {               return connection.isValid(validationSeconds);            }            try (Statement statement = connection.createStatement()) {               if (isNetworkTimeoutSupported != TRUE) {                  setQueryTimeout(statement, validationSeconds);               }               statement.execute(config.getConnectionTestQuery());            }         }         finally {            setNetworkTimeout(connection, networkTimeout);            if (isIsolateInternalQueries && !isAutoCommit) {               connection.rollback();            }         }         return true;      }      catch (Exception e) {         lastConnectionFailure.set(e);         LOGGER.warn("{} - Failed to validate connection {} ({})", poolName, connection, e.getMessage());         return false;      }   }   /**    * Set the network timeout, if isUseNetworkTimeout is true and the    * driver supports it.    *    * @param connection the connection to set the network timeout on    * @param timeoutMs the number of milliseconds before timeout    * @throws SQLException throw if the connection.setNetworkTimeout() call throws    */   private void setNetworkTimeout(final Connection connection, final long timeoutMs) throws SQLException   {      if (isNetworkTimeoutSupported == TRUE) {         connection.setNetworkTimeout(netTimeoutExecutor, (int) timeoutMs);      }   }   /**    * Set the query timeout, if it is supported by the driver.    *    * @param statement a statement to set the query timeout on    * @param timeoutSec the number of seconds before timeout    */   private void setQueryTimeout(final Statement statement, final int timeoutSec)   {      if (isQueryTimeoutSupported != FALSE) {         try {            statement.setQueryTimeout(timeoutSec);            isQueryTimeoutSupported = TRUE;         }         catch (Throwable e) {            if (isQueryTimeoutSupported == UNINITIALIZED) {               isQueryTimeoutSupported = FALSE;               LOGGER.info("{} - Failed to set query timeout for statement. ({})", poolName, e.getMessage());            }         }      }   }

如果是jdbc4的话,可以使用isUseJdbc4Validation,是直接利用connection.isValid(validationSeconds)来验证连接的有效性;否则的话则用connectionTestQuery查询语句来查询验证。

this.isUseJdbc4Validation = config.getConnectionTestQuery() == null;当connectionTestQuery为null的时候,isUseJdbc4Validation为true

HikariPool.getConnection

HikariCP-2.7.6-sources.jar!/com/zaxxer/hikari/pool/HikariPool.java

/**    * Get a connection from the pool, or timeout after the specified number of milliseconds.    *    * @param hardTimeout the maximum time to wait for a connection from the pool    * @return a java.sql.Connection instance    * @throws SQLException thrown if a timeout occurs trying to obtain a connection    */   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();      }   }

可以看到borrow到poolEntry之后,如果不是isMarkedEvicted,则会调用isConnectionAlive来判断连接的有效性

HikariPool

HikariCP-2.7.6-sources.jar!/com/zaxxer/hikari/pool/HikariPool.java

/**    * The house keeping task to retire and maintain minimum idle connections.    */   private final class HouseKeeper implements Runnable   {      private volatile long previous = plusMillis(currentTime(), -HOUSEKEEPING_PERIOD_MS);      @Override      public void run()      {         try {            // refresh timeouts in case they changed via MBean            connectionTimeout = config.getConnectionTimeout();            validationTimeout = config.getValidationTimeout();            leakTaskFactory.updateLeakDetectionThreshold(config.getLeakDetectionThreshold());            final long idleTimeout = config.getIdleTimeout();            final long now = currentTime();            // Detect retrograde time, allowing +128ms as per NTP spec.            if (plusMillis(now, 128) < plusMillis(previous, HOUSEKEEPING_PERIOD_MS)) {               LOGGER.warn("{} - Retrograde clock change detected (housekeeper delta={}), soft-evicting connections from pool.",                           poolName, elapsedDisplayString(previous, now));               previous = now;               softEvictConnections();               return;            }            else if (now > plusMillis(previous, (3 * HOUSEKEEPING_PERIOD_MS) / 2)) {               // No point evicting for forward clock motion, this merely accelerates connection retirement anyway               LOGGER.warn("{} - Thread starvation or clock leap detected (housekeeper delta={}).", poolName, elapsedDisplayString(previous, now));            }            previous = now;            String afterPrefix = "Pool ";            if (idleTimeout > 0L && config.getMinimumIdle() < config.getMaximumPoolSize()) {               logPoolState("Before cleanup ");               afterPrefix = "After cleanup  ";               final List
notInUse = connectionBag.values(STATE_NOT_IN_USE); int toRemove = notInUse.size() - config.getMinimumIdle(); for (PoolEntry entry : notInUse) { if (toRemove > 0 && elapsedMillis(entry.lastAccessed, now) > idleTimeout && connectionBag.reserve(entry)) { closeConnection(entry, "(connection has passed idleTimeout)"); toRemove--; } } } logPoolState(afterPrefix); fillPool(); // Try to maintain minimum connections } catch (Exception e) { LOGGER.error("Unexpected exception in housekeeping task", e); } } }

HouseKeeper线程也用到了validationTimeout

小结

validationTimeout用来指定验证连接有效性的超时时间(默认是5秒,最小不能小于250毫秒),如果是没有设置connectionTestQuery的话,默认是用jdbc4规范中的connection.isValid(validationSeconds)来验证连接的有效性。

另外hikari是在borrow连接的时候校验连接的有效性,相当于tomcat jdbc pool的testOnBorrow=true

doc

转载于:https://my.oschina.net/go4it/blog/1616752

你可能感兴趣的文章
如何看待一本图书
查看>>
Linux 中如何通过命令行访问 Dropbox
查看>>
开发进度——4
查看>>
JS里验证信息
查看>>
Akka actor tell, ask 函数的实现
查看>>
windows10 chrome 调试 ios safari 方法
查看>>
Hello , Ruby!
查看>>
Netty 4.1.35.Final 发布,经典开源 Java 网络服务框架
查看>>
详解Microsoft.AspNetCore.CookiePolicy
查看>>
SCDPM2012 R2实战一:基于SQL 2008 R2集群的SCDPM2012 R2的安装
查看>>
SQL SERVER中字段类型与C#数据类型的对应关系
查看>>
Linux lsof命令详解
查看>>
SVG path
查看>>
js判断checkbox是否选中
查看>>
多系统盘挂载
查看>>
MySQL函数怎么加锁_MYSQL 函数调用导致自动生成共享锁问题
查看>>
MR1和MR2的工作原理
查看>>
Eclipse中修改代码格式
查看>>
GRUB Legacy
查看>>
关于 error: LINK1123: failure during conversion to COFF: file invalid or corrupt 错误的解决方案...
查看>>