我們有個定時任務會每天去請求一下別人提供的webservice來拿到今天簽署的合同的數據,某天早上巡檢服務器的時候,發現定時任務沒有執行,通過dump線程的狀態,發現執行這個定時任務的線程被阻塞住了
阻塞的原因是讀操作的超時時間沒有設置,默認值是-1 導致了客戶端一直等待,然後程序一直阻塞
解決的方法也很簡單,參照jdk的文檔我們可以在啓動參數上加上超時的相關的屬性
-Dsun.net.client.defaultConnectTimeout=10000
-Dsun.net.client.defaultReadTimeout=10000
但是這裏又會遇到一個問題:怎樣確定這些參數生效了,也就是說怎樣模擬服務器端超時的情況,畢竟服務器端不會每次都超時
針對這種情況,我們可以使用iptables來丟棄掉服務器端的相關端口返回的SYN包或者數據包,來模擬連接超時和讀數據超時的情況
我們以百度爲例,模擬weget訪問百度的時候的超時情況
用到的兩個wget的參數:
-T 設置以秒爲單位的超時時間
-t 則是設置重試的次數
DROP掉百度返回的連接的建立連接的握手數據包:
iptables -A INPUT -p tcp -m tcp -s baidu.com --tcp-flags SYN SYN --sport 80 -j DROP
清除掉上一個規則,DROP掉百度返回的傳輸數據的數據包:
因爲iptables的INPUT鏈裏裏只設置了這一條規則,所以直接根據行號爲1來DROP即可
iptables -D INPUT 1
iptables -A INPUT -p tcp -m tcp -s baidu.com --tcp-flags PSH PSH --sport 80 -j DROP
通過這種方式,將我們的定時任務的程序請求的webservice的服務器返回的數據包也做這樣的處理,這樣就可以測試超時之後的情況了
模擬連接超時之後程序的報錯信息:
讀超時:
程序記錄超時之後拋出的異常再做相應的處理即可(比如將這次失敗的定時任務寫入數據庫,下次再繼續嘗試等)不會再阻塞線程影響其他任務的執行了