HttpClient如何 關閉連接(轉)


ava代碼

  1. HttpClient client = new HttpClient();   
  2. HttpMethod method = new GetMethod("http://www.apache.org");   
  3. try {   
  4.   client.executeMethod(method);   
  5.   byte[] responseBody = null;   
  6.      
  7.   responseBody = method.getResponseBody();   
  8.      
  9. catch (HttpException e) {   
  10.   // TODO Auto-generated catch block   
  11.   e.printStackTrace();   
  12. catch (IOException e) {   
  13.   // TODO Auto-generated catch block   
  14.   e.printStackTrace();   
  15. }finally{   
  16.   method.releaseConnection();   
  17.      
  18. }  


大部分人使用HttpClient都是使用類似上面的代碼,因為Apache官方例子就是如此。但在使用HttpClient會發現如果不斷循環發送大量請求到服務器會導致APACHE服務器的連接被占滿,后續的請求便排隊等待,程序陷入“假死”狀態。

Java代碼
  1. Timeout 30  
  2. KeepAlive On   #表示服務器端不會主動關閉鏈接   
  3. MaxKeepAliveRequests 100  
  4. KeepAliveTimeout 180   

因此這樣的配置就會導致每個鏈接至少要過180S才會被釋放,這樣在大量請求訪問時就必然會造成連接被占滿,請求等待的情況。
在 通過DEBUG后發現HttpClient在method.releaseConnection()后並沒有把連接關閉,這個方法只是將 連接返回給 connection manager。如果使用HttpClient client = new HttpClient()實例化一個HttpClient connection manager默認實現是使用SimpleHttpConnectionManager。SimpleHttpConnectionManager有個構 造函數如下
Java代碼
  1.   
  2. public SimpleHttpConnectionManager(boolean alwaysClose) {   
  3.     super();   
  4.     this.alwaysClose = alwaysClose;   
  5. }  

看 方法注釋我們就可以看到如果alwaysClose設為true在鏈接釋放之后connection manager 就會關閉鏈。在我們HttpClient client = new HttpClient()這樣實例化一個client時connection manager是這樣被實例化的
Java代碼
  1. this.httpConnectionManager = new SimpleHttpConnectionManager();  

因此alwaysClose默認是false,connection是不會被主動關閉的,因此我們就有了一個客戶端關閉鏈接的方法。
方法一:
把事例代碼中的第一行實例化代碼改為如下即可,在method.releaseConnection();之后connection manager會關閉connection 。
Java代碼
  1. HttpClient client = new HttpClient(new HttpClientParams(),new SimpleHttpConnectionManager(true) );  

方法二:
實例化代碼使用:HttpClient client = new HttpClient();
在method.releaseConnection();之后加上
Java代碼
  1. ((SimpleHttpConnectionManager)client.getHttpConnectionManager()).shutdown();  

shutdown源代碼很簡單,看了一目了然
Java代碼
  1. public void shutdown() {   
  2.     httpConnection.close();   
  3. }  

方法三:
實例化代碼使用:HttpClient client = new HttpClient();
在method.releaseConnection();之后加上
client.getHttpConnectionManager().closeIdleConnections(0);此方法源碼代碼如下:
Java代碼
  1. public void closeIdleConnections(long idleTimeout) {   
  2.     long maxIdleTime = System.currentTimeMillis() - idleTimeout;   
  3.     if (idleStartTime <= maxIdleTime) {   
  4.         httpConnection.close();   
  5.     }   
  6. }  

將idleTimeout設為0可以確保鏈接被關閉。
以上這三種方法都是有客戶端主動關閉TCP鏈接的方法。下面再介紹由服務器端自動關閉鏈接的方法。
方法四:
代碼實現很簡單,所有代碼就和最上面的事例代碼一樣。只需要在HttpMethod method = new GetMethod("http://www.apache.org");加上一行HTTP頭的設置即可
Java代碼
  1. method.setRequestHeader("Connection""close");  

看一下HTTP協議中關於這個屬性的定義:
HTTP/1.1 defines the "close" connection option for the sender to signal that the connection will be closed after completion of the response. For example,
       Connection: close
現在再說一下客戶端關閉鏈接和服務器端關閉鏈接的區別。如果采用客戶端關閉鏈接的方法,在客戶端的機器上使用netstat –an命令會看到很多TIME_WAIT的TCP鏈接。如果服務器端主動關閉鏈接這中情況就出現在服務器端。
參考WIKI上的說明http://wiki.apache.org/HttpComponents/FrequentlyAskedConnectionManagementQuestions
The TIME_WAIT state is a protection mechanism in TCP. The side that closes a socket connection orderly will keep the connection in state TIME_WAIT for some time, typically between 1 and 4 minutes.
TIME_WAIT的狀態會出現在主動關閉連接的這一端。TCP協議中TIME_WAIT狀態主要是為了保證數據的完整傳輸。具體可以參考此文檔:
http://www.softlab.ntua.gr/facilities/documentation/unix/unix-socket-faq/unix-socket-faq-2.html#ss2.7
另外強調一下使用上面這些方法關閉鏈接是在我們的應用中明確知道不需要重用連接時可以主動關閉連接來釋放資源。如果你的應用是需要重用接的話就沒必要這么做,使用原有的接還可以提供性能。


免責聲明!

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



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