java
  • 001
  • 002
  • 003
  • 004
  • 005
  • 006
  • 007
  • 008
  • 009
  • 010
  • 011
  • 012
  • 013
  • 014
  • 015
  • 016
  • 017
  • 018
  • 019
  • 020
  • 021
  • 022
  • 023
  • 024
  • 025
  • 026
  • 027
  • 028
  • 029
  • 030
  • 031
  • 032
  • 033
  • 034
  • 035
  • 036
  • 037
  • 038
  • 039
  • 040
  • 041
  • 042
  • 043
  • 044
  • 045
  • 046
  • 047
  • 048
  • 049
  • 050
  • 051
  • 052
  • 053
  • 054
  • 055
  • 056
  • 057
  • 058
  • 059
  • 060
  • 061
  • 062
  • 063
  • 064
  • 065
  • 066
  • 067
  • 068
  • 069
  • 070
  • 071
  • 072
  • 073
  • 074
  • 075
  • 076
  • 077
  • 078
  • 079
  • 080
  • 081
  • 082
  • 083
  • 084
  • 085
  • 086
  • 087
  • 088
  • 089
  • 090
  • 091
  • 092
  • 093
  • 094
  • 095
  • 096
  • 097
  • 098
  • 099
  • 100
  • 101
  • 102
  • 103
  • 104
  • 105
  • 106
  • 107
  • 108
  • 109
  • 110
  • 111
  • 112
  • 113
  • 114
  • 115
  • 116
  • 117
  • 118
  • 119
  • 120
  • 121
  • 122
  • 123
  • 124
  • 125
  • 126
  • 127
  • 128
  • 129
  • 130
  • 131
  • 132
  • 133
  • 134
  • 135
  • 136
  • 137
  • 138
  • 139
  • 140
  • 141
  • 142
  • 143
  • 144
  • 145
  • 146
  • 147
  • 148
  • 149
  • 150
  • 151
  • 152
  • 153
  • 154
  • 155
  • 156
  • 157
  • 158
  • 159
  • 160
  • 161
  • 162
  • 163
  • 164
  • 165
  • 166
  • 167
  • 168
  • 169
  • 170
  • 171
  • 172
  • 173
  • 174
  • 175
  • 176
  • 177
  • 178
  • 179
  • 180
  • 181
  • 182
  • 183
  • 184
  • 185
  • 186
  • 187
  • 188
  • 189
  • 190
  • 191
  • 192
  • 193
  • 194
  • 195
  • 196
  • 197
  • 198
  • 199
  • 200
  • 201
  • 202
  • 203
  • 204
  • 205
  • 206
  • 207
  • 208
  • 209
  • 210
  • 211
  • 212
  • 213
  • 214
  • 215
  • 216
  • 217
  • 218
  • 219
  • 220
  • 221
  • 222
  • 223
  • 224
  • 225
  • 226
  • 227
  • 228
  • 229
  • 230
  • 231
  • 232
  • 233
  • 234
  • 235
  • 236
  • 237
  • 238
// 连接池瘦身 public void shrink(boolean checkTime, boolean keepAlive) { try { lock.lockInterruptibly(); } catch (InterruptedException e) { return; } boolean needFill = false; int evictCount = 0; int keepAliveCount = 0; int fatalErrorIncrement = fatalErrorCount - fatalErrorCountLastShrink; fatalErrorCountLastShrink = fatalErrorCount; try { if (!inited) { return; } // 根据 poolingCount 和 minIdle 计算出 evictCheck(丢弃检查) 的范围 final int checkCount = poolingCount - minIdle; final long currentTimeMillis = System.currentTimeMillis(); // 开始遍历连接池里闲置的连接 for (int i = 0; i < poolingCount; ++i) { DruidConnectionHolder connection = connections[i]; if ((onFatalError || fatalErrorIncrement > 0) && (lastFatalErrorTimeMillis > connection.connectTimeMillis)) { keepAliveConnections[keepAliveCount++] = connection; continue; } // 除非手动调用,不然经过主流程4触发,一般为 true if (checkTime) { // 默认不启用,忽略 if (phyTimeoutMillis > 0) { long phyConnectTimeMillis = currentTimeMillis - connection.connectTimeMillis; if (phyConnectTimeMillis > phyTimeoutMillis) { evictConnections[evictCount++] = connection; continue; } } // 计算闲置时间 long idleMillis = currentTimeMillis - connection.lastActiveTimeMillis; // 如果闲置时间达不到检测&瘦身的阈值,则不处理 if (idleMillis < minEvictableIdleTimeMillis && idleMillis < keepAliveBetweenTimeMillis ) { break; } // 达到需要丢弃的阈值时,则判断连接下标是否在 evictCheck 范围,若在,则视为“可以丢弃的对象”放入e victConnections 数组 if (idleMillis >= minEvictableIdleTimeMillis) { if (checkTime && i < checkCount) { evictConnections[evictCount++] = connection; continue; } else if (idleMillis > maxEvictableIdleTimeMillis) { evictConnections[evictCount++] = connection; continue; } } // 如果上面的条件均没有命中,如果 keepAlive 为 true,则判断是不是超过了闲置连接检查其活性的频次阈值(即由 keepAliveBetweenTimeMillis 控制) if (keepAlive && idleMillis >= keepAliveBetweenTimeMillis) { // 满足条件则视为“需要检测活性的对象”,放入 keepAliveConnections 数组 keepAliveConnections[keepAliveCount++] = connection; } } else { if (i < checkCount) { evictConnections[evictCount++] = connection; } else { break; } } } // 这一批需要移除特殊处理的连接总数 int removeCount = evictCount + keepAliveCount; if (removeCount > 0) { // 根据当前移除的元素,把剩余的元素移动至数组首部(参考流程4.1) System.arraycopy(connections, removeCount, connections, 0, poolingCount - removeCount); // 剩余位置清空 Arrays.fill(connections, poolingCount - removeCount, poolingCount, null); poolingCount -= removeCount; } keepAliveCheckCount += keepAliveCount; if (keepAlive && poolingCount + activeCount < minIdle) { needFill = true; } } finally { lock.unlock(); } // 如果需要丢弃的连接数量大于 0 if (evictCount > 0) { for (int i = 0; i < evictCount; ++i) { DruidConnectionHolder item = evictConnections[i]; Connection connection = item.getConnection(); // 直接关闭连接(这里是直接关闭驱动连接,不再放回池子) JdbcUtils.close(connection); destroyCountUpdater.incrementAndGet(this); } // 将 evictConnections 数组重新置空(方便下次使用) Arrays.fill(evictConnections, null); } // 检测那些需要判活的连接数 if (keepAliveCount > 0) { // keep order for (int i = keepAliveCount - 1; i >= 0; --i) { DruidConnectionHolder holer = keepAliveConnections[i]; Connection connection = holer.getConnection(); holer.incrementKeepAliveCheckCount(); boolean validate = false; try { // 检测其活性 this.validateConnection(connection); validate = true; } catch (Throwable error) { if (LOG.isDebugEnabled()) { LOG.debug("keepAliveErr", error); } // skip } boolean discard = !validate; // 检测通过 if (validate) { holer.lastKeepTimeMillis = System.currentTimeMillis(); // 检测通过后,再次放入池子 boolean putOk = put(holer, 0L, true); if (!putOk) { // 放不进去池子(说明已经达到连接池最大连接数阈值 maxActive),则视为可以“直接抛弃”的连接 discard = true; } } if (discard) { try { // 如果可以抛弃,则直接关闭连接(直接调用驱动的 close) connection.close(); } catch (Exception e) { // skip } lock.lock(); try { // 抛弃连接数累加 discardCount++; if (activeCount + poolingCount <= minIdle) { // 唤起主流程3追加连接对象 emptySignal(); } } finally { lock.unlock(); } } } this.getDataSourceStat().addKeepAliveCheckCount(keepAliveCount); // 将 keepAliveConnections 数组重新置空(方便下次使用) Arrays.fill(keepAliveConnections, null); } if (needFill) { lock.lock(); try { int fillCount = minIdle - (activeCount + poolingCount + createTaskCount); for (int i = 0; i < fillCount; ++i) { emptySignal(); } } finally { lock.unlock(); } } else if (onFatalError || fatalErrorIncrement > 0) { lock.lock(); try { emptySignal(); } finally { lock.unlock(); } } } // 上面检测通过,再次通过该方法重新把连接放入池子 private boolean put(DruidConnectionHolder holder, long createTaskId, boolean checkExists) { lock.lock(); try { if (this.closing || this.closed) { return false; } // 若池子内闲置连接数超过 maxActive,则无法继续添加新的连接进来,返回 false if (poolingCount >= maxActive) { if (createScheduler != null) { clearCreateTask(createTaskId); } return false; } if (checkExists) { for (int i = 0; i < poolingCount; i++) { if (connections[i] == holder) { return false; } } } // 否则直接把此连接对象放入连接池队尾 connections[poolingCount] = holder; incrementPoolingCount(); if (poolingCount > poolingPeak) { poolingPeak = poolingCount; poolingPeakTime = System.currentTimeMillis(); } // 唤起那些因获取不到可用连接而陷入阻塞状态的业务线程一次 notEmpty.signal(); notEmptySignalCount++; // 不启用该模式,忽略 if (createScheduler != null) { clearCreateTask(createTaskId); if (poolingCount + createTaskCount < notEmptyWaitThreadCount // && activeCount + poolingCount + createTaskCount < maxActive) { emptySignal(); } } } finally { lock.unlock(); } return true; }