溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點(diǎn)擊 登錄注冊 即表示同意《億速云用戶服務(wù)條款》

防止防火墻導(dǎo)致的數(shù)據(jù)庫空閑連接斷開問題的方法

發(fā)布時(shí)間:2021-09-10 18:04:05 來源:億速云 閱讀:380 作者:柒染 欄目:大數(shù)據(jù)

防止防火墻導(dǎo)致的數(shù)據(jù)庫空閑連接斷開問題的方法,相信很多沒有經(jīng)驗(yàn)的人對此束手無策,為此本文總結(jié)了問題出現(xiàn)的原因和解決方法,通過這篇文章希望你能解決這個(gè)問題。

ERROR [com.alibaba.druid.util.JdbcUtils] - close connection error
java.sql.SQLRecoverableException: IO Error: Broken pipe
    at oracle.jdbc.driver.T4CConnection.logoff(T4CConnection.java:556)
    at oracle.jdbc.driver.PhysicalConnection.close(PhysicalConnection.java:3984)
    at com.alibaba.druid.filter.FilterChainImpl.connection_close(FilterChainImpl.java:167)
    at com.alibaba.druid.filter.stat.StatFilter.connection_close(StatFilter.java:254)
    at com.alibaba.druid.filter.FilterChainImpl.connection_close(FilterChainImpl.java:163)
    at com.alibaba.druid.proxy.jdbc.ConnectionProxyImpl.close(ConnectionProxyImpl.java:115)
    at com.alibaba.druid.util.JdbcUtils.close(JdbcUtils.java:79)
    at com.alibaba.druid.pool.DruidDataSource.discardConnection(DruidDataSource.java:965)
    at com.alibaba.druid.pool.DruidDataSource.getConnectionDirect(DruidDataSource.java:932)
    at com.alibaba.druid.filter.FilterChainImpl.dataSource_connect(FilterChainImpl.java:4534)
    at com.alibaba.druid.filter.stat.StatFilter.dataSource_getConnection(StatFilter.java:661)
    at com.alibaba.druid.filter.FilterChainImpl.dataSource_connect(FilterChainImpl.java:4530)
    at com.alibaba.druid.pool.DruidDataSource.getConnection(DruidDataSource.java:884)
    at com.alibaba.druid.pool.DruidDataSource.getConnection(DruidDataSource.java:876)
    at com.alibaba.druid.pool.DruidDataSource.getConnection(DruidDataSource.java:92)

java.net.SocketException: Broken pipe是什么意思呢?
其實(shí)就是與數(shù)據(jù)庫建立的tcp連接因?yàn)槟承┰驍嚅_了,而導(dǎo)致了“管道破裂”。一般數(shù)據(jù)庫連接池會(huì)與數(shù)據(jù)庫保持長連接,在需要的時(shí)候省去建立連接的過程,直接使用,而為什么這些空閑的連接會(huì)被斷開呢?被誰斷開了?

為什么數(shù)據(jù)庫TCP連接會(huì)被斷開?

后來和同事討論的過程中得知?jiǎng)e的項(xiàng)目組也發(fā)生過類似的情況,而他們和這個(gè)項(xiàng)目的共同之處就在于服務(wù)都是在DMZ區(qū),外網(wǎng)可訪問,而數(shù)據(jù)庫在內(nèi)網(wǎng),需要通過防火墻才能訪問到數(shù)據(jù)庫。于是去找負(fù)責(zé)維護(hù)網(wǎng)絡(luò)、防火墻的同事了解,原來防火墻有一個(gè)TCP超時(shí)時(shí)間,目前設(shè)置的為半小時(shí),其意義是,對于通過防火墻的所有TCP連接,如果在半小時(shí)內(nèi)沒有任何活動(dòng),就會(huì)被防火墻拆除,這樣就會(huì)導(dǎo)致連接中斷。在拆除連接時(shí),也不會(huì)向連接的兩端發(fā)送任何數(shù)據(jù)來通知連接已經(jīng)拆除。
 

解決方法

1、調(diào)大防火墻的連接切斷時(shí)長

這是一個(gè)臨時(shí)解決方法,比如將防火墻的連接超時(shí)時(shí)間調(diào)整為8小時(shí),這樣可以盡量避免空閑連接的切斷,但無法完全避免,因?yàn)闊o法預(yù)計(jì)連接會(huì)被空閑多久,如果你的系統(tǒng)不是總有人訪問的話,那么連接遲早會(huì)因?yàn)榭臻e而被切斷,導(dǎo)致一些不可預(yù)計(jì)的問題,而調(diào)大超時(shí)時(shí)間只是緩解而已

2、tcp keepalive功能

tcp的keepalive,其實(shí)就是用來保持tcp連接的,其原理簡單說就是如果一個(gè)TCP連接在指定的時(shí)間內(nèi)沒有任何活動(dòng),會(huì)發(fā)送一個(gè)探測包到連接的對端,檢測連接的對端是否仍然存在,如果對端一定時(shí)間內(nèi)仍沒有對探測的響應(yīng),會(huì)再次發(fā)送探測包,發(fā)送幾次后,仍然沒有響應(yīng),就認(rèn)為連接已經(jīng)失效,關(guān)閉本地連接。
tcp keepalive并不是默認(rèn)開啟的,在開發(fā)程序時(shí)可以設(shè)置tcp keepalive為true,這樣tcp連接在一定時(shí)間內(nèi)沒有任何數(shù)據(jù)報(bào)文傳輸則啟動(dòng)探測,這個(gè)時(shí)間一般是操作系統(tǒng)規(guī)定,Linux系統(tǒng)中可以通過設(shè)置net.ipv4.tcp_keepalive_time來修改,默認(rèn)是7200秒,即2小時(shí)。當(dāng)然在編程時(shí)也可以設(shè)置這個(gè)時(shí)間用于當(dāng)前socket,但是Java的Socket API中好像只有設(shè)置keepalive=true,并沒法設(shè)置tcp_keepalive_time
當(dāng)設(shè)置了tcp keepalive之后,只要tcp探測包發(fā)送的時(shí)間小于防火墻的連接超時(shí)時(shí)間,防火墻就會(huì)檢查到連接中仍然有數(shù)據(jù)傳輸,就不會(huì)斷開這個(gè)連接。

使用JDBC創(chuàng)建的數(shù)據(jù)庫tcp連接是沒有設(shè)置keepalive的,這點(diǎn)可以通過Linux的netstat或ss命令在數(shù)據(jù)庫客戶端(即應(yīng)用端)驗(yàn)證
使用命令netstat -anoss -ano,其中參數(shù)o都是顯示timer計(jì)時(shí)器,timer計(jì)時(shí)器在連接建立狀態(tài)下可以對連接保活計(jì)時(shí)
netstat命令對沒有開啟keepalive的tcp連接顯示為:off (0.00/0/0)
ss命令對沒有keepalive的tcp連接,不會(huì)顯示timer計(jì)時(shí)器

3、Oracle數(shù)據(jù)庫的DCD

Oracle提供了類似tcp keepalive的機(jī)制,也就是DCD(Dead Conneciton Detection)。在$ORACLE_HOME/network/admin/sqlnet.ora文件中增加如下一行:

sqlnet.expire_time=NNN

這里NNN為分鐘數(shù),Oracle數(shù)據(jù)庫會(huì)在會(huì)話IDLE時(shí)間超過這個(gè)指定的時(shí)間時(shí),檢測這個(gè)會(huì)話的對端(即客戶端)是否還有效。避免客戶端由于異常退出,導(dǎo)致會(huì)話一直存在。
同樣的如果DCD的時(shí)間比防火墻切斷空閑連接的時(shí)間短,連接也可以一直保持

4、程序不定時(shí)執(zhí)行查詢

以上幾種方法要么是利用tcp連接keepalive特性,要么是采用數(shù)據(jù)庫端的空閑連接檢測,我們的程序中也可以主動(dòng)做這種心跳檢測

Druid數(shù)據(jù)庫連接池從1.0.28開始,添加了druid.keepAlive屬性,默認(rèn)關(guān)閉
打開druid.keepAlive之后,當(dāng)連接池空閑時(shí),池中的minIdle數(shù)量以內(nèi)的連接,空閑時(shí)間超過minEvictableIdleTimeMillis,則會(huì)執(zhí)行keepAlive操作,即執(zhí)行druid.validationQuery指定的查詢SQL,一般為select * from dual,只要minEvictableIdleTimeMillis設(shè)置的小于防火墻切斷連接時(shí)間,就可以保證當(dāng)連接空閑時(shí)自動(dòng)做?;顧z測,不會(huì)被防火墻切斷

看完上述內(nèi)容,你們掌握防止防火墻導(dǎo)致的數(shù)據(jù)庫空閑連接斷開問題的方法的方法了嗎?如果還想學(xué)到更多技能或想了解更多相關(guān)內(nèi)容,歡迎關(guān)注億速云行業(yè)資訊頻道,感謝各位的閱讀!

向AI問一下細(xì)節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場,如果涉及侵權(quán)請聯(lián)系站長郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI