请求重试Apache HttpClient之间的超时

时间:2018-01-31 11:42:14

标签: httpclient apache-httpclient-4.x apache-commons-httpclient

有人可以分享如何配置现代HttpClient 4.5.3重试失败的请求并在每次重试前等待一段时间吗?

到目前为止看起来我正确地认为.setRetryHandler(new DefaultHttpRequestRetryHandler(X, false))允许重试X次请求。

但我无法理解如何配置退避:.setConnectionBackoffStrategy() / .setBackoffManager()根据JavaDocs管理其他内容,而不是重试之间的超时。

3 个答案:

答案 0 :(得分:6)

BackoffManager / ConnectionBackoffStrategy组合可用于根据I / O错误率和503响应动态增加或减少每个路由限制的最大连接数。它们对请求执行没有影响,不能用于控制请求重新执行

这是HC 4.x API最好的方法

CloseableHttpClient client = HttpClientBuilder.create()
        .setRetryHandler(new HttpRequestRetryHandler() {
            @Override
            public boolean retryRequest(IOException exception, int executionCount, HttpContext context) {
                return executionCount <= maxRetries &&
                        exception instanceof SocketException;
            }
        })
        .setServiceUnavailableRetryStrategy(new ServiceUnavailableRetryStrategy() {
            @Override
            public boolean retryRequest(HttpResponse response, int executionCount, HttpContext context) {
                return executionCount <= maxRetries &&
                        response.getStatusLine().getStatusCode() == HttpStatus.SC_SERVICE_UNAVAILABLE;
            }

            @Override
            public long getRetryInterval() {
                return 100;
            }
        })
        .build();

请注意,目前还没有优雅的方法在I / O错误的情况下强制执行请求执行尝试之间的延迟,或者根据请求路由动态调整重试间隔。

答案 1 :(得分:2)

关于动态延迟,我想建议一下:

CloseableHttpClient client = HttpClientBuilder.create()
    .setRetryHandler(new HttpRequestRetryHandler() {
        @Override
        public boolean retryRequest(IOException exception, int executionCount, HttpContext context) {
            return executionCount <= maxRetries ;
        }
    })
    .setServiceUnavailableRetryStrategy(new ServiceUnavailableRetryStrategy() {
        int waitPeriod = 100;
        @Override
        public boolean retryRequest(HttpResponse response, int executionCount, HttpContext context) {
            waitPeriod *= 2;
            return executionCount <= maxRetries &&
               response.getStatusLine().getStatusCode() >= 500; //important!
        }

        @Override
        public long getRetryInterval() {
            return waitPeriod;
        }
    })
    .build();

附录: 请注意,如果发生IO错误(例如超时,端口未打开或连接关闭),将不会调用ServiceUnavailableRetryStrategy.retryRequest。在这种情况下,将仅调用HttpRequestRetryHandler.retryRequest,并且重试将立即发生或在固定的延迟后发生(我无法最终弄清这一点)。因此,oleg的答案实际上是正确的答案。在HttpClient 4.5的支持下无法做到这一点。

(我实际上想将其称为设计错误,因为在现代微服务环境中,IO错误后的延迟重试非常重要。)

答案 2 :(得分:0)

您可以使用lambda

client.setRetryHandler((e, execCount, httpContext) -> {
                if (execCount > tries) {
                    return false;
                } else {
                    try {
                        Thread.sleep(recalMillis);
                    } catch (InterruptedException ex) {
                        //ignore
                    }
                    return true;
                }

请注意,处理程序仅适用于IOExceptions类型