HikariPool 链接池在初始化的时候主要作了几件事:java
public HikariPool(final HikariConfig config) { super(config); // 1. 构建自定义的线程池容器 ConcurrentBag this.connectionBag = new ConcurrentBag<>(this); this.suspendResumeLock = config.isAllowPoolSuspension() ? new SuspendResumeLock() : SuspendResumeLock.FAUX_LOCK; this.houseKeepingExecutorService = initializeHouseKeepingExecutorService(); // 2. 建立链接,校验有效性 快速失败 checkFailFast(); // 若是传入opentracing的 metricsTracker就能够上报链接池的一些指标信息 if (config.getMetricsTrackerFactory() != null) { setMetricsTrackerFactory(config.getMetricsTrackerFactory()); } else { setMetricRegistry(config.getMetricRegistry()); } setHealthCheckRegistry(config.getHealthCheckRegistry()); handleMBeans(this, true); ThreadFactory threadFactory = config.getThreadFactory(); final int maxPoolSize = config.getMaximumPoolSize(); // 3. 链接新增线程池的 blockQueue,上限为 maxPoolSize LinkedBlockingQueue<Runnable> addConnectionQueue = new LinkedBlockingQueue<>(maxPoolSize); // 4. addConnectionQueueReadOnlyView 用来查看当前有几个db链接任务 this.addConnectionQueueReadOnlyView = unmodifiableCollection(addConnectionQueue); // 5. 构建负责新建db链接的线程池,1个工做线程、队列上限maxPoolSize this.addConnectionExecutor = createThreadPoolExecutor(addConnectionQueue, poolName + " connection adder", threadFactory, new ThreadPoolExecutor.DiscardOldestPolicy()); // 6. 构建负责关闭db链接的线程池,1个工做线程、队列上限maxPoolSize this.closeConnectionExecutor = createThreadPoolExecutor(maxPoolSize, poolName + " connection closer", threadFactory, new ThreadPoolExecutor.CallerRunsPolicy()); // 7. 链接泄露检测(leakDetectionThreshold默认为0,不开启),db链接从池子中取出后开始计时,若是超过必定的时长还未归还则认为可能发现链接泄露/慢查询了 this.leakTaskFactory = new ProxyLeakTaskFactory(config.getLeakDetectionThreshold(), houseKeepingExecutorService); // 8. houseKeepingExecutor 定时任务,用来维护链接池内 minimumIdle个链接 // 间隔30ms检查一次链接池,若是不足 minimumIlde则填充,超过minimumIlde~maxPoolSize的那部分链接若是空闲时长 > idleTimeout则关闭掉 this.houseKeeperTask = houseKeepingExecutorService.scheduleWithFixedDelay(**new HouseKeeper()**, 100L, housekeepingPeriodMs, MILLISECONDS); // 若是系统变量设置的阻塞等待 链接池填充完毕,则会等待 houseKeeperTask 把链接池填充完毕 if (Boolean.getBoolean("com.zaxxer.hikari.blockUntilFilled") && config.getInitializationFailTimeout() > 1) { // 给负责新建db链接的线程池 加大火力 addConnectionExecutor.setCorePoolSize(Math.min(16, Runtime.getRuntime().availableProcessors())); addConnectionExecutor.setMaximumPoolSize(Math.min(16, Runtime.getRuntime().availableProcessors())); final long startTime = currentTime(); while (elapsedMillis(startTime) < config.getInitializationFailTimeout() && getTotalConnections() < config.getMinimumIdle()) { quietlySleep(MILLISECONDS.toMillis(100)); } addConnectionExecutor.setCorePoolSize(1); addConnectionExecutor.setMaximumPoolSize(1); } }
几个关键对象:ide
String afterPrefix = "Pool "; if (idleTimeout > 0L && config.getMinimumIdle() < config.getMaximumPoolSize()) { logPoolState("Before cleanup "); afterPrefix = "After cleanup "; final List<PoolEntry> 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--; } } }
fillPool();
空闲db链接数补足到 minimumIdle 个private synchronized void fillPool() { final int connectionsToAdd = Math.min(config.getMaximumPoolSize() - getTotalConnections(), config.getMinimumIdle() - getIdleConnections()) - addConnectionQueueReadOnlyView.size(); //这时候 addConnectionExecutor 的队列视图就有用了 if (connectionsToAdd <= 0) logger.debug("{} - Fill pool skipped, pool is at sufficient level.", poolName); for (int i = 0; i < connectionsToAdd; i++) { addConnectionExecutor.submit((i < connectionsToAdd - 1) ? poolEntryCreator : postFillPoolEntryCreator); } }