Apache HttpClient使用之阻塞陷阱

 

前言:
  以前作個一個數據同步的定時程序. 其內部集成了某電商的SDK(簡單的Apache Httpclient4.x封裝)+Spring Quartz來實現. 本來覺得簡單輕鬆, 喝杯咖啡就高枕無憂的事. 沒想到該程序並不買帳, work時間一久, 竟頻頻罷工還賣萌. 我勒個過去, 套用一句流行的話說: 真是青春日了狗了.html

相關文章的連接:
  第三方SDK(Rest API)和Jaskson的巧用 
  quartz和定時任務執行 java

現象回顧:
  最近發現數據同步遲滯了, 因而立馬去check下服務進程. 發現進程活得好好的(白白胖胖那種), 稍鬆了口氣, 看來沒有OOM, 以及被誤殺. 但日誌沒有滾動, 也就是說日誌很久沒更新了. 這是啥回事呢?
  難道說worker線程退出江湖了, 死鎖大爺又來踢館了, 仍是說路遇張麻子(此山是我開, 此樹是我栽)?
  使用jstack -l <pid>, 連續屢次採樣thread dump. 發現worker線程一直在read socket上等待.
  
  大機率上來說, 進程是被堵塞了於此了.
  固然於此同時, 還發現了被動關閉, 哎呀媽呀, 問題還真很多.  
  程序員

問題分析:
  簡單解讀下某電商平臺的SDK代碼片斷:apache

public HttpResponse get(String method, HashMap<String,String> parames) throws Exception{
    String url = apiEntry + getParamStr(method, parames);

    HttpClient client = new DefaultHttpClient();
    HttpGet request = new HttpGet(url);
    request.addHeader("User-Agent", DefaultUserAgent);
    HttpResponse response = client.execute(request);

    return response;
}

  代碼很簡潔, 也能很好地work, 那究竟哪一個環節有疏忽呢?
  因爲問題都出如今Apache Httpclient 4.x上, 所以咱們先看看網上是否也有相似的案例場景.
  • socket阻塞
  參考了相關文章, 基本承認博文<<Apache HttpClient 沒有設置time out致使應用長時間阻塞的問題>>中的說法: socket沒有設置超時選項致使.
  具體解讀, 能夠理解爲服務端對端不迴應, 或者因網絡異常, 致使socket一直阻塞於讀. Apache HttpClient默認設置的socket爲SO_TIMEOUT爲0, 既無限等待.
  結合之上的代碼分析, 確實忽視了超時設定, 陷入了Apache HttpClient隱藏很深的坑中. ^_^!
  解決方案是:爲對應的httpclient設置超時便可.api

httpClient = new DefaultHttpClient(); 
httpClient.getParams().setIntParameter(CoreConnectionPNames.SO_TIMEOUT, 2000); 
httpClient.getParams().setIntParameter(CoreConnectionPNames.CONNECTION_TIMEOUT, 2000); 

  這樣阻塞的問題就能夠暫時告一段落了.
  • 句柄泄露(CLOSE_WAIT半鏈接關閉)
  一樣參考了博文: <<HttpClient容易忽視的細節——鏈接關閉>>與<<HttpClient 與 Close_Wait>>.
  按apache httpclient的設計理念, 當http client 處於高併發時, 默認機制致使的CLOSE_WAIT會影響服務的可用性.
  對比之上的代碼, 確實沒有找到主動關閉鏈接的代碼.
  Apache HttpClient自己變更多, 接口又雜, 以致每一個版本的解決方案又有所不一樣, 有些讓人眼花繚亂.
  比較一致的解決方式是,在處理完單個請求後, 調用以下清理代碼:微信

httpmethod.releaseConnection();
client.getConnectionManager().shutdown();

  但無論怎麼說, Apache HttpClient 4.x的關閉機制, 仍是值得大書特書的, 這邊顯得簡略, 但願之後有機會能深刻研究.網絡

總結:
  此次算是事出有因, 問題出在了第三方的SDK上. 因而可知, 對第三方的SDK的使用, 仍是得留個心眼. 實際上, 不少平臺的SDK, 每每是實習生所編寫的, 且沒有通過嚴苛的測試, 因此質量不免有些良莠不齊.
  不管是SDK的使用者, 仍是SDK的開發者, 都須要精益求精, 在質量(性能和穩定), 用戶體驗(易用/易理解)上作足功夫了, 這也是程序員的軟實力之一.併發

後記:
  本文對Apache HttpClient 4.x的阻塞陷阱作了介紹, 展示了其案例表現, 以及解決方案. 但缺乏對Apache HttpClient深刻分析, 以及使用方式推薦. 但願本身能有機會, 好好地整理一番.socket

 公衆號&遊戲站點:
  我的微信公衆號: 木目的H5遊戲世界
  
高併發

  我的遊戲做品集站點(尚在建設中...): www.mmxfgame.com,  也可直接ip訪問http://120.26.221.54/.

相關文章
相關標籤/搜索