为什么Apache HTTP Client中的重试之间没有延迟?

时间:2017-09-22 13:06:00

标签: apache-httpclient-4.x

当Apache HTTP Client无法连接到服务器(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;
        }
    }
}

1 个答案:

答案 0 :(得分:0)

DefaultRequestDirector确实有这种硬编码的逻辑故意忽略IOException。但是,这个API在4.3和4.3+中已弃用,您可以直接将RetryHandler设置为HttpClientBuilder。

您需要覆盖DefaultHttpRequestRetryHandler同样忽略ConnectionException,但是以更可配置的方式,通过定义不可重试类的列表(不幸的是,这个构造函数受到保护,所以a需要创建子类来公开该构造函数)。

    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);
        }
    }
祝你好运!