淺析mybatis源碼(二)鏈接池

這篇主要看的是mybatis對於數據庫鏈接池的實現。實現類爲org.apache.ibatis.datasource.pooled包下的PooledDataSource類。 數據庫鏈接池的代碼並不難,關鍵在於理解他的鏈接和釋放的策略。java

鏈接池參數

protected int poolMaximumActiveConnections = 10;//最大存活鏈接數,有請求的鏈接
  protected int poolMaximumIdleConnections = 5;//最大空閒鏈接數,就是沒有處理請求的鏈接
  protected int poolMaximumCheckoutTime = 20000;//強制收回時間
  protected int poolTimeToWait = 20000;//獲取鏈接等待時間
  protected int poolMaximumLocalBadConnectionTolerance = 3;//若是獲取到的是一個壞的鏈接,那麼從新獲取一個新的鏈接,次數最多爲 poolMaximumIdleConnections + poolMaximumLocalBadConnectionTolerance
  protected String poolPingQuery = "NO PING QUERY SET";//心跳查詢sql
  protected boolean poolPingEnabled;//容許心跳查詢
  protected int poolPingConnectionsNotUsedFor;//執行心跳查詢頻率

還有一個屬性poolState用來存放數據庫狀態,來看看狀態類PoolState的屬性sql

鏈接池狀態類屬性

protected final List<PooledConnection> idleConnections = new ArrayList<PooledConnection>();//空閒鏈接列表
  protected final List<PooledConnection> activeConnections = new ArrayList<PooledConnection>();//活躍鏈接列表
  protected long requestCount = 0;//獲取到有效鏈接的次數
  protected long accumulatedRequestTime = 0;//獲取到有效鏈接的總耗時
  protected long accumulatedCheckoutTime = 0;//收回鏈接的總耗時
  protected long claimedOverdueConnectionCount = 0;//強制獲取鏈接次數
  protected long accumulatedCheckoutTimeOfOverdueConnections = 0;//強制收回鏈接佔用時間之和
  protected long accumulatedWaitTime = 0;//等待鏈接收回時間之和
  protected long hadToWaitCount = 0;//等待的請求數量
  protected long badConnectionCount = 0;//壞鏈接數量

鏈接池最重要的兩個方法莫過於獲取鏈接和釋放鏈接。在池中pop和push則須要根據鏈接池參數來進行決策。而每次動做都會更新響應的狀態。接下來看看pop和push的具體策略數據庫

pop策略

push策略

因爲變量名太長,沒法在流程圖中標明鏈接池狀態是如何變化的。有興趣的能夠看下源碼。看下源碼就能對那些狀態變量有了更清晰的認識。apache

PooledConnection類

怎麼才能在close的時候不是真的close而是調用pushConnection呢?有一種方式就是使用代理。靜態代理相對麻煩,須要把除了close方法外全部方法委託給真實的Connection類。mybatis使用的是動態代理。mybatis

@Override
  public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
    String methodName = method.getName();
    if (CLOSE.hashCode() == methodName.hashCode() && CLOSE.equals(methodName)) {//如果close方法
      dataSource.pushConnection(this);
      return null;
    } else {
      try {
        if (!Object.class.equals(method.getDeclaringClass())) {//若是不是Object定義的那些方法
          checkConnection();//檢查鏈接是否有效
        }
        return method.invoke(realConnection, args);//其餘方法委託給realConnection
      } catch (Throwable t) {
        throw ExceptionUtil.unwrapThrowable(t);
      }
    }
  }

總結

鏈接池的代碼並不難,可是能夠給咱們一個啓發,當使用mybatis鏈接池遇到問題時或者須要優化、監控等,能夠獲取到poolState的各個屬性,來作一些參考。ide

相關文章
相關標籤/搜索