真的会用removeAbandoned吗
removeAbandoned
(公众号 皮皮鲲编程)
removeAbandoned 是Druid连接池的一个参数。“removeAbandoned” 功能允许连接池管理器检测并删除长时间没有活动的、被遗弃的连接。当一个连接被标记为被遗弃的时候,连接池会将其从池中移除,然后释放资源,以确保连接资源能够被及时回收和重新利用,防止连接的滥用和长时间占用。
当removeAbandoned设置为True的时候,必须设置一个 removeAbandonedTimeoutMillis 时间,当连接时间超过这个时间的时候 就会触发回收机制,将该连接回收,释放资源。
让我们看看他这个操作流程:
1.当获取连接的时候,会将连接放到 activeConnections 中
Map<DruidPooledConnection, Object> activeConnections
= new IdentityHashMap<DruidPooledConnection, Object>();
public DruidPooledConnection getConnectionDirect(long maxWaitMillis) throws SQLException {
// ...前面是获取连接 省略了
if (removeAbandoned) {
//如果加了这个参数
StackTraceElement[] stackTrace = Thread.currentThread().getStackTrace();
poolableConnection.connectStackTrace = stackTrace;
//这个设置了一个时间,相当于是获取连接的时间
poolableConnection.setConnectedTimeNano();
poolableConnection.traceEnable = true;
?
activeConnectionLock.lock();
try {
//将连接放入activeConnections
activeConnections.put(poolableConnection, PRESENT);
} finally {
activeConnectionLock.unlock();
}
}
?
if (!this.defaultAutoCommit) {
poolableConnection.setAutoCommit(false);
}
?
return poolableConnection;
}
}
2.然后就会检测 他这个连接是否超过配置的时长,如果超过了,则将连接从activeConnections 拿出,并放入abandonedList中去,然后释放连接,并关闭。
源码如下:
public int removeAbandoned() {
int removeCount = 0;
?
long currrentNanos = System.nanoTime();
?
List<DruidPooledConnection> abandonedList = new ArrayList<DruidPooledConnection>();
?
activeConnectionLock.lock();
try {
Iterator<DruidPooledConnection> iter = activeConnections.keySet().iterator();
//循环遍历这个activeConnection
for (; iter.hasNext();) {
DruidPooledConnection pooledConnection = iter.next();
?
//判断这个连接如果正在执行SQL,则跳出循环
if (pooledConnection.isRunning()) {
continue;
}
// 计算连接的时间
long timeMillis = (currrentNanos - pooledConnection.getConnectedTimeNano()) / (1000 * 1000);
//如果连接时间 超过了 这个配置的时间
if (timeMillis >= removeAbandonedTimeoutMillis) {
// 移动出activeConnection
iter.remove();
// 设置这个标识是已经超过了时长了 要回收了
pooledConnection.setTraceEnable(false);
//放入abandonedList
abandonedList.add(pooledConnection);
}
}
} finally {
activeConnectionLock.unlock();
}
?
if (abandonedList.size() > 0) {
for (DruidPooledConnection pooledConnection : abandonedList) {
final ReentrantLock lock = pooledConnection.lock;
lock.lock();
try {
//如果这个连接已经被遗弃了 跳出
if (pooledConnection.isDisable()) {
continue;
}
} finally {
lock.unlock();
}
//关闭练级
JdbcUtils.close(pooledConnection);
pooledConnection.abandond();
removeAbandonedCount++;
removeCount++;
// 下面就没啥了。。。省略
?
}
}
?
return removeCount;
}
总结下removeAbandoned 的用法
1.removeAbandoned 参数和 removeAbandonedTimeoutMillis 的设置:
removeAbandoned 参数设置为 true 时,表示开启连接被遗弃的检测功能。
removeAbandonedTimeoutMillis 表示连接被认定为遗弃的时间阈值,即连接在连接池中闲置超过此阈值时被标记为遗弃。
2.连接获取和放入活动连接池:
当从连接池获取连接时,开始计时,并将连接放入活动连接池中(activeConnections)。
3.连接执行 SQL 时不被认定为遗弃:
在连接执行 SQL 语句期间处于 “running” 状态时,通常不会被认定为遗弃而回收。
4.连接执行完成归还连接池时的处理:
当连接执行完毕并归还给连接池时,如果该连接没有被认定为遗弃,则从活动连接池中移除。
5.连接回收线程的检查和标记:
对于那些尚未归还给连接池且不在 “running” 状态的连接,比如在执行 SQL 后未关闭连接的情况下,连接回收线程会检查连接自从被获取之后到现在的时间长度。
如果连接的使用时间超过了 removeAbandonedTimeoutMillis 设置的阈值,则认为该连接需要被遗弃,并被标记为遗弃状态。
连接被标记为遗弃后,连接将被关闭,不再允许归还到连接池中。
这个逻辑确保了连接池中的连接不会长时间闲置,避免了连接资源的浪费。使用 removeAbandoned 功能可以及时地回收那些长时间未释放的连接,保证了连接池的资源有效利用。
但是在代码上也有这句话:显然,他们并不推荐在生产中使用这个参数,因为可能会导致一个正常的连接被回收。造成一定影响。因此,在使用这个参数的时候一定要慎重 尤其是使用ThreadLocal 作为连接池的载体的时候 很有可能导致连接使用的过程中出现错误。做好连接使用前的判断工作。
if (removeAbandoned) {
LOG.warn("removeAbandoned is true, not use in production.");
}
?
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。 如若内容造成侵权/违法违规/事实不符,请联系我的编程经验分享网邮箱:veading@qq.com进行投诉反馈,一经查实,立即删除!