說明:在解決問題的時候,參考了以下文章
http://blog.csdn.net/wuqingyong/archive/2006/09/07/1187293.aspx
http://jayenho.blog.51cto.com/37194/91556
作為對問題的總結,特寫本文。
最近總是遇到tomcat的log File報Connection reset的問題,使用的是JNDI的方式來使用DataSource。
Apache Tomcat使用org.apache.naming.factory.DbcpDataSourceFactory作為默認的數據源工廠。
Tomcat的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"/>
這樣的話,就可以避免產生Connection Reset的錯誤了.
這樣一來,就能夠解決Connect Reset的問題了。剛才說了,其實很多App Server都會有相應的配置地方,只是大型的服務器正好提供了Admin Console,上面可以顯式的配置Connection Pool,也有明顯的屬性選擇,這里就不一一詳述了,都是眼見的功夫。