聊聊HttpClient的ServiceUnavailableRetryStrategy

2023-10-13 09:23:04 浏览数 (2)

本文主要研究一下HttpClient的ServiceUnavailableRetryStrategy

ServiceUnavailableRetryStrategy

org/apache/http/client/ServiceUnavailableRetryStrategy.java

代码语言:javascript复制
public interface ServiceUnavailableRetryStrategy {

    /**
     * Determines if a method should be retried given the response from the target server.
     *
     * @param response the response from the target server
     * @param executionCount the number of times this method has been
     * unsuccessfully executed
     * @param context the context for the request execution

     * @return {@code true} if the method should be retried, {@code false}
     * otherwise
     */
    boolean retryRequest(HttpResponse response, int executionCount, HttpContext context);

    /**
     * @return The interval between the subsequent auto-retries.
     */
    long getRetryInterval();

}

ServiceUnavailableRetryStrategy定义了retryRequest方法用于返回是否该重试,getRetryInterval返回自动重试的间隔

DefaultServiceUnavailableRetryStrategy

org/apache/http/impl/client/DefaultServiceUnavailableRetryStrategy.java

代码语言:javascript复制
@Contract(threading = ThreadingBehavior.IMMUTABLE)
public class DefaultServiceUnavailableRetryStrategy implements ServiceUnavailableRetryStrategy {

    /**
     * Maximum number of allowed retries if the server responds with a HTTP code
     * in our retry code list. Default value is 1.
     */
    private final int maxRetries;

    /**
     * Retry interval between subsequent requests, in milliseconds. Default
     * value is 1 second.
     */
    private final long retryInterval;

    public DefaultServiceUnavailableRetryStrategy(final int maxRetries, final int retryInterval) {
        super();
        Args.positive(maxRetries, "Max retries");
        Args.positive(retryInterval, "Retry interval");
        this.maxRetries = maxRetries;
        this.retryInterval = retryInterval;
    }

    public DefaultServiceUnavailableRetryStrategy() {
        this(1, 1000);
    }

    @Override
    public boolean retryRequest(final HttpResponse response, final int executionCount, final HttpContext context) {
        return executionCount <= maxRetries &&
            response.getStatusLine().getStatusCode() == HttpStatus.SC_SERVICE_UNAVAILABLE;
    }

    @Override
    public long getRetryInterval() {
        return retryInterval;
    }

}

DefaultServiceUnavailableRetryStrategy实现了ServiceUnavailableRetryStrategy接口,其构造器接收maxRetries(默认1)及retryInterval(单位毫秒,默认1s);retryRequest方法在executionCount小于等于maxRetries且statusCode=503的时候返回true

ServiceUnavailableRetryExec

org/apache/http/impl/execchain/ServiceUnavailableRetryExec.java

代码语言:javascript复制
@Contract(threading = ThreadingBehavior.IMMUTABLE_CONDITIONAL)
public class ServiceUnavailableRetryExec implements ClientExecChain {

    private final Log log = LogFactory.getLog(getClass());

    private final ClientExecChain requestExecutor;
    private final ServiceUnavailableRetryStrategy retryStrategy;

    public ServiceUnavailableRetryExec(
            final ClientExecChain requestExecutor,
            final ServiceUnavailableRetryStrategy retryStrategy) {
        super();
        Args.notNull(requestExecutor, "HTTP request executor");
        Args.notNull(retryStrategy, "Retry strategy");
        this.requestExecutor = requestExecutor;
        this.retryStrategy = retryStrategy;
    }

    @Override
    public CloseableHttpResponse execute(
            final HttpRoute route,
            final HttpRequestWrapper request,
            final HttpClientContext context,
            final HttpExecutionAware execAware) throws IOException, HttpException {
        final Header[] origheaders = request.getAllHeaders();
        for (int c = 1;; c  ) {
            final CloseableHttpResponse response = this.requestExecutor.execute(
                    route, request, context, execAware);
            try {
                if (this.retryStrategy.retryRequest(response, c, context)
                        && RequestEntityProxy.isRepeatable(request)) {
                    response.close();
                    final long nextInterval = this.retryStrategy.getRetryInterval();
                    if (nextInterval > 0) {
                        try {
                            this.log.trace("Wait for "   nextInterval);
                            Thread.sleep(nextInterval);
                        } catch (final InterruptedException e) {
                            Thread.currentThread().interrupt();
                            throw new InterruptedIOException();
                        }
                    }
                    request.setHeaders(origheaders);
                } else {
                    return response;
                }
            } catch (final RuntimeException ex) {
                response.close();
                throw ex;
            }
        }
    }

}

ServiceUnavailableRetryExec实现了ClientExecChain接口,其execute方法执行完requestExecutor.execute之后,会请求retryStrategy.retryRequest判断是否需要重试,在需要重试且RequestEntityProxy.isRepeatable(request)时,获取retryStrategy.getRetryInterval()进行sleep,然后继续下个循环请求execute方法

小结

HttpClient的ServiceUnavailableRetryStrategy定义了retryRequest方法用于返回是否该重试,getRetryInterval返回自动重试的间隔;DefaultServiceUnavailableRetryStrategy实现了ServiceUnavailableRetryStrategy接口,其构造器接收maxRetries(默认1)及retryInterval(单位毫秒,默认1s);retryRequest方法在executionCount小于等于maxRetries且statusCode=503的时候返回true;ServiceUnavailableRetryExec则使用ServiceUnavailableRetryStrategy完成了针对503的重试。

0 人点赞