52

我正在尝试使用以下代码向我的服务器发送请求。它总是在第三次请求时失败。

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)
4

10 回答 10

76

我有同样的问题,我找到了解决办法。此超时是由于连接泄漏。就我而言,我使用httpDelete的是方法而不是消耗响应。相反,我正在检查响应的状态。

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

所以我使用 EntityUtils.consumeQuietly(response.getEntity());了它来确保实体内容被完全消耗并且内容流(如果存在)被关闭。

于 2014-04-02T20:17:48.570 回答
35

我已经修好了!添加块mPost.releaseConnection()finally

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

将包更新org.apache.httpcomponents到 4.2.1

于 2012-08-09T23:13:55.383 回答
8

只需将要获取响应的行放在 try-with-resources 中,然后使用 CloseableHttpResponse 而不是 HttpResponse ,如下所示:

try(final CloseableHttpResponse mHttpResponse = client.execute(mPost);)
{
 System.out.println("HttpClientTest  ---> get response");
 ....remainder code

mHttpResponse 对象将被自动使用并为您关闭

希望这可以帮助!

于 2018-04-03T15:27:51.587 回答
4

使用 aCloseableHttpClient而不是HttpClient. 您将获得 aCloseableHttpResponse而不是HttpResponsewhich 支持close()。因此,当您完成响应后,只需关闭它,无需关闭连接。

CloseableHttpResponse response = closableHttpClient.execute(httpPost, context);

...做你需要做的事情:

response.close();
于 2019-01-17T10:30:44.360 回答
3

如果您ApacheHttpClient与 DropWizard 0.6.2 一起使用,也会发生这种情况,它在幕后创建一个MultiThreadedHttpConnectionManager具有默认配置的 - 并且该默认配置一次只允许 2 个并发 http 连接更多信息在这里

因此,使用此配置,如果您的服务器被淹没并且一直向同一主机发出请求,那么您一次最多允许运行 2 个连接!

于 2016-11-17T19:47:28.993 回答
2

我们遇到了同样的问题,并且我们受到限制,因为来自池的连接的 DefaultMaxPerRoute 的初始值为 2。我们的 API 会使用相同的 URI 触发不同的调用,但主体不同。一旦我们像这样明确地将其设置为更高的值

PoolingHttpClientConnectionManager cm = new PoolingHttpClientConnectionManager();
    cm.setMaxTotal(40);
    cm.setDefaultMaxPerRoute(20);

我们能够解决它。

于 2019-10-07T10:17:54.007 回答
1

通过 spark 编写和读取镶木地板时,我们遇到了这个错误。确切的错误是:
com.amazonaws.SdkClientException: Unable to execute HTTP request: Timeout waiting for connection from pool

终于弄明白这和Hadoop升级到3.1.3版本

有关 好像在这个新版本的Hadoop中,属性名从:
fs.s3a.connection.maximum改成
了:
spark.hadoop.fs.s3a .connection.maximum

在我们的 spark 配置中重命名属性,让我们回到正轨。

于 2020-01-20T06:42:27.850 回答
1

我遇到了同样的错误。事实证明,我需要关闭响应。

CloseableHttpResponse response = null;
try {
       response = ##some code
} catch(Exception e) {
  if (response != null) {
      response.close();
  }
}
于 2020-10-13T03:48:42.813 回答
0

正如Rama所说,这可能是连接泄漏的迹象。

releaseConnection()可以帮助解决此问题,但您可能需要找出根本原因。

timeout此外,这可能会发生,因为没有可用的连接可以租用,当您没有HttpClient. 在这种情况下,releaseConnection()将无济于事。

于 2018-10-15T12:46:23.227 回答
0

在我的情况下,正在使用实体内容流的 bufferedReader 没有被关闭。关闭它解决了错误。

于 2020-04-09T19:21:48.680 回答