为什么在 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);
        }
    }

祝你好运!