咱們你們在作J2EE項目開發的時候,都會用到Application Server,而後配置Connection Pool,Data Source,但不知道你們有沒有留意到,其實咱們絕大部分的應用用的都是Apache的DBCP機制。
JES,Weblogic,JBoss等等的大型App Server,其中一個好處就是提供了Admin Console,讓配置作起來就像傻瓜式的,Step By Step就能夠了,下面舉個用Tomcat的應用例子,深刻一點探討DBCP的配置都作了些什麼。(固然得配置Server.xml了,可是其實JES和Weblogic等等的大型App Server,也是能夠一樣修改Server.xml或這Domain.xml來達到同一目的的,只不過有了Admin Console,你們容易避免犯錯,但其實我以爲,要深刻了解一個App Server,避免不了深刻了解配置文件裏面的內容)。
當使用DBCP(一般咱們都是用Oracle的了)時候,不知道你們有沒有遇到一個狀況,當數據庫鏈接由於某種緣由斷掉(有可能時網絡問題,致使App Server跑了一天後,次日再×××上爆錯誤),再從Connection Pool中獲取鏈接而又不作Validate,這時候取得的Connection實際上已是無效的了,從而致使程序一跑,立刻爆Connect Reset錯誤。
其實只要你瞭解一下DBCP的運做機制和相關屬性的話,這個問題就很容易避免了。
DBCP使用Apache的ObjectPool做爲Connection Pool的實現,在構造GenericObjectPool的時候,會生成一個Inner Class Evictor,實現Runnable的接口。若是屬性_timeBetweenEvictionRunsMillis > 0,每過_timeBetweenEvictionRunsMillis毫秒後Evictor會調用evict method,檢查Object的idle time是否大於屬性_minEvictableIdleTimeMillis毫秒(若是_minEvictableIdleTimeMillis設置爲<=0則忽略,使用default value 30分鐘),若是是則銷燬該Object,不然就激活並進行Validate,而後調用ensureMinIdle method檢查確保Connection Pool中的Object個數不小於屬性_minIdle。在調用returnObject method把Object放回ObjectPool時候,須要檢查該Object是否有效,而後調用PoolableObjectFactory的passivateObject method使Object處於inactive狀態,再檢查ObjectPool中的對象個數是否小於屬性_maxIdle,是則能夠把該Object放回到ObjectPool,不然銷燬此Object。
除此以外,還有幾個比較重要的屬性,_testOnBorrow,_testOnReturn,_testWhileIdle,這些屬性的意思是取得,返回對象,空閒時候是否進行Valiadte,檢查對象是否有效。默認都爲False,只有把這些屬性設爲True,再提供_validationQuery語句就能夠保證DBCP始終有效了,例如,Oracle中就徹底可使用select 1 from dual來進行驗證,這裏要注意的是,DBCP要求_validationQuery語句查詢的Result Set必須爲非空。
在Tomcat的Server.xml,咱們能夠看看下面的這個例子:
<Resource name="lda/raw"
type="javax.sql.DataSource"
password="lda_master"
driverClassName="oracle.jdbc.driver.OracleDriver"
maxIdle="30" minIdle="2" maxWait="60000" maxActive="1000"
testOnBorrow="true" testWhileIdle="true" validationQuery="select 1 from dual"
username="lda_master" url="jdbc:oracle:thin:@192.160.100.107:15537:lcststd"/>
這樣一來,就可以解決Connect Reset的問題了。剛纔說了,其實不少App Server都會有相應的配置地方,只是大型的服務器正好提供了Admin Console,上面能夠顯式的配置Connection Pool,也有明顯的屬性選擇,這裏就不一一詳述了,都是眼見的功夫。