代码之家  ›  专栏  ›  技术社区  ›  snowindy

请求重试之间超时Apache HttpClient

  •  5
  • snowindy  · 技术社区  · 6 年前

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

    到目前为止,看起来我没弄错 .setRetryHandler(new DefaultHttpRequestRetryHandler(X, false)) 将允许重试请求X次。

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

    3 回复  |  直到 6 年前
        1
  •  10
  •   Thomas Schütt    5 年前

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

    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();
    

    附件: 请注意,ServiceUnavailableRetryStrategy。如果出现超时、端口未打开或连接关闭等IO错误,则不会调用retryRequest。在这种情况下,只有HttpRequestRetryHandler。将调用retryRequest,重试将立即发生或在固定延迟后发生(我无法最终澄清这一点)。所以奥列格的答案实际上是正确的。有了HttpClient 4.5的支持,就无法做到这一点。

    (实际上,我想把这称为设计错误,因为IO错误后延迟重试在现代微服务环境中至关重要。)

        2
  •  8
  •   ok2c    6 年前

    BackoffManager / ConnectionBackoffStrategy combo可用于根据输入/输出错误率和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错误的情况下,目前没有一种优雅的方法来强制执行请求执行尝试之间的延迟,或者根据请求路由动态调整重试间隔。

        3
  •  1
  •   Artem Demyansky    4 年前

    您可以使用lambda

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

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