2012-08-09 140 views
24

我想用下面的代码发送请求到我的服务器。它总是在第三次请求时失败。httpclient异常“org.apache.http.conn.ConnectionPoolTimeoutException:超时等待连接”

import java.io.InputStreamReader; 
import java.io.UnsupportedEncodingException; 
import java.nio.charset.Charset; 

import org.apache.http.HttpEntity; 
import org.apache.http.HttpResponse; 
import org.apache.http.HttpStatus; 
import org.apache.http.HttpVersion; 
import org.apache.http.client.HttpClient; 
import org.apache.http.client.methods.HttpPost; 
import org.apache.http.entity.ContentType; 
import org.apache.http.entity.StringEntity; 
import org.apache.http.impl.client.DefaultHttpClient; 
import org.apache.http.impl.conn.tsccm.ThreadSafeClientConnManager; 
import org.apache.http.params.BasicHttpParams; 
import org.apache.http.params.CoreConnectionPNames; 
import org.apache.http.params.HttpParams; 
import org.apache.http.params.HttpProtocolParams; 
import org.json.JSONException; 
import org.json.JSONObject; 
import org.json.JSONTokener; 

public class HttpClientTest { 
    private HttpClient client; 

    public HttpClientTest() { 
     HttpParams params = new BasicHttpParams(); 
     params.setParameter(CoreConnectionPNames.CONNECTION_TIMEOUT, 15000); 
     params.setParameter(CoreConnectionPNames.SO_TIMEOUT, 15000); 

     HttpProtocolParams.setVersion(params, HttpVersion.HTTP_1_1); 
     HttpProtocolParams.setContentCharset(params, "utf-8"); 
     HttpProtocolParams.setUseExpectContinue(params, true); 
     ThreadSafeClientConnManager cm = new ThreadSafeClientConnManager(); 
     cm.setMaxTotal(100); 
     client = new DefaultHttpClient(cm, params); 

     while (true) { 
      HttpPost mPost = new HttpPost("http://myip/myservice"); 

      JSONObject json = new JSONObject(); 
      try { 
       json.put("serialNumber", "abcd"); 
      } catch (JSONException e1) { 
       e1.printStackTrace(); 
      } 
      StringEntity s = null; 
      try { 
       s = new StringEntity(json.toString()); 
      } catch (UnsupportedEncodingException e) { 
       e.printStackTrace(); 
      }    
      s.setContentEncoding("UTF-8"); 
      s.setContentType("application/json"); 
      mPost.setEntity(s); 

      JSONObject response = null; 

      System.out.println("HttpClientTest ---> send post"); 
      HttpResponse mHttpResponse; 
      try { 
       mHttpResponse = client.execute(mPost); 
       System.out.println("HttpClientTest ---> get response"); 
       if(mHttpResponse.getStatusLine().getStatusCode() == HttpStatus.SC_OK){ 
        HttpEntity entity = mHttpResponse.getEntity(); 
        ContentType contentType = ContentType.getOrDefault(entity); 
        Charset charset = contentType.getCharset(); 
        response = new JSONObject(new JSONTokener(new InputStreamReader(entity.getContent(), charset))); 

        System.out.println("HttpClientTest ---> get result:" + response.toString()); 
       } else { 
        mPost.abort(); 
        break; 
       } 
      } catch (Exception e) { 
       e.printStackTrace(); 
      } 
     } 
    } 

    public static void main(String[] args) { 
     HttpClientTest t = new HttpClientTest(); 
    } 
} 

例外如下:

org.apache.http.conn.ConnectionPoolTimeoutException: Timeout waiting for connection 
    at org.apache.http.impl.conn.tsccm.ConnPoolByRoute.getEntryBlocking(ConnPoolByRoute.java:417) 
    at org.apache.http.impl.conn.tsccm.ConnPoolByRoute$1.getPoolEntry(ConnPoolByRoute.java:300) 
    at org.apache.http.impl.conn.tsccm.ThreadSafeClientConnManager$1.getConnection(ThreadSafeClientConnManager.java:224) 
    at org.apache.http.impl.client.DefaultRequestDirector.execute(DefaultRequestDirector.java:401) 
    at org.apache.http.impl.client.AbstractHttpClient.execute(AbstractHttpClient.java:820) 
    at org.apache.http.impl.client.AbstractHttpClient.execute(AbstractHttpClient.java:754) 
    at org.apache.http.impl.client.AbstractHttpClient.execute(AbstractHttpClient.java:732) 
    at com.i360r.client.takeaway.network.HttpClientTest.<init>(HttpClientTest.java:68) 
    at com.i360r.client.takeaway.network.HttpClientTest.main(HttpClientTest.java:88) 
+1

你能为此得到任何解决方案吗? – CoronaPintu 2013-11-22 10:08:35

+0

有人解决了吗? – 2016-08-11 13:14:41

回答

22

我已经定了!在finally区块中添加mPost.releaseConnection()

try { 
} catch (Exception e) { 
} finally { 
    mPost.releaseConnection(); 
} 

DO更新包org.apache.httpcomponents 4.2.1

39

我有同样的问题,我发现修复。 此超时是由于连接泄漏。在我的情况下,我使用httpDelete方法,而不是消费响应。相反,检查响应的状态。

修复方法是,响应实体需要消耗。为了确保正确释放系统资源,必须关闭与实体关联的内容流。

因此,我使用EntityUtils.consumeQuietly(response.getEntity());确保实体内容已完全消耗,并且内容流(如果存在)已关闭。

+1

当忽略响应时,与Fluent HTTP客户端有类似的问题。仍然必须调用execute()。discardContent()以避免连接泄漏。 – rrhartjr 2015-01-23 14:42:54

+4

非常讨厌......如果你不使用它,图书馆应该放弃......或者至少给你一个警告...... – nterry 2016-08-22 23:05:15

2

如果你使用ApacheHttpClient与DropWizard 0.6.2,其幕后有一个默认的配置创建一个MultiThreadedHttpConnectionManager这也可能发生 - 而且默认配置只允许在一个时间more info here 2个并发的HTTP连接。

因此,通过这种配置,如果您的服务器越来越臃肿,并且始终向同一主机发出请求,则一次最多可以运行2个连接!

相关问题