为什么在 Apache HTTP 客户端中重试之间没有延迟?
Why there are no delays between retries in Apache HTTP Client?
当 Apache HTTP 客户端无法连接到服务器 (IOException
) 时,它可能会尝试重试连接。但是,它不会等到下次重试。这似乎违反直觉,例如当目标服务器正在恢复或启动时,它可能需要一些时间才能为新请求做好准备。
为什么会这样?
这是来自 DefaultRequestDirector
的相应代码:
for (;;) {
context.setAttribute(ExecutionContext.HTTP_REQUEST, wrapper);
// Increment connect count
connectCount++;
try {
if (!managedConn.isOpen()) {
managedConn.open(route, context, params);
} else {
managedConn.setSocketTimeout(HttpConnectionParams.getSoTimeout(params));
}
establishRoute(route, context);
break;
} catch (final IOException ex) {
try {
managedConn.close();
} catch (final IOException ignore) {
}
if (retryHandler.retryRequest(ex, connectCount, context)) {
...
} else {
throw ex;
}
}
}
DefaultRequestDirector
确实有这种故意忽略 IOException
的硬编码逻辑。但是,此 API 在 4.3 和 4.3+ 中已弃用,您可以直接将 RetryHandler 设置为 HttpClientBuilder。
您将需要重写 DefaultHttpRequestRetryHandler
,它也忽略 ConnectionException
,但以更可配置的方式,通过定义不可重试的列表-类(不幸的是,这构造函数是受保护的,因此需要创建一个子类来公开该构造函数)。
CustomHttpRequestRetryHandler myRetryHandler = new CustomHttpRequestRetryHandler(3, false,
Collections.<Class<? extends IOException>>emptyList());
CloseableHttpClient client = HttpClients.custom()
.setRetryHandler(myRetryHandler)
.build();
private static class CustomHttpRequestRetryHandler extends DefaultHttpRequestRetryHandler {
public CustomHttpRequestRetryHandler(int retryCount, boolean requestSentRetryEnabled, Collection<Class<? extends IOException>> clazzes) {
super(retryCount, requestSentRetryEnabled, clazzes);
}
}
祝你好运!
当 Apache HTTP 客户端无法连接到服务器 (IOException
) 时,它可能会尝试重试连接。但是,它不会等到下次重试。这似乎违反直觉,例如当目标服务器正在恢复或启动时,它可能需要一些时间才能为新请求做好准备。
为什么会这样?
这是来自 DefaultRequestDirector
的相应代码:
for (;;) {
context.setAttribute(ExecutionContext.HTTP_REQUEST, wrapper);
// Increment connect count
connectCount++;
try {
if (!managedConn.isOpen()) {
managedConn.open(route, context, params);
} else {
managedConn.setSocketTimeout(HttpConnectionParams.getSoTimeout(params));
}
establishRoute(route, context);
break;
} catch (final IOException ex) {
try {
managedConn.close();
} catch (final IOException ignore) {
}
if (retryHandler.retryRequest(ex, connectCount, context)) {
...
} else {
throw ex;
}
}
}
DefaultRequestDirector
确实有这种故意忽略 IOException
的硬编码逻辑。但是,此 API 在 4.3 和 4.3+ 中已弃用,您可以直接将 RetryHandler 设置为 HttpClientBuilder。
您将需要重写 DefaultHttpRequestRetryHandler
,它也忽略 ConnectionException
,但以更可配置的方式,通过定义不可重试的列表-类(不幸的是,这构造函数是受保护的,因此需要创建一个子类来公开该构造函数)。
CustomHttpRequestRetryHandler myRetryHandler = new CustomHttpRequestRetryHandler(3, false,
Collections.<Class<? extends IOException>>emptyList());
CloseableHttpClient client = HttpClients.custom()
.setRetryHandler(myRetryHandler)
.build();
private static class CustomHttpRequestRetryHandler extends DefaultHttpRequestRetryHandler {
public CustomHttpRequestRetryHandler(int retryCount, boolean requestSentRetryEnabled, Collection<Class<? extends IOException>> clazzes) {
super(retryCount, requestSentRetryEnabled, clazzes);
}
}
祝你好运!