searchusermenu
  • 发布文章
  • 消息中心
点赞
收藏
评论
分享
原创

druid 入门相关

2023-11-02 06:54:38
2
0

入门参考:

官方文档:
 github.com/alibaba/druid/wiki/DruidDataSource%E9%85%8D%E7%BD%AE
参考其中配置。


                                   ConnectionPool
                              |---------------------------| 
                              |                           |
       getConnection          |                           |    
      (notEmpty.await)        |                           |   
      (lowWater.signal)       |                           |
      (maxActive.await)       |                           |
  <-------------------------- |                           |
  <-------------------------- |                           |
  <-------------------------- |                           |
                              |                           |
                              |                           |
  --------------------------> |                           |
  --------------------------> |                           |    销毁多余连接的线程
  --------------------------> |                           |    (highWater.awati, idleTimeout.await)
    close                     |                           | --------------------------------------> 
    (highWater.signal)        |                           |
    (maxActive.signal)        |                           |  
                              |                           |
                              |                           |
              产生连接的线程     |                           |
     (lowWater.await)         |                           |
     (notEmpty.signal)        |                           |
  --------------------------> |                           |
                              |                           |
                              |---------------------------|
                              
五个Condition:notEmpty、maxActive、lowWater、hightWater, idleTime

    public Connection createPhysicalConnection(String url, Properties info) throws SQLException {
        Connection conn;
        if (getProxyFilters().size() == 0) {
            conn = getDriver().connect(url, info);
        } else {
            conn = new FilterChainImpl(this).connection_connect(info);
        }

        createCountUpdater.incrementAndGet(this);

        return conn;
    }

对比proxool连接池:

 


proxool太古老,不方便监控,参数控制等也有些问题:比如
maximumConnectionLifetime 是通过创建时间来控制的:

/**
 * The age in millseconds since this connection was built
 */
long getAge();


以下是过期清理的代码:
HouseKeeper.sweep()
        // Now to check whether the connection is due for expiry
       if (proxyConnection.getAge() > definition.getMaximumConnectionLifetime()) {
           final String reason = "age is " + proxyConnection.getAge() + "ms";
           // Check whether we can make it offline
           if (proxyConnection.setStatus(ProxyConnectionIF.STATUS_AVAILABLE, ProxyConnectionIF.STATUS_OFFLINE)) {
               if (proxyConnection.setStatus(ProxyConnectionIF.STATUS_OFFLINE, ProxyConnectionIF.STATUS_NULL)) {
                   // It is.  Expire it now .
                   connectionPool.expireProxyConnection(proxyConnection, ConnectionListenerIF.MAXIMUM_CONNECTION_LIFETIME_EXCEEDED, reason, ConnectionPool.REQUEST_EXPIRY);
               }
           } else {
               // Oh no, it's in use.  Never mind, we'll mark it for expiry
               // next time it is available.  This will happen in the
               // putConnection() method.
               proxyConnection.markForExpiry(reason);
               if (log.isDebugEnabled()) {
                   log.debug(connectionPool.displayStatistics() + " - #" + FormatHelper.formatMediumNumber(proxyConnection.getId())
                           + " marked for expiry.");
               }
           } // END if (poolableConnection.setOffline())
       } // END if (poolableConnection.getAge() > maximumConnectionLifetime)   


生产连接池,小于minimumConnectionCount则添加,小于最小空闲数prototypeCount也添加。
Prototyper.sweep()
while (!cancel && connectionPool.isConnectionPoolUp()) {

            String reason = null;
            if (connectionCount >= getDefinition().getMaximumConnectionCount()) {
                // We don't want to make any more that the maximum
                break;
            } else if (connectionCount < getDefinition().getMinimumConnectionCount()) {
                reason = "to achieve minimum of " + getDefinition().getMinimumConnectionCount();
            } else if (connectionPool.getAvailableConnectionCount() < getDefinition().getPrototypeCount()) {
                reason = "to keep " + getDefinition().getPrototypeCount() + " available";
            } else {
                // Nothing to do
                break;
            }

            ProxyConnectionIF freshlyBuiltProxyConnection = null;
            try {
                // If it has been shutdown then we should just stop now.
                if (!connectionPool.isConnectionPoolUp()) {
                    break;
                }
                freshlyBuiltProxyConnection = buildConnection(ConnectionInfoIF.STATUS_AVAILABLE, reason);
                somethingDone = true;
            } catch (Throwable e) {
                log.error("Prototype", e);
            }
}
 

以上就会造成非高峰期时间段内,如果最小值配的比较大,会固定回收时间重新创建一次连接池的最小个数。
而druid没有这个问题:

 


DruidDataSource.shrink()
for (int i = 0; i < poolingCount; ++i) {
            DruidConnectionHolder connection = connections[i];

            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) {
                    break;
                }

                if (checkTime && i < checkCount) {
                    evictConnections[evictCount++] = connection;
                } else if (idleMillis > maxEvictableIdleTimeMillis) {
                    evictConnections[evictCount++] = connection;
                } else if (keepAlive) {
                    keepAliveConnections[keepAliveCount++] = connection;
                }
            } else {
                if (i < checkCount) {
                    evictConnections[evictCount++] = connection;
                } else {
                    break;
                }
            }
        }
 
0条评论
0 / 1000
林维镇
5文章数
0粉丝数
林维镇
5 文章 | 0 粉丝
原创

druid 入门相关

2023-11-02 06:54:38
2
0

入门参考:

官方文档:
 github.com/alibaba/druid/wiki/DruidDataSource%E9%85%8D%E7%BD%AE
参考其中配置。


                                   ConnectionPool
                              |---------------------------| 
                              |                           |
       getConnection          |                           |    
      (notEmpty.await)        |                           |   
      (lowWater.signal)       |                           |
      (maxActive.await)       |                           |
  <-------------------------- |                           |
  <-------------------------- |                           |
  <-------------------------- |                           |
                              |                           |
                              |                           |
  --------------------------> |                           |
  --------------------------> |                           |    销毁多余连接的线程
  --------------------------> |                           |    (highWater.awati, idleTimeout.await)
    close                     |                           | --------------------------------------> 
    (highWater.signal)        |                           |
    (maxActive.signal)        |                           |  
                              |                           |
                              |                           |
              产生连接的线程     |                           |
     (lowWater.await)         |                           |
     (notEmpty.signal)        |                           |
  --------------------------> |                           |
                              |                           |
                              |---------------------------|
                              
五个Condition:notEmpty、maxActive、lowWater、hightWater, idleTime

    public Connection createPhysicalConnection(String url, Properties info) throws SQLException {
        Connection conn;
        if (getProxyFilters().size() == 0) {
            conn = getDriver().connect(url, info);
        } else {
            conn = new FilterChainImpl(this).connection_connect(info);
        }

        createCountUpdater.incrementAndGet(this);

        return conn;
    }

对比proxool连接池:

 


proxool太古老,不方便监控,参数控制等也有些问题:比如
maximumConnectionLifetime 是通过创建时间来控制的:

/**
 * The age in millseconds since this connection was built
 */
long getAge();


以下是过期清理的代码:
HouseKeeper.sweep()
        // Now to check whether the connection is due for expiry
       if (proxyConnection.getAge() > definition.getMaximumConnectionLifetime()) {
           final String reason = "age is " + proxyConnection.getAge() + "ms";
           // Check whether we can make it offline
           if (proxyConnection.setStatus(ProxyConnectionIF.STATUS_AVAILABLE, ProxyConnectionIF.STATUS_OFFLINE)) {
               if (proxyConnection.setStatus(ProxyConnectionIF.STATUS_OFFLINE, ProxyConnectionIF.STATUS_NULL)) {
                   // It is.  Expire it now .
                   connectionPool.expireProxyConnection(proxyConnection, ConnectionListenerIF.MAXIMUM_CONNECTION_LIFETIME_EXCEEDED, reason, ConnectionPool.REQUEST_EXPIRY);
               }
           } else {
               // Oh no, it's in use.  Never mind, we'll mark it for expiry
               // next time it is available.  This will happen in the
               // putConnection() method.
               proxyConnection.markForExpiry(reason);
               if (log.isDebugEnabled()) {
                   log.debug(connectionPool.displayStatistics() + " - #" + FormatHelper.formatMediumNumber(proxyConnection.getId())
                           + " marked for expiry.");
               }
           } // END if (poolableConnection.setOffline())
       } // END if (poolableConnection.getAge() > maximumConnectionLifetime)   


生产连接池,小于minimumConnectionCount则添加,小于最小空闲数prototypeCount也添加。
Prototyper.sweep()
while (!cancel && connectionPool.isConnectionPoolUp()) {

            String reason = null;
            if (connectionCount >= getDefinition().getMaximumConnectionCount()) {
                // We don't want to make any more that the maximum
                break;
            } else if (connectionCount < getDefinition().getMinimumConnectionCount()) {
                reason = "to achieve minimum of " + getDefinition().getMinimumConnectionCount();
            } else if (connectionPool.getAvailableConnectionCount() < getDefinition().getPrototypeCount()) {
                reason = "to keep " + getDefinition().getPrototypeCount() + " available";
            } else {
                // Nothing to do
                break;
            }

            ProxyConnectionIF freshlyBuiltProxyConnection = null;
            try {
                // If it has been shutdown then we should just stop now.
                if (!connectionPool.isConnectionPoolUp()) {
                    break;
                }
                freshlyBuiltProxyConnection = buildConnection(ConnectionInfoIF.STATUS_AVAILABLE, reason);
                somethingDone = true;
            } catch (Throwable e) {
                log.error("Prototype", e);
            }
}
 

以上就会造成非高峰期时间段内,如果最小值配的比较大,会固定回收时间重新创建一次连接池的最小个数。
而druid没有这个问题:

 


DruidDataSource.shrink()
for (int i = 0; i < poolingCount; ++i) {
            DruidConnectionHolder connection = connections[i];

            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) {
                    break;
                }

                if (checkTime && i < checkCount) {
                    evictConnections[evictCount++] = connection;
                } else if (idleMillis > maxEvictableIdleTimeMillis) {
                    evictConnections[evictCount++] = connection;
                } else if (keepAlive) {
                    keepAliveConnections[keepAliveCount++] = connection;
                }
            } else {
                if (i < checkCount) {
                    evictConnections[evictCount++] = connection;
                } else {
                    break;
                }
            }
        }
 
文章来自个人专栏
性能调优
5 文章 | 1 订阅
0条评论
0 / 1000
请输入你的评论
0
0