爲何要設置HTTP timeout?

先看一個不設置timeout形成的線上事故。網絡

一次線上事故

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

但經過日誌能夠肯定的是,該任務線程還在執行中。按照這個定時任務執行的業務邏輯來講,這是不正常的,除了一個HTTP請求外,其它都是不耗時的操做。那麼問題只多是出在HTTP請求之上了。性能

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

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

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

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

總結

一般健壯的程序都是要設置超時時間的,上面的程序沒有設置超時時間,能夠說是一段有缺陷的代碼。但是這樣一段有缺陷的代碼,爲何能在生產環境跑了好久,最後才暴露出問題呢?日誌

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

那麼什麼狀況下,沒有設置超時時間會形成嚴重的影響呢?資源

  1. 與用戶操做相關的接口,若是不設置超時時間,將會出現長時間的無響應,嚴重影響用戶體驗。
  2. 負載很高的系統,由於大量調用耗時長的接口,致使性能急劇降低,從而影響其餘正常的業務。
  3. 某些狀況下,HTTP請求可能永遠都得不到響應,那麼這部分系統資源就一直被佔用,直到系統奔潰。

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

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

TCP在斷開鏈接時,若是出現異常狀況,致使TCP鏈接的一端異常奔潰,好比電源掉電、系統奔潰、網絡故障等。

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

回顧上面的生產故障,它恰好就是處於「半開鏈接」的狀態,致使任務線程一直在等待響應結果。爲了不這種狀況的發生,超時時間是必需要設置的。

相關文章
相關標籤/搜索