zoukankan      html  css  js  c++  java
  • Hikari申请db连接的过程

    HikariDataSource#getConnection → HikariPool#getConnection

    public Connection getConnection(final long hardTimeout) throws SQLException
       {
          suspendResumeLock.acquire(); //获取信号量,这个是提供给jmx控制的功能 默认是空实现,可忽略
          final long startTime = currentTime();
    
          try {
             long timeout = hardTimeout;
             do {
    						//从connectionBag获取连接,如果超时则直接退出
                PoolEntry poolEntry = connectionBag.borrow(timeout, MILLISECONDS);
                if (poolEntry == null) {
                   break; // We timed out... break and throw exception
                }
    
                final long now = currentTime();
    						// 如果poolEntry被标记为evicted,则要关闭这个连接
    						// 如果poolEntry上次访问时间到现在超过 aliveBypassWindowsMs=500ms,需要检测下连接是否可用,如果不可用的话,关闭连接
                if (poolEntry.isMarkedEvicted() || (elapsedMillis(poolEntry.lastAccessed, now) > aliveBypassWindowMs && !isConnectionAlive(poolEntry.connection))) {
                   closeConnection(poolEntry, poolEntry.isMarkedEvicted() ? EVICTED_CONNECTION_MESSAGE : DEAD_CONNECTION_MESSAGE);
                   timeout = hardTimeout - elapsedMillis(startTime);
                }
                else {
                   metricsTracker.recordBorrowStats(poolEntry, startTime);
    							 // 返回代理db连接
                   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();
          }
       }
    

    connectionBag.borrow() 的过程参见 Hikari定制连接池容器ConcurrentBag

    成功获取到 poolEntry 后时,leakTaskFactory.schedule(poolEntry) 会启动一个连接泄露的检测任务 ProxyLeakTask ,如果超过 leakDetectionThreshold(默认是0,不开启) 时长还未归还则认为这个连接泄露了

     ProxyLeakTask schedule(final PoolEntry poolEntry)
     {
    		// 默认是关闭的
        return (leakDetectionThreshold == 0) ? ProxyLeakTask.NO_LEAK : scheduleNewTask(poolEntry);
     }
    
     
     private ProxyLeakTask scheduleNewTask(PoolEntry poolEntry) {
        ProxyLeakTask task = new ProxyLeakTask(poolEntry);
    	  //一次性任务,在leakDetectionThreshold后执行一次
        task.schedule(executorService, leakDetectionThreshold);
    
        return task;
     }
    

    executorService使用的是 houseKeepingExecutorService 管家调度线程池, 在连接从池子里拿出 leakDetectionThreshold 时间后执行一次 ProxyLeakTask#run()

    public void run()
       {
          isLeaked = true;
    
          final StackTraceElement[] stackTrace = exception.getStackTrace(); 
          final StackTraceElement[] trace = new StackTraceElement[stackTrace.length - 5];
          System.arraycopy(stackTrace, 5, trace, 0, trace.length);
    
          exception.setStackTrace(trace);
          LOGGER.warn("Connection leak detection triggered for {} on thread {}, stack trace follows", connectionName, threadName, exception);
       }
    

    标识已经泄露了 isLeaked = true, 并打印 'Connection leak detection xxx' 警告日志

    当连接 close() 归还回池子时,会取消这个 ProxyLeakTask#cancel()

    void cancel()
       {
          scheduledFuture.cancel(false);
    			// 如果是被标记为”泄露"后再取消的,则打印个日志说明下
          if (isLeaked) {
             LOGGER.info("Previously reported leaked connection {} on thread {} was returned to the pool (unleaked)", connectionName, threadName);
          }
       }
    

    本文来自博客园,作者:mushishi,转载请注明原文链接:https://www.cnblogs.com/mushishi/p/14665230.html

  • 相关阅读:
    Android Fragment 解析和使用
    Android数据库表的创建和数据升级操作
    Android通过xml文件配置数据库
    Android上的事件流操作数据库
    Android SQLite的ORM接口实现(一)---findAll和find的实现
    Android注解编程的第一步---模仿ButterKnife的ViewBinder机制
    Android下拉刷新底部操作栏的隐藏问题
    Android开发总结
    一个ListView布局的不断演化
    SpringBoot入门-概念(一)
  • 原文地址:https://www.cnblogs.com/mushishi/p/14665230.html
Copyright © 2011-2022 走看看