【问题标题】:Setting time out in apache http client在 apache http 客户端中设置超时
【发布时间】:2014-03-01 20:01:59
【问题描述】:

我正在使用 Apache http 客户端 4.3.2 发送获取请求。我所做的是:

private final RequestConfig requestConfig = RequestConfig.custom()
        .setConnectTimeout(1000)
        .setConnectionRequestTimeout(1000)
        .setSocketTimeout(1000)
        .build();
private final HttpClient client = HttpClientBuilder.create()
        .disableAuthCaching()
        .disableAutomaticRetries()
        .disableConnectionState()
        .disableContentCompression()
        .disableCookieManagement()
        .disableRedirectHandling()
        .setDefaultRequestConfig(requestConfig)
        .build(); 

发送请求时:

HttpGet request = null;

try {
    request = new HttpGet(url);
    if (client.execute(request).getStatusLine().getStatusCode() == 200) {
        /* do some work here */
    }
} catch (Exception e) {
    Logger.error(e);
} finally {
    if (request != null) {
        request.releaseConnection();
    }
}

但是我的一些请求仍然需要很长时间才能超时。这是异常的堆栈跟踪:

java.net.SocketTimeoutException: Read timed out
    at java.net.SocketInputStream.socketRead0(Native Method)
    at java.net.SocketInputStream.read(SocketInputStream.java:152)
    at java.net.SocketInputStream.read(SocketInputStream.java:122)
    at org.apache.http.impl.io.SessionInputBufferImpl.streamRead(SessionInputBufferImpl.java:136)
    at org.apache.http.impl.io.SessionInputBufferImpl.fillBuffer(SessionInputBufferImpl.java:152)
    at org.apache.http.impl.io.SessionInputBufferImpl.readLine(SessionInputBufferImpl.java:270)
    at org.apache.http.impl.conn.DefaultHttpResponseParser.parseHead(DefaultHttpResponseParser.java:140)
    at org.apache.http.impl.conn.DefaultHttpResponseParser.parseHead(DefaultHttpResponseParser.java:57)
    at org.apache.http.impl.io.AbstractMessageParser.parse(AbstractMessageParser.java:260)
    at org.apache.http.impl.DefaultBHttpClientConnection.receiveResponseHeader(DefaultBHttpClientConnection.java:161)
    at sun.reflect.GeneratedMethodAccessor5.invoke(Unknown Source)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:606)
    at org.apache.http.impl.conn.CPoolProxy.invoke(CPoolProxy.java:138)
    at com.sun.proxy.$Proxy0.receiveResponseHeader(Unknown Source)
    at org.apache.http.protocol.HttpRequestExecutor.doReceiveResponse(HttpRequestExecutor.java:271)
    at org.apache.http.protocol.HttpRequestExecutor.execute(HttpRequestExecutor.java:123)
    at org.apache.http.impl.execchain.MainClientExec.execute(MainClientExec.java:254)
    at org.apache.http.impl.execchain.ProtocolExec.execute(ProtocolExec.java:195)
    at org.apache.http.impl.client.InternalHttpClient.doExecute(InternalHttpClient.java:186)
    at org.apache.http.impl.client.CloseableHttpClient.execute(CloseableHttpClient.java:82)
    at org.apache.http.impl.client.CloseableHttpClient.execute(CloseableHttpClient.java:106)
    at org.apache.http.impl.client.CloseableHttpClient.execute(CloseableHttpClient.java:57)

我应该设置其他超时值吗?我做错了什么?

【问题讨论】:

  • 我也有同样的问题,request.viaProxy(proxy).connectTimeout(1000) .socketTimeout(1000).execute() .returnContent().asString(StandardCharsets.UTF_8); 甚至需要 1 分钟!

标签: java timeout apache-httpcomponents


【解决方案1】:

当我遇到这个问题时,我更改了我的请求以配置每个请求的超时时间。

//...
HttpRequestBase request = new HttpGet(url); //or HttpPost

RequestConfig.Builder requestConfig = RequestConfig.custom();
requestConfig.setConnectTimeout(30 * 1000);
requestConfig.setConnectionRequestTimeout(30 * 1000);
requestConfig.setSocketTimeout(30 * 1000);

request.setConfig(requestConfig.build());

CloseableHttpResponse response = client.execute(request);
//...

效果很好。

【讨论】:

    【解决方案2】:

    这是一个实现目标的代码 sn-p 示例:

    int timeout = 5;
    RequestConfig config = RequestConfig.custom()
      .setConnectTimeout(timeout * 1000)
      .setConnectionRequestTimeout(timeout * 1000)
      .setSocketTimeout(timeout * 1000).build();
    CloseableHttpClient client =  HttpClientBuilder.create().setDefaultRequestConfig(config).build();
    

    这是以类型安全且可读的方式配置所有三个超时的推荐方式。

    Here is the full detail

    【讨论】:

      【解决方案3】:

      您可以尝试使用 HttpUriRequest#abort() 中止请求,请参阅https://hc.apache.org/httpcomponents-client-4.3.x/httpclient/apidocs/org/apache/http/client/methods/HttpUriRequest.html#abort%28%29。 但是,设置一个不需要拦截的超时会更好。

      【讨论】:

        【解决方案4】:
        private static final Integer TIMEOUT = 300;
        private static final Integer MILLISECONDS = 1000;
        

        RequestConfig 配置 = RequestConfig.custom().setConnectTimeout(TIMEOUT * MILLISECONDS) .setConnectionRequestTimeout(TIMEOUT * MILLISECONDS).setSocketTimeout(TIMEOUT * MILLISECONDS).build();

        httpClientBuilder.setDefaultRequestConfig(config); httpClientBuilder.setSSLSocketFactory(sslConnectionSocketFactory);

        我失败了:连接超时:连接错误 20 秒,即使我已将时间设置为 5 分钟。

        【讨论】:

          【解决方案5】:

          .setSocketTimeout(1000) 表示应用程序在读取数据包时不活动 1 秒会导致此异常。

          您可以通过在调试模式下运行代码并延迟进入下一步一段时间来测试这一点。

          检查您希望应用程序进行数据读取操作的最长可能时间限制,例如 50 秒(批量数据的极端情况)--> 然后更新 .setSocketTimeout(50000)

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 2014-05-16
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2013-07-16
            • 2011-11-12
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多