一. 背景
17年公司有個項目組在南京作項目的時候,開發框架用的是spring boot ,數據庫鏈接池用的是druid,但總是遇到socket read timeout的錯誤,不得已放棄了druid而改用了tomcat數據庫鏈接池,問題獲得解決,也就沒有深刻找druid的緣由了(按理說牛掰的druid不該該啊)。html
時間到了18年,我所在的項目組到了安徽馬鞍山,其中接口平臺項目(SpringBoot動態配置多數據源-從數據庫讀取鏈接信息)竟然也遇到了這個問題(這個項目已在多個地市正常使用,難道是因爲馬鞍山跟南京捱得太近被傳染了嗎!),程序動不動就阻塞幾十分鐘(時間不定),形成客戶端長時間等待來一個報錯消息。此次咱們沒有迴避這個問題,不管如何要搞定它。spring
二. 解決問題
巧的是咱們的合做公司,他們的項目已經上線一年多了,常常是隔個幾天也遇到這個問題,他們的作法是重啓整個項目(這樣客戶體驗真的好嗎???不能苟同啊)。我先是調試了程序,發現就是在運行connection = druidDataSource.getConnection();這句代碼(從數據庫鏈接池取一個鏈接)的時候,程序就阻塞在這裏不動了,我把問題拿到網上搜索了一番,初步懷疑是下面兩個緣由之一:sql
網絡抖動(網絡不穩定、閃斷)形成的(由於我在使用svn同步項目的時候,常常因爲網絡問題同步失敗);
防火牆把個人socket鏈接斷開了(由於個人應用服務器和數據庫服務器之間有一個防火牆)。
針對緣由1,我按照網上的說法(https://blog.csdn.net/supper10090/article/details/79622397?utm_source=blogxgwz3)作了配置,惋惜問題還健在。因此我就懷疑是緣由2(https://www.2cto.com/database/201505/402016.html)了,找來防火牆的安裝公司一查,人家說並無這個配置。。。大寫的尷尬。一不當心進入了小小的迷茫。。。在我靜一靜以後,找到了這篇文章:https://www.cnblogs.com/trust-freedom/p/6992952.html,在文章的最後,發現了契機,各位小夥伴本身去讀讀吧,能學到很多東西!數據庫
最終,我結合緣由1與2的解決方式,得出問題解決辦法:tomcat
第一步:druidDataSource.setConnectionProperties("oracle.net.CONNECT_TIMEOUT=6000;oracle.jdbc.ReadTimeout=30000"); //後面的ReadTimeout單位也是毫秒,不要設置的過短,不然有些sql執行時間原本就長,報錯會影響正常使用服務器
第二步:網絡
druidDataSource.setMinEvictableIdleTimeMillis(180000); //配置一個鏈接在池中最小生存的時間,單位是毫秒,這裏配置爲3分鐘180000
druidDataSource.setKeepAlive(true); //打開druid.keepAlive以後,當鏈接池空閒時,池中的minIdle數量之內的鏈接,空閒時間超過minEvictableIdleTimeMillis,則會執行keepAlive操做,即執行druid.validationQuery指定的查詢SQL,通常爲select * from dual,只要minEvictableIdleTimeMillis設置的小於防火牆切斷鏈接時間,就能夠保證當鏈接空閒時自動作保活檢測,不會被防火牆切斷oracle
socket超時致使程序阻塞的問題再也沒有出現!以上我是經過代碼實現的,你們能夠經過配置文件實現。框架
PS: 對於直接把數據源寫死在項目中,這個問題出現的頻率不高(但會出現),但因爲個人項目數據源是動態配置的,這個問題出現的特別頻繁(爲何這麼頻繁呢?我也不知道了)
dom