有人能分享如何配置现代化的HttpClient 4.5.3以在每次重试之前等待一段时间并重试失败的请求吗?
目前看来,我已经正确地理解了.setRetryHandler(new DefaultHttpRequestRetryHandler(X, false))
将允许重试X次请求。
但我无法理解如何配置退避:.setConnectionBackoffStrategy()
/ .setBackoffManager()
根据JavaDocs调节其他内容,而不是重试之间的超时。
有人能分享如何配置现代化的HttpClient 4.5.3以在每次重试之前等待一段时间并重试失败的请求吗?
目前看来,我已经正确地理解了.setRetryHandler(new DefaultHttpRequestRetryHandler(X, false))
将允许重试X次请求。
但我无法理解如何配置退避:.setConnectionBackoffStrategy()
/ .setBackoffManager()
根据JavaDocs调节其他内容,而不是重试之间的超时。
关于动态延迟,我建议这样:
CloseableHttpClient client = HttpClientBuilder.create()
.setRetryHandler(new HttpRequestRetryHandler() {
@Override
public boolean retryRequest(IOException exception, int executionCount, HttpContext context) {
return executionCount <= maxRetries ;
}
})
.setServiceUnavailableRetryStrategy(new ServiceUnavailableRetryStrategy() {
int waitPeriod = 100;
@Override
public boolean retryRequest(HttpResponse response, int executionCount, HttpContext context) {
waitPeriod *= 2;
return executionCount <= maxRetries &&
response.getStatusLine().getStatusCode() >= 500; //important!
}
@Override
public long getRetryInterval() {
return waitPeriod;
}
})
.build();
附录: 请注意,如果出现超时、端口未开放或连接关闭等IO错误,将不会调用ServiceUnavailableRetryStrategy.retryRequest。在这种情况下,只会调用HttpRequestRetryHandler.retryRequest,并且重试将立即发生或在固定延迟后发生(我最终无法澄清这一点)。因此,Oleg的答案实际上是正确的。没有办法使用HttpClient 4.5支持此功能。
(实际上,我认为这是一个设计缺陷,在现代微服务环境中,IO错误后的延迟重试非常重要。)
BackoffManager
/ ConnectionBackoffStrategy
组合可用于根据 I/O 错误和 503 响应的速率动态增加或减少每路最大连接限制。它们不会影响请求执行,并且不能用于控制请求重新执行。这是使用 HC 4.x API 的最佳方法。CloseableHttpClient client = HttpClientBuilder.create()
.setRetryHandler(new HttpRequestRetryHandler() {
@Override
public boolean retryRequest(IOException exception, int executionCount, HttpContext context) {
return executionCount <= maxRetries &&
exception instanceof SocketException;
}
})
.setServiceUnavailableRetryStrategy(new ServiceUnavailableRetryStrategy() {
@Override
public boolean retryRequest(HttpResponse response, int executionCount, HttpContext context) {
return executionCount <= maxRetries &&
response.getStatusLine().getStatusCode() == HttpStatus.SC_SERVICE_UNAVAILABLE;
}
@Override
public long getRetryInterval() {
return 100;
}
})
.build();
HttpRequestRetryHandler
的实现,并覆盖 retryRequest(...)
方法以添加延迟,甚至是动态或指数级的,用于处理 IOException
。 - Drakes您可以使用 Lambda
client.setRetryHandler((e, execCount, httpContext) -> {
if (execCount > tries) {
return false;
} else {
try {
Thread.sleep(recalMillis);
} catch (InterruptedException ex) {
//ignore
}
return true;
}
请注意,处理程序仅适用于IOException类型的异常。
.setRetryHandler(new HttpRequestRetryHandler() { .. })
并覆盖retryRequest()
。这是一个很好的解决方案,因为重试和延迟都在此手动编码。 - gene b.这对我们非常有效。它可以进行重试(3次)和延迟(1000ms)。我们覆盖了两个东西:HttpResponseInterceptor.process()
和 HttpRequestRetryHandler.retryRequest()
。第一个会对无效的(400+)HTTP状态码抛出异常,然后进入retryRequest
实现。注意:如果所有的重试都已经用尽,您将来到此片段底部的最终Catch。
// Define an HttpClient with the following features:
// 1) Intercept HTTP response to detect any 400+ HTTP Codes (process() implementation), and if so,
// 2) Force a retry with a delay (HttpRequestRetryHandler.retryRequest() implementation)
final CloseableHttpClient httpClient = HttpClients.custom().addInterceptorLast(new HttpResponseInterceptor() {
@Override
public void process(HttpResponse response, HttpContext context) throws HttpException, IOException {
if (response.getStatusLine().getStatusCode() >= 400) {
// Throw an IOException to force a retry via HttpRequestRetryHandler.retryRequest()
throw new IOException("Invalid code returned: " + response.getStatusLine().getStatusCode());
}
}
})
.setRetryHandler(new HttpRequestRetryHandler() {
@Override
public boolean retryRequest(IOException exception, int executionCount, HttpContext context) {
if (executionCount > MAX_RETRIES) { // MAX_RETRIES = 3
return false;
} else {
try {
// Sleep before retrying
Thread.sleep(DELAY); // DELAY = 1000 MS
} catch (InterruptedException ex) {
// ... Log or silently swallow
}
return true;
}
}
})
.build();
final HttpGet getOp = new HttpGet("http://yoururl.com/api/123/");
try {
return httpClient.execute(getOp, new ResponseHandler<String>() {
@Override
public String handleResponse(final HttpResponse response) throws ClientProtocolException, IOException {
// ... Process response after preliminary HTTP code verification
}
});
} catch (IOException ioe) {
// NOTE: Comes here if all retries have failed, throw error back to caller
log.error("All retries have been exhausted");
throw ioe;
}
ExponentialBackOffSchedulingStrategy
与异步缓存重新验证有关,而不是请求执行。 - ok2cDefaultBackoffStrategy
的逻辑基本上符合我的需求。 - snowindy