真的会用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.");
      }

你可能感兴趣的:(java,jvm,算法)