天天看點

Apache HttpClient 沒有設定time out導緻應用長時間阻塞的問題

update 2014-5-18:

今天又處理了一個httpclient阻塞的問題,還是socket read沒有逾時設定。

用jstack -l pid 得到線程的調用棧,每隔一段時間執行一次,對比三次的thread dump結果,發現有一個線程是三次執行的位置一樣的,說明它是阻塞在這裡了:

業務的邏輯是接收一個jms消息,再http請求調用得到處理結果。在http請求處阻塞了,導緻後面的消息都不能消息。

----------------------------------------------

現在的對外接口一般都是http + json的,因為簡單,語言無關。

apache httpclient應該是最常用的java http元件了。這貨有個坑爹的地方,apache httpclient如果對方不回應,或者網絡原因不傳回了,那麼httpclient會一直阻塞。這種情況在公網可能比較容易碰到。在内網時,也有一次因為一台中轉的nginx挂掉而導緻hessian請求長時間阻塞。

因為http client預設的so_timeout是0,即一直等待。

這個問題,在幫同僚查找問題時碰到好幾次了,可能是大家潛意識裡認為http請求是即時的,失敗的話也很快傳回。

apache httpclient的示例也沒提到要設定timeout,這也是比較坑爹的地方。一個庫如果沒有預設阻止使用者去範錯誤,那麼你也應當在文檔,示例代碼裡提醒使用者不要範錯誤。

有三個可以設定time out 的參數:

so_linger最好不要設定,可能會坑死人。參考:

http://unliminet.blog.51cto.com/380895/346686

http://stackoverflow.com/questions/3757289/tcp-option-so-linger-zero-when-its-required