為什么要設置HTTP timeout?


先看一個不設置timeout造成的線上事故。

一次線上事故

有一次生產上的一個服務出了點故障,一個原本每5分鍾執行一次的定時任務突然不執行了。第一反應是任務執行報錯,查看日志,卻沒有找到任何異常報錯信息。

但通過日志可以確定的是,該任務線程還在執行中。按照這個定時任務執行的業務邏輯來說,這是不正常的,除了一個HTTP請求外,其它都是不耗時的操作。那么問題只可能是出在HTTP請求之上了。

通過jstack查看線程的堆棧信息,確定了就是HTTP請求的問題了。

從上面的堆棧信息,可以看到該定時任務線程處於“RUNNABLE”狀態,在JVM中"RUNNABLE"表示線程運行在JVM中,但在等待操作系統的其他資源。從堆棧信息中看到,該線程正在進行Socket的讀取操作。

從發現任務執行,到定位到這里,已經過去十幾分鍾了,Socket一直在讀取等待中,說明沒有設置超時時間,或者說超時時間沒有生效。

回頭看程序代碼,發現這個服務的HTTP工具類沒有設置HTTP timeout。隨后,趕緊設置timeout。

總結

通常健壯的程序都是要設置超時時間的,上面的程序沒有設置超時時間,可以說是一段有缺陷的代碼。可是這樣一段有缺陷的代碼,為什么能在生產環境跑了很久,最后才暴露出問題呢?

我想主要是因為,即使你不設置超時時間,在正常情況下,一個HTTP請求總是會返回結果,即使可能會耗時較長。對於一個負載不高的服務來說,潛在的問題沒有暴露出來。

那么什么情況下,沒有設置超時時間會造成嚴重的影響呢?

  1. 與用戶操作相關的接口,如果不設置超時時間,將會出現長時間的無響應,嚴重影響用戶體驗。
  2. 負載很高的系統,因為大量調用耗時長的接口,導致性能急劇下降,從而影響其他正常的業務。
  3. 某些情況下,HTTP請求可能永遠都得不到響應,那么這部分系統資源就一直被占用,直到系統奔潰。

前面兩種情況比較好理解,問題是什么情況下,HTTP請求會永遠得不到響應呢?

了解計算機網絡應該都知道TCP建立連接時的三次握手和斷開連接時的四次揮手。

TCP在斷開連接時,如果出現異常情況,導致TCP連接的一端異常奔潰,比如電源掉電、系統奔潰、網絡故障等。

在這種情況下,TCP的斷開操作不會通知對端程序,從而導致對端程序一直處於等待狀態,Socket不能及時釋放。這種一端開着,一端已經關閉的狀態,被稱為半開連接。

回顧上面的生產故障,它剛好就是處於“半開連接”的狀態,導致任務線程一直在等待響應結果。為了避免這種情況的發生,超時時間是必須要設置的。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM