1. 首先,出現(xiàn) Broken pipe 的錯(cuò)誤不是因連接超時(shí)所致,這個(gè)錯(cuò)誤只有在Linux下多發(fā),就是在高并發(fā)的情況下,網(wǎng)絡(luò)資源不足的情況出現(xiàn)的, 會發(fā)送SIGPIPE信號,LINUX下默認(rèn)程序退出的,具體解決辦法目前還未找到合適的,有的說法是在Linux的環(huán)境變量中設(shè)置: _JAVA_SR_SIGNUM = 12 基本就可以解決,但經(jīng)測試結(jié)果看并未解決。對于該問題持續(xù)關(guān)注中。
2. 之后,Broken pipe 問題未徹底解決,那么對于DBCP連接池只好對一些作廢的連接要進(jìn)行強(qiáng)制回收,若這里不做強(qiáng)制回收的話,最終也就會導(dǎo)致 pool exhausted 了,所以這一步一定要加上保護(hù)。配置如下:
- #### 是否在自動(dòng)回收超時(shí)連接的時(shí)候打印連接的超時(shí)錯(cuò)誤
- dbcp.logAbandoned=true
- #### 是否自動(dòng)回收超時(shí)連接
- dbcp.removeAbandoned=true
- #### 超時(shí)時(shí)間(以秒數(shù)為單位)
- dbcp.removeAbandonedTimeout=150
3. 對于DB的 wait_timeout 空閑連接時(shí)間設(shè)置,在超過該時(shí)間值的連接,DB端會強(qiáng)行關(guān)閉,經(jīng)測試結(jié)果,即使DB強(qiáng)行關(guān)閉了空閑連接,對于DBCP而言在獲取該連接時(shí)無法激活該連接,會自動(dòng)廢棄該連接,重新從池中獲取空閑連接或是重新創(chuàng)建連接,從源代碼上看,這個(gè)自動(dòng)完成的激活邏輯并不需要配置任何參數(shù),是DBCP的默認(rèn)操作。故對于網(wǎng)上的不少說連接池時(shí)間配置與DB不協(xié)調(diào)會導(dǎo)致 Broken pipe 的說法是錯(cuò)誤,至少對于DBCP是不會出現(xiàn)該問題,也許C3P0是這樣。
不過對于連接池的優(yōu)化而言,本來就在池里空閑的連接被DB給強(qiáng)行關(guān)閉也不件好事,這里可以組合以下幾個(gè)配置解決該問題:
java 代碼
- # false : 空閑時(shí)是否驗(yàn)證, 若不通過斷掉連接, 前提是空閑對象回收器開啟狀態(tài)
- dbcp.testWhileIdle = true
- # -1 : 以毫秒表示空閑對象回收器由運(yùn)行間隔。值為負(fù)數(shù)時(shí)表示不運(yùn)行空閑對象回收器
- # 若需要回收, 該值最好小于 minEvictableIdleTimeMillis 值
- dbcp.timeBetweenEvictionRunsMillis = 300000
- # 1000*60*30 : 被空閑對象回收器回收前在池中保持空閑狀態(tài)的最小時(shí)間, 毫秒表示
- # 若需要回收, 該值最好小于DB中的 wait_timeout 值
- dbcp.minEvictableIdleTimeMillis = 320000
4. 最后,還有一個(gè)就是DBCP的maxWait參數(shù),該參數(shù)值不宜配置太大,因?yàn)樵诔叵臐M時(shí),該會掛起線程等待一段時(shí)間看看是否能獲得連接,一般到池耗盡的可能很少,若真要耗盡了一般也是并發(fā)太大,若此時(shí)再掛線程的話,也就是同時(shí)掛起了Server的線程,若到Server線程也掛滿了,不光是訪問DB的線程無法訪問,就連訪問普通頁面也無法訪問了。結(jié)果是更糕。
這樣,通過以上幾個(gè)配置,DBCP連接池的連接泄漏應(yīng)該不會發(fā)生了(當(dāng)然除了程序上的連接泄漏),不過對于并發(fā)大時(shí)Linux上的BrokenPipe 問題最好能徹底解決。但是對于并發(fā)量大時(shí),Tomcat或JBoss的服務(wù)線程會掛起的原因還是未最終定位到原因,目前解決了DBCP的影響后,估計(jì)問題可能會是出現(xiàn)在 mod_jk 與 Tomcat 的連接上了,最終原因也有可能是 broken pipe 所致。關(guān)注與解決中……
2.ibatis使用dbcp連接數(shù)據(jù)庫
一、建立數(shù)據(jù)表(我用的是oracle 9.2.0.1)
prompt PL/SQL Developer import file
prompt Created on 2007年5月24日 by Administrator
set feedback off
set define off
prompt Dropping T_ACCOUNT...
dro p table T_ACCOUNT cascade constraints; (注意:這里由于ISP限制上傳drop,所以加了一個(gè)空格)
prompt Creating T_ACCOUNT...
create table T_ACCOUNT
(
ID NUMBER not null,
FIRSTNAME VARCHAR2(2),
LASTNAME VARCHAR2(4),
EMAILADDRESS VARCHAR2(60)
)
;
alter table T_ACCOUNT
add constraint PK_T_ACCOUNT primary key (ID);
prompt Disabling triggers for T_ACCOUNT...
alter table T_ACCOUNT disable all triggers;
prompt Loading T_ACCOUNT...
insert into T_ACCOUNT (ID, FIRSTNAME, LASTNAME, EMAILADDRESS)
values (1, '王', '三旗', 'E_wsq@msn.com');
insert into T_ACCOUNT (ID, FIRSTNAME, LASTNAME, EMAILADDRESS)
values (2, '冷', '宮主', 'E_wsq@msn.com');
commit;
prompt 2 records loaded
prompt Enabling triggers for T_ACCOUNT...
alter table T_ACCOUNT enable all triggers;
set feedback on
set define on
prompt Done.
二、在工程中加入
commons-dbcp-1.2.2.jar
commons-pool-1.3.jar
ibatis-common-2.jar
ibatis-dao-2.jar
ibatis-sqlmap-2.jar
三、編寫如下屬性文件
jdbc.properties
#連接設(shè)置
driverClassName=oracle.jdbc.driver.OracleDriver
url=jdbc:oracle:thin:@90.0.12.112:1521:ORCL
username=gzfee
password=1
#<!-- 初始化連接 -->
initialSize=10
#<!-- 最大空閑連接 -->
maxIdle=20
#<!-- 最小空閑連接 -->
minIdle=5
#最大連接數(shù)量
maxActive=50
#是否在自動(dòng)回收超時(shí)連接的時(shí)候打印連接的超時(shí)錯(cuò)誤
logAbandoned=true
#是否自動(dòng)回收超時(shí)連接
removeAbandoned=true
#超時(shí)時(shí)間(以秒數(shù)為單位)
removeAbandonedTimeout=180
#<!-- 超時(shí)等待時(shí)間以毫秒為單位 6000毫秒/1000等于60秒 -->
maxWait=1000
四、將上面建立的屬性文件放入classes下
注:如果是用main類測試則應(yīng)在工程目錄的classes下,如果是站點(diǎn)測試則在web-inf的classes目錄下
五、寫ibatis與DBCP的關(guān)系文件
DBCPSqlMapConfig.xml
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE sqlMapConfig
PUBLIC "-//ibatis.apache.org//DTD SQL Map Config 2.0//EN"
"http://ibatis.apache.org/dtd/sql-map-config-2.dtd">
<sqlMapConfig>
<properties resource ="jdbc.properties"/>
<transactionManager type ="JDBC">
<dataSource type ="DBCP">
<property name ="JDBC.Driver" value ="${driverClassName}"/>
<property name ="JDBC.ConnectionURL" value ="${url}" />
<property name ="JDBC.Username" value ="${username}" />
<property name ="JDBC.Password" value ="${password}" />
<property name ="Pool.MaximumWait" value ="30000" />
<property name ="Pool.ValidationQuery" value ="select sysdate from dual" />
<property name ="Pool.LogAbandoned" value ="true" />
<property name ="Pool.RemoveAbandonedTimeout" value ="1800000" />
<property name ="Pool.RemoveAbandoned" value ="true" />
</dataSource>
</transactionManager>
<sqlMap resource="com/mydomain/data/Account.xml"/> (注:這里對應(yīng)表映射)
</sqlMapConfig>
六、寫數(shù)據(jù)表映射文件
Account.xml
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE sqlMap
PUBLIC "-//ibatis.apache.org//DTD SQL Map 2.0//EN"
"http://ibatis.apache.org/dtd/sql-map-2.dtd">
<sqlMap namespace="Account">
<!-- Use type aliases to avoid typing the full classname every time. -->
<typeAlias alias="Account" type="com.mydomain.domain.Account"/>
<!-- Result maps describe the mapping between the columns returned
from a query, and the class properties. A result map isn't
necessary if the columns (or aliases) match to the properties
exactly. -->
<resultMap id="AccountResult" class="Account">
<result property="id" column="id"/>
<result property="firstName" column="firstName"/>
<result property="lastName" column="lastName"/>
<result property="emailAddress" column="emailAddress"/>
</resultMap>
<!-- Select with no parameters using the result map for Account class. -->
<select id="selectAllAccounts" resultMap="AccountResult">
select * from T_ACCOUNT
</select>
<!-- A simpler select example without the result map. Note the
aliases to match the properties of the target result class. -->
<select id="selectAccountById" parameterClass="int" resultClass="Account">
select
id as id,
firstName as firstName,
lastName as lastName,
emailAddress as emailAddress
from T_ACCOUNT
where id = #id#
</select>
<!-- Insert example, using the Account parameter class -->
<insert id="insertAccount" parameterClass="Account">
insert into T_ACCOUNT (
id,
firstName,
lastName,
emailAddress
values (
#id#, #firstName#, #lastName#, #emailAddress#
)
</insert>
<!-- Update example, using the Account parameter class -->
<update id="updateAccount" parameterClass="Account">
update T_ACCOUNT set
firstName = #firstName#,
lastName = #lastName#,
emailAddress = #emailAddress#
where
id = #id#
</update>
<!-- Delete example, using an integer as the parameter class -->
<delete id="deleteAccountById" parameterClass="int">
delet e from T_ACCOUNT where id = #id# (注意:這里由于ISP限制上傳delete,所以加了一個(gè)空格)
</delete>
</sqlMap>