【问题标题】:How to retry on 5XX errors using Apache Http Client library如何使用 Apache Http 客户端库重试 5XX 错误
【发布时间】:2020-05-21 20:48:26
【问题描述】:

我正在使用 Apache http 客户端,并且正在使用我的自定义 HttpRequestRetryHandler。下面给出的代码。

@Slf4j
@RequiredArgsConstructor
public class MyCustomHttpRequestRetryHandler implements HttpRequestRetryHandler {
    private final String serviceName;
    private final int maxRetries;

    private static final List<Class> RETRYABLE_EXCEPTIONS = Arrays.asList(
        InterruptedIOException.class, // ConnectTimeoutException, ConnectionPoolTimeoutException, SocketTimeoutException and RequestAbortedException
        NoHttpResponseException.class, // Usually when under heavy load, the web server receive requests but fails to process them
        ConnectException.class // Occurs when socket connection fails to to a remote address and port

    );

    @Override
    public boolean retryRequest(IOException exception, int executionCount, HttpContext context) {
        if (executionCount > maxRetries) {
            return false;
        }
        if (isExceptionRetryable(exception)) {
            log.warn("Service: {}: Re-trying service call due to : {}. Number of retry: {}/{}", serviceName, exception.getMessage(), executionCount,
                maxRetries, exception);
            return true;
        }
        return false;
    }

    private boolean isExceptionRetryable(Throwable throwable) {
        for (Class clazz : RETRYABLE_EXCEPTIONS) {
            if (clazz.isInstance(throwable)) {
                return true;
            }
        }
        return false;
    }
}

有了这个可重试的异常列表,我可以很好的捕捉到超时和连接异常,但是如何处理重试5XX错误呢? 根据异常处理文档https://hc.apache.org/httpclient-3.x/exception-handling.html,我在返回 5XX 时找不到异常。

对我们的任何帮助表示赞赏!

注意:- 依赖版本

    <dependency>
      <groupId>org.apache.httpcomponents</groupId>
      <artifactId>fluent-hc</artifactId>
      <version>4.5.12</version>
    </dependency>

【问题讨论】:

  • 我可以很好地纠正一个肮脏的逻辑,在 5XX 上手动重试,但我想看看是否有任何 Apache http 客户端提供开箱即用的功能。

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


【解决方案1】:

我问这个问题太早了。我为我的问题找到了以下解决方案。

/**
 * This class will define retry strategy for service unavailable errors
 */
@Slf4j
public class ServiceUnavailableRetryHandler implements ServiceUnavailableRetryStrategy {
    private final Set<Integer> retryableErrorCodes = new HashSet<>(Arrays.asList(500, 503));
    private final long retryInternal = 500;
    private final int maxRetries = 3;


    @Override
    public boolean retryRequest(HttpResponse response, int executionCount, HttpContext context) {

        int statusCode = response.getStatusLine().getStatusCode();

        String errMsg = String.format("Service Unavailable - StatusCode: %d, Attempt#: %d/%d", statusCode, executionCount, maxRetries);

        if (executionCount > maxRetries) {
            log.error(errMsg);
            return false;
        }

        if (retryableErrorCodes.contains(statusCode)) {
            log.warn(errMsg);
            return true;
        }
        return false;

    }

    @Override
    public long getRetryInterval() {
        return this.retryInternal;
    }
}

将此处理程序/策略类添加到您的 http 客户端构建器中。

httpClientBuilder.setServiceUnavailableRetryStrategy(new ServiceUnavailableRetryHandler());

【讨论】:

    猜你喜欢
    • 2020-04-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-06-15
    • 2012-10-01
    相关资源
    最近更新 更多