天天看點

分析Atomikos資料連接配接池源碼,弄清testQuery

分析Atomikos資料連接配接池源碼,弄清testQuery

分類: java2010-03-18 17:19 1163人閱讀 評論(0) 收藏 舉報

作者:fbysss

msn:[email protected] 

blog:blog.csdn.net/fbysss

聲明:本文由fbysss原創,轉載請注明出處

關鍵字:Atomikos資料連接配接池

前言

     Atomikos資料連接配接池,國内有一些應用,但testQuery這個屬性,在網上均是簡單配置,并沒有做特殊說明。通過對Atomikos源碼的分析,發現這裡很有學問。

分析

    我們使用的資料源是AtomikosDataSourceBean,在其doInit方法中, 會調用AtomikosXAConnectionFactory的createPooledConnection方法,該方法會傳回一個AtomikosXAPooledConnection連接配接。

而AtomikosXAPooledConnection是AbstractXPooledConnection的一個子類,AbstractXPooledConnection中,在調用createConnectionProxy時,會調用testUnderlyingConnection方法,用于進行測試。

在AtomikosDataSourceBean的getConnection時,調用connectionPool的borrowConnection方法,進而調用AbstractXPooledConnection中的createConnectionProxy,進而調用testUnderlyingConnection方法。

可以看testUnderlyingConnection中的關鍵代碼,一旦設定了testQuery,每次getConnection的時候,就會連接配接查詢一次(通過jprofiler也可以檢測出來):

[java]  view plain copy

  1. String testQuery = getTestQuery();  
  2.     if (testQuery != null) {  
  3.         Configuration.logDebug ( this + ": testing connection with query [" + testQuery + "]" );  
  4.         Statement stmt = null;  
  5.         try {  
  6.             stmt = connection.createStatement();  
  7.             ResultSet rs = stmt.executeQuery(testQuery);  
  8.             rs.close();  
  9.             stmt.close();  
  10.         } catch ( SQLException e) {  
  11.             throw new CreateConnectionException ( "Error executing testQuery" ,  e );  
  12.         }  
  13.         Configuration.logDebug ( this + ": connection tested OK" );  
  14.     }  
  15.     else {  
  16.         Configuration.logDebug ( this + ": no test query, skipping test" );  
  17.     }  

如果失敗,抛出CreateConnectionException異常。

注意ConnectionPool的borrowConnection方法,其中有一段:

[java]  view plain copy

  1. Iterator it = connections.iterator();  
  2. while ( it.hasNext() && ret == null ) {  
  3.    xpc = (XPooledConnection) it.next();  
  4.    if (xpc.isAvailable()) {  
  5.        try {  
  6.           ret = xpc.createConnectionProxy ( hmsg );  
  7.           Configuration.logDebug( this + ": got connection from pool, new size: " + availableSize() + "/" + totalSize());  
  8.        } catch ( CreateConnectionException ex ) {  
  9.           String msg = this +  ": error creating proxy of connection " + xpc;  
  10.           Configuration.logWarning( msg , ex);  
  11.           it.remove();  
  12.           xpc.destroy();  
  13.        }  
  14.    }  
  15. }  

可以看到,其做的事情,就是周遊連接配接池中的連接配接,一個一個的測試。注意ret = xpc.createConnectionProxy ( hmsg ),一旦該方法抛出CreateConnectionException,就執行it.remove();即将該連接配接從連接配接池中删除。

如果設定了testQuery屬性,每次擷取連接配接時testQuery,能夠保證應用伺服器啟動之後,與資料庫連接配接暫時中斷之後,能夠在下一次請求時,自動重建立立連接配接。

連接配接池是如何自動建立連接配接的呢?其實就是簡單的把無效的連接配接一個一個删掉,直到全部删光了,池裡面沒有有效(poolAvailableSize==0,是根據連接配接的isTerminated狀态來判斷的,而不是是否被重置過)的連接配接了,這樣根據連接配接池的機制,就會調用growPool方法去請求新的連接配接。

但是這樣有性能消耗,而且還不小。對于網站展示部分,不需要實時去檢測,可以考慮采用定時檢測的方法:

n  首先,保證testQuery為空,不配置。

n  建立一個DbPoolMonitorService類,實作ApplicationContextAware接口,這樣應用啟動時,會自動注入ApplicationContext對象。這樣,可以在service中,調用getBean方法,擷取AtomikosDataSourceBean的執行個體,

AtomikosDataSourceBean ads = (AtomikosDataSourceBean)ctx.getBean(“jtaDataSource”);

然後,ads中能夠獲得minPoolSize/maxPoolSize/availablePoolSize/totalPoolSize等屬性,可以做一個界面來監測資料連接配接池的使用和配置情況,甚至可以動态修改這些屬性。

n  做一個定時器,調用一個DbPoolMonitorService定期去手工test。使用SELECT 1 語句即可。

n  注意:try 部分ads.setTestQuery (“SELECT 1”);然後調用BaseDao的執行個體去執行一句話,依然可以使”SELECT 1” 。finally部分ads.setTestQuery(null),以保證不對其他部分造成後續影響。

n  可根據使用者通路量,來決定定時周期,一般10分鐘左右即可。這樣,避免了每次擷取連接配接去做一次檢測操作,又能夠将故障限制在一定時間範圍内。是一個較好的折衷做法。

補充:我們再看 ret = xpc.createConnectionProxy ( hmsg )這句話,如果這時候DB和WebAppServer的網絡鍊路已經正常,DB正常運作,傳回将不是空,會退出循環。這樣,如果連接配接池中的連接配接是多個,則隻會生成1個新的連接配接,如果要保證連接配接池機制的效果,需要在寫監控程式的時候,去取得所有有效連接配接,循環test。

分享到:

  • 上一篇:openfire安裝備忘
  • 下一篇:SVN分支與合并透析