ava代碼html
- HttpClient client = new HttpClient();
- HttpMethod method = new GetMethod("http://www.apache.org");
- try {
- client.executeMethod(method);
- byte[] responseBody = null;
-
- responseBody = method.getResponseBody();
-
- } catch (HttpException e) {
- // TODO Auto-generated catch block
- e.printStackTrace();
- } catch (IOException e) {
- // TODO Auto-generated catch block
- e.printStackTrace();
- }finally{
- method.releaseConnection();
-
- }
大部分人使用HttpClient都是使用相似上面的代碼,由於Apache官方例子就是如此。但在使用HttpClient會發現若是不斷循環發送大量請求到服務器會致使APACHE服務器的鏈接被佔滿,後續的請求便排隊等待,程序陷入「假死」狀態。apache
Java代碼
- Timeout 30
- KeepAlive On #表示服務器端不會主動關閉連接
- MaxKeepAliveRequests 100
- KeepAliveTimeout 180
所以這樣的配置就會致使每一個連接至少要過180S纔會被釋放,這樣在大量請求訪問時就必然會形成鏈接被佔滿,請求等待的狀況。
在 經過DEBUG後發現HttpClient在method.releaseConnection()後並無把鏈接關閉,這個方法只是將
鏈接返回給 connection manager。若是使用HttpClient client = new HttpClient()實例化一個HttpClient connection manager默認實現是使用SimpleHttpConnectionManager。SimpleHttpConnectionManager有個構 造函數以下
Java代碼
-
- public SimpleHttpConnectionManager(boolean alwaysClose) {
- super();
- this.alwaysClose = alwaysClose;
- }
看 方法註釋咱們就能夠看到若是alwaysClose設爲true在連接釋放以後connection manager 就會關閉鏈。在咱們HttpClient client = new HttpClient()這樣實例化一個client時connection manager是這樣被實例化的
Java代碼
- this.httpConnectionManager = new SimpleHttpConnectionManager();
所以alwaysClose默認是false,connection是不會被主動關閉的,所以咱們就有了一個客戶端關閉連接的方法。
方法一:
把事例代碼中的第一行實例化代碼改成以下便可,在method.releaseConnection();以後connection manager會關閉connection 。
Java代碼
- HttpClient client = new HttpClient(new HttpClientParams(),new SimpleHttpConnectionManager(true) );
方法二:
實例化代碼使用:HttpClient client = new HttpClient();
在method.releaseConnection();以後加上
Java代碼
- ((SimpleHttpConnectionManager)client.getHttpConnectionManager()).shutdown();
shutdown源代碼很簡單,看了一目瞭然
Java代碼
- public void shutdown() {
- httpConnection.close();
- }
方法三:
實例化代碼使用:HttpClient client = new HttpClient();
在method.releaseConnection();以後加上
client.getHttpConnectionManager().closeIdleConnections(0);此方法源碼代碼以下:
Java代碼
- public void closeIdleConnections(long idleTimeout) {
- long maxIdleTime = System.currentTimeMillis() - idleTimeout;
- if (idleStartTime <= maxIdleTime) {
- httpConnection.close();
- }
- }
將idleTimeout設爲0能夠確保連接被關閉。
以上這三種方法都是有客戶端主動關閉TCP連接的方法。下面再介紹由服務器端自動關閉連接的方法。
方法四:
代碼實現很簡單,全部代碼就和最上面的事例代碼同樣。只須要在HttpMethod method = new GetMethod("http://www.apache.org");加上一行HTTP頭的設置便可
Java代碼
- 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
另外強調一下使用上面這些方法關閉連接是在咱們的應用中明確知道不須要重用鏈接時能夠主動關閉鏈接來釋放資源。若是你的應用是須要重用連接的話就不必這麼作,使用原有的連接還能夠提供性能。