background
Online services rely on third parties, interfaces RT traffic is large in response time is very long. Since each timeout parameter is set to 5s.
Examples
PoolingHttpClientConnectionManager connManager = new PoolingHttpClientConnectionManager();
// 连接池最大的连接数
connManager.setMaxTotal(6000);
// 单个路由的最大连接数,例如:www.baidu.com,图片最大高峰并发量520
connManager.setDefaultMaxPerRoute(500);
RequestConfig.Builder custom = RequestConfig.custom();
// 连接超时时间 建立连接时间 此前设置3000
custom.setConnectTimeout(800);
// 从connect Manager获取Connection 超时时间(连接池获取连接超时时间)
custom.setConnectionRequestTimeout(500);
// (获取response的返回时间)读取返回时间 此前设置40000,官方建议40s
custom.setSocketTimeout(1000);
RequestConfig config = custom.build();
// DefaultHttpRequestRetryHandler 重试策略(可自定义)
httpClient = HttpClients.custom().setRetryHandler(new DefaultHttpRequestRetryHandler(1, true)).setConnectionManager(connManager)
.setDefaultRequestConfig(config).build();
复制代码
Construction httpClient
By debug, you can know the future build method of execution, access to InternalHttpClient object, if you do not specify execution chain, is to use RetryExec actuator, the default retry strategy is DefaultHttpRequestRetryHandler
public CloseableHttpClient build() {
... 省略部分代码
// Add request retry executor, if not disabled
if (!automaticRetriesDisabled) {
HttpRequestRetryHandler retryHandlerCopy = this.retryHandler;
if (retryHandlerCopy == null) {
retryHandlerCopy = DefaultHttpRequestRetryHandler.INSTANCE;
}
execChain = new RetryExec(execChain, retryHandlerCopy);
}
... 省略部分代码
}
复制代码
Timeout parameters
Three dimensions timeout settings
- Connection timeout setConnectTimeout
- Read Timeout setSocketTimeout
- Obtaining a connection from the connection pool timeout setConnectionRequestTimeout
Retry strategy impact on the business
By default there retry strategy, or you can manually change or redefine retry strategy, but in some cases, it can retry, retry some cases is failure.
Retry analysis
For our scenario applications get the post, it can be summarized as follows:
Only InterruptedIOException retry only occurs when IOExecetion occurs, UnknownHostException, ConnectException, SSLException, may occur in the weight at which no abnormality 4 retry methods can get three retries, post methods corresponding socket output stream is not successfully write and flush test three times.
Does not retry exception:
- InterruptedIOException, thread interrupt exception
- UnknownHostException, find the corresponding host
- ConnectException, found the host, connection establishment failure
- SSLException, https abnormal certification
DefaultHttpRequestRetryHandler retry strategy
@Override
public boolean retryRequest(
final IOException exception,
final int executionCount,
final HttpContext context) {
Args.notNull(exception, "Exception parameter");
Args.notNull(context, "HTTP context");
if (executionCount > this.retryCount) {
// Do not retry if over max retry count
return false;
}
// 异常类是否在禁止重试中
if (this.nonRetriableClasses.contains(exception.getClass())) {
return false;
} else {
for (final Class<? extends IOException> rejectException : this.nonRetriableClasses) {
if (rejectException.isInstance(exception)) {
return false;
}
}
}
final HttpClientContext clientContext = HttpClientContext.adapt(context);
final HttpRequest request = clientContext.getRequest();
if(requestIsAborted(request)){
return false;
}
if (handleAsIdempotent(request)) {
// Retry if the request is considered idempotent
return true;
}
// 根据上下文判断请求是否发送成功了,或者根据状态为是否永远可以重复发送(默认的是否) requestSentRetryEnabled 参数可以在构建httpCLient对象设置重试策略指定此属性
// isRequestSent 是在HttpRequestExecutor中doSendRequest方法中flush成功设置context.setAttribute("http.request_sent", Boolean.TRUE);
if (!clientContext.isRequestSent() || this.requestSentRetryEnabled) {
// Retry if the request has not been sent fully or
// if it's OK to retry methods that have been sent
return true;
}
// otherwise do not retry
return false;
}
// 几种类型的异常不重试,同时判断是否与异常类型的子类,是子类的话,也不重试
复制代码
In addition two timeouts, connection timeout and read timeout: java.net.SocketTimeoutException: Read timed out java.net.SocketTimeoutException: connect timed out two timeouts are SocketTimeoutException, inherited from InterruptedIOException, belonging to the above first kind interrupt thread exceptions, will not be retried.
Will retry the circumstances under which
post flush with the write request in the output stream, when, in addition to which IOExecetion InterruptedIOException, UnknownHostException, ConnectException, SSLException occur.
That could possibly go wrong step by step HttpClientConnection.flush (), with the inside you can know the object of its operation is a SocketOutputStream, and flush this class is empty achieve, so you can just look at wirte method.
Retry parameters requestSentRetryEnabled http.request_sent
//根据上下文判断请求是否发送成功了,或者根据状态为是否永远可以重复发送(默认的是否)
if (!clientContext.isRequestSent() || this.requestSentRetryEnabled) {
return true;
}
复制代码
Prohibit retry
httpclient provided by default retry strategy for some scenarios, we can manually close retry strategy. HttpClientBuilder, which is build () method RetryExec chose the actuator is pre-conditions, i.e. no manual prohibited.
// Add request retry executor, if not disabled
if (!automaticRetriesDisabled) {
HttpRequestRetryHandler retryHandlerCopy = this.retryHandler;
if (retryHandlerCopy == null) {
retryHandlerCopy = DefaultHttpRequestRetryHandler.INSTANCE;
}
execChain = new RetryExec(execChain, retryHandlerCopy);
}
复制代码