• 聊聊HttpClient的ConnectionBackoffStrategy


    本文主要研究一下HttpClient的ConnectionBackoffStrategy

    ConnectionBackoffStrategy

    org/apache/http/client/ConnectionBackoffStrategy.java

    /**
     * When managing a dynamic number of connections for a given route, this
     * strategy assesses whether a given request execution outcome should
     * result in a backoff signal or not, based on either examining the
     * {@code Throwable} that resulted or by examining the resulting
     * response (e.g. for its status code).
     *
     * @since 4.2
     *
     */
    public interface ConnectionBackoffStrategy {
    
        /**
         * Determines whether seeing the given {@code Throwable} as
         * a result of request execution should result in a backoff
         * signal.
         * @param t the {@code Throwable} that happened
         * @return {@code true} if a backoff signal should be
         *   given
         */
        boolean shouldBackoff(Throwable t);
    
        /**
         * Determines whether receiving the given {@link HttpResponse} as
         * a result of request execution should result in a backoff
         * signal. Implementations MUST restrict themselves to examining
         * the response header and MUST NOT consume any of the response
         * body, if any.
         * @param resp the {@code HttpResponse} that was received
         * @return {@code true} if a backoff signal should be
         *   given
         */
        boolean shouldBackoff(HttpResponse resp);
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34

    ConnectionBackoffStrategy定义了shouldBackoff方法,它根据异常或者response来进行判断

    NullBackoffStrategy

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

    public class NullBackoffStrategy implements ConnectionBackoffStrategy {
    
        @Override
        public boolean shouldBackoff(final Throwable t) {
            return false;
        }
    
        @Override
        public boolean shouldBackoff(final HttpResponse resp) {
            return false;
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12

    NullBackoffStrategy实现了ConnectionBackoffStrategy,shouldBackoff方法返回false

    DefaultBackoffStrategy

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

    public class DefaultBackoffStrategy implements ConnectionBackoffStrategy {
    
        @Override
        public boolean shouldBackoff(final Throwable t) {
            return t instanceof SocketTimeoutException || t instanceof ConnectException;
        }
    
        @Override
        public boolean shouldBackoff(final HttpResponse resp) {
            return resp.getStatusLine().getStatusCode() == 429 ||
                resp.getStatusLine().getStatusCode() == HttpStatus.SC_SERVICE_UNAVAILABLE;
        }
    
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14

    DefaultBackoffStrategy在SocketTimeoutException或者ConnectException的时候返回true,或者在response code为429或者503的时候返回true

    BackoffStrategyExec

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

    @Contract(threading = ThreadingBehavior.IMMUTABLE_CONDITIONAL)
    public class BackoffStrategyExec implements ClientExecChain {
    
        private final ClientExecChain requestExecutor;
        private final ConnectionBackoffStrategy connectionBackoffStrategy;
        private final BackoffManager backoffManager;
    
        public BackoffStrategyExec(
                final ClientExecChain requestExecutor,
                final ConnectionBackoffStrategy connectionBackoffStrategy,
                final BackoffManager backoffManager) {
            super();
            Args.notNull(requestExecutor, "HTTP client request executor");
            Args.notNull(connectionBackoffStrategy, "Connection backoff strategy");
            Args.notNull(backoffManager, "Backoff manager");
            this.requestExecutor = requestExecutor;
            this.connectionBackoffStrategy = connectionBackoffStrategy;
            this.backoffManager = backoffManager;
        }
    
        @Override
        public CloseableHttpResponse execute(
                final HttpRoute route,
                final HttpRequestWrapper request,
                final HttpClientContext context,
                final HttpExecutionAware execAware) throws IOException, HttpException {
            Args.notNull(route, "HTTP route");
            Args.notNull(request, "HTTP request");
            Args.notNull(context, "HTTP context");
            CloseableHttpResponse out = null;
            try {
                out = this.requestExecutor.execute(route, request, context, execAware);
            } catch (final Exception ex) {
                if (out != null) {
                    out.close();
                }
                if (this.connectionBackoffStrategy.shouldBackoff(ex)) {
                    this.backoffManager.backOff(route);
                }
                if (ex instanceof RuntimeException) {
                    throw (RuntimeException) ex;
                }
                if (ex instanceof HttpException) {
                    throw (HttpException) ex;
                }
                if (ex instanceof IOException) {
                    throw (IOException) ex;
                }
                throw new UndeclaredThrowableException(ex);
            }
            if (this.connectionBackoffStrategy.shouldBackoff(out)) {
                this.backoffManager.backOff(route);
            } else {
                this.backoffManager.probe(route);
            }
            return out;
        }
    
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59

    BackoffStrategyExec实现了ClientExecChain接口,其execute执行requestExecutor.execute,捕获到异常的时候通过connectionBackoffStrategy.shouldBackoff(ex)来决定是否需要backOff,是的话执行backoffManager.backOff(route);若没有异常则通过connectionBackoffStrategy.shouldBackoff(out)根据response来判断是否需要backOff,是的化执行backoffManager.backOff(route)

    小结

    HttpClient的DefaultBackoffStrategy在SocketTimeoutException或者ConnectException的时候返回true,或者在response code为429或者503的时候返回true;BackoffStrategyExec则通过connectionBackoffStrategy与backoffManager来配合执行backOff。这个backOff的目的就是动态调整每个route的connection大小(MaxPerRoute)。

  • 相关阅读:
    21.6 CSS 弹性布局
    Java | Leetcode Java题解之第130题被围绕的区域
    一文知晓Linux文件权限
    信息系统项目管理师-整合管理论文提纲
    服装企业如何利用APS生产计划排产提升管理效益?
    阿里云服务器镜像系统Anolis OS龙蜥详细介绍
    Canvas实现3D效果
    GitHub上架即下架!《分布式系统人人都是架构师》全彩笔记开源
    HTTP 介绍
    ip地址转化
  • 原文地址:https://blog.csdn.net/hello_ejb3/article/details/133822021