HttpClient連接池拋出大量ConnectionPoolTimeoutExceptionTimeoutwaitingforconnection異常排查_第1頁
HttpClient連接池拋出大量ConnectionPoolTimeoutExceptionTimeoutwaitingforconnection異常排查_第2頁
HttpClient連接池拋出大量ConnectionPoolTimeoutExceptionTimeoutwaitingforconnection異常排查_第3頁
HttpClient連接池拋出大量ConnectionPoolTimeoutExceptionTimeoutwaitingforconnection異常排查_第4頁
HttpClient連接池拋出大量ConnectionPoolTimeoutExceptionTimeoutwaitingforconnection異常排查_第5頁
已閱讀5頁,還剩3頁未讀 繼續(xù)免費閱讀

下載本文檔

版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請進(jìn)行舉報或認(rèn)領(lǐng)

文檔簡介

HttpClient 連接池拋出大量ConnectionPoolTimeoutExceptionTimeoutwaitingforconnection 異常排查今天解決了一個 HttpClient 的異常,汗啊,一個HttpClient 使用稍有不慎都會是毀滅級別的啊。這里有之前因為route配置不當(dāng)導(dǎo)致服務(wù)器異常的一個處理: 里面的HttpConnectionManager 實現(xiàn)就是我在這里使用的實現(xiàn)。問題表現(xiàn):tomcat后臺日志發(fā)現(xiàn)大量異常 [plain]viewoutException:Timeoutwaitingforconnection時間一長tomcat就無法繼續(xù)處理其他請求,從假死變成真死了。linux運(yùn)行:[plain]viewplaincopyprint?netstat-n|awk'/^tcp/{++S[$NF]}END{for(ainS)printa,S[a]}' 發(fā)現(xiàn)CLOSE_WAIT 的數(shù)量始終在 400以上,一直沒降過。問題分析:一開始我對我的 HttpClient 使用過程深信不疑,我不認(rèn)為異常是來自這里。所以我開始從 TCP的連接狀態(tài)入手,猜測可能導(dǎo)致異常的原因。 以前經(jīng)常遇到 TIME_WAIT數(shù)過大導(dǎo)致的服務(wù)器異常, 很容易解決,修改下sysctl就ok了。但是這次是 CLOSE_WAIT,是完全不同的概念了。關(guān)于TIME_WAIT 和CLOSE_WAIT 的區(qū)別和異常處理我會單獨起一篇文章詳細(xì)說說我的理解。簡單來說CLOSE_WAIT 數(shù)目過大是由于被動關(guān)閉連接處理不當(dāng)導(dǎo)致的。我說一個場景,服務(wù)器A會去請求服務(wù)器B上面的apache獲取文件資源,正常情況下,如果請求成功,那么在抓取完資源后服務(wù)器 A會主動發(fā)出關(guān)閉連接的請求,這個時候就是主動關(guān)閉連接,連接狀態(tài)我們可以看到是TIME_WAIT。如果一旦發(fā)生異常呢?假設(shè)請求的資源服務(wù)器B上并不存在,那么這個時候就會由服務(wù)器 B發(fā)出關(guān)閉連接的請求,服務(wù)器A就是被動的關(guān)閉了連接, 如果服務(wù)器 A被動關(guān)閉連接之后自己并沒有釋放連接,那就會造成CLOSE_WAIT 的狀態(tài)了。所以很明顯,問題還是處在程序里頭。先看看我的HttpConnectionManager實現(xiàn):[java]viewplaincopyprint?publicclassHttpConnectionManager{privatestaticHttpParamshttpParams;privatestaticClientConnectionManagerconnectionManager;/***最大連接數(shù)*/publicfinalstaticintMAX_TOTAL_CONNECTIONS=800;/***獲取連接的最大等待時間*/publicfinalstaticintWAIT_TIMEOUT=60000;/***每個路由最大連接數(shù)*/publicfinalstaticintMAX_ROUTE_CONNECTIONS=400; /**連接超時時間 */ publicfinalstaticintCONNECT_TIMEOUT=10000; /**時時間 */ publicfinalstaticintREAD_TIMEOUT=10000; static{ httpParams=newBasicHttpParams();

**讀取超設(shè)置最大連接數(shù)ConnManagerParams.setMaxTotalConnections(httpParams,MAX_TOTAL_CONNECTIONS); //設(shè)置獲取連接的最大等待時間ConnManagerParams.setTimeout(httpParams,WAIT_TIMEOUT); //設(shè)置每個路由最大連接數(shù)ConnPerRouteBeanconnPerRoute=newConnPerRouteBean(MAX_ROUTE_CONNECTIONS);ConnManagerParams.setMaxConnectionsPerRoute(httpParams,connPerRoute); //設(shè)置連接超時時間HttpConnectionParams.setConnectionTimeout(httpParams,CONNECT_TIMEOUT); //設(shè)置讀取超時時間HttpConnectionParams.setSoTimeout(httpParams,READ_TIMEOUT);

SchemeRegistryregistry=newSchemeRegistry();

registry.register(newScheme("http",PlainSocketFactory.getSocketFactory(),80)); registry.register(newScheme("https",SSLSocketFactory.getSocketFactory(),443));connectionManager=newThreadSafeClientConnManager(httpParams,registry);

}

publicstaticHttpClientgetHttpClient(){

returnnewDefaultHttpClient(connectionManager,httpParams);

}

}看到?jīng)]

MAX_ROUTE_CONNECTIONS

正好是

400,跟CLOSE_WAIT 非常接近啊,難道是巧合?繼續(xù)往下看。然后看看調(diào)用它的代碼是什么樣的: [java]viewplaincopyprint?publicstaticStringreadNet(StringurlPath){StringBuffersb=newStringBuffer();HttpClientclient=null;InputStreamin=null;InputStreamReaderisr=null;try{client=HttpConnectionManager.getHttpClient();HttpGetget=newHttpGet();get.setURI(newURI(urlPath));HttpResponseresponse=client.execute(get);if(response.getStatusLine().getStatusCode()!=200){ returnnull; }HttpEntityentity=response.getEntity();if(entity!=null){in=entity.getContent();.....}returnsb.toString();}catch(Exceptione){e.printStackTrace();returnnull;}finally{if(isr!=null){try{isr.close();}catch(IOExceptione){e.printStackTrace();}}if(in!=null){try{<spanstyle="color:#ff0000;">in.close();</span>}catch(IOExceptione){e.printStackTrace();}}}}很簡單,就是個遠(yuǎn)程讀取中文頁面的方法。值得注意的是這一段代碼是后來某某同學(xué)加上去的,看上去沒啥問題,是用于非200狀態(tài)的異常處理: [java]viewplaincopyprint?if(response.getStatusLine().getStatusCode()!=200){ returnnull; }代碼本身沒有問題,但是問題是放錯了位置。如果這么寫的話就沒問題:[java]viewplaincopyprint?client=HttpConnectionManager.getHttpClient();HttpGetget=newHttpGet();get.setURI(newURI(urlPath));HttpResponseresponse=client.execute(get);HttpEntityentity=response.getEntity();if(entity!=null){ in=entity.getContent(); .......... }if(response.getStatusLine().getStatusCode()!=200){ returnnull; }returnsb.toString(); 看出毛病了吧。在這篇入門HttpClient4.X升級入門+http連接池使用)里頭我提到了HttpClient4使用我們常用的InputStream.close()來確認(rèn)連接關(guān)閉,前面那種寫法 InputStreamin 根本就不會被賦值,意味著一旦出現(xiàn)非 200的連接,這個連接將永遠(yuǎn)僵死在連接池里頭,太恐怖了。。。所以我們看到 CLOST_WAIT 數(shù)目為400,因為對一個路由的連接已經(jīng)完全被僵死連接占滿了。 。。其實上面那段代碼還有一個沒處理好的地方,異常處理不夠嚴(yán)謹(jǐn),所以最后我把代碼改成了這樣:[java]viewplaincopyprint?publicstaticStringreadNet(StringurlPath){StringBuffersb=newStringBuffer();HttpClientclient=null;InputStreamin=null;InputStreamReaderisr=null;HttpGetget=newHttpGet();try{clientHttpConnectionManager.getHttpClient();get.setURI(newURI(urlPath));HttpResponseresponse=client.execute(get);if(response.getStatusLine().getStatusCode()!=200){ get.abort(); returnnull; } HttpEntityentity=response.getEntity();if(entity!=null){ in=entity.getContent(); ......} returnsb.toString(); } catch(Exceptione) { get.abort();e.printStackTrace(); returnnull;finally { if(isr!=null){ try{ isr.close(); }

}catch(IOExceptione){e.printS

溫馨提示

  • 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
  • 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
  • 5. 人人文庫網(wǎng)僅提供信息存儲空間,僅對用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負(fù)責(zé)。
  • 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請與我們聯(lián)系,我們立即糾正。
  • 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時也不承擔(dān)用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。

評論

0/150

提交評論