使用Backoff策略提高HttpClient连接管理的效率
作者:codecraft
序
本文主要研究一下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); }
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; } }
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; } }
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; } }
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
)。
以上就是使用Backoff策略提高HttpClient连接管理的效率的详细内容,更多关于HttpClient Backoff连接管理的资料请关注脚本之家其它相关文章!