【问题标题】:CloseableHttpClient: will all exceptions go to retyHandler() if there's one?CloseableHttpClient:如果有异常,所有异常都会转到 retyHandler() 吗?
【发布时间】:2019-04-05 18:33:06
【问题描述】:

所以我正在关注 retryHandler() 的这个例子,它有 try/finally。我的问题是:如何重试异常?

public class HttpClientRetryHandlerExample {

    public static void main(String... args) throws IOException {

        CloseableHttpClient httpclient = HttpClients.custom()
                .setRetryHandler(retryHandler())
                .build();

        try {
            HttpGet httpget = new HttpGet("http://localhost:1234");
            System.out.println("Executing request " + httpget.getRequestLine());
            httpclient.execute(httpget);
            System.out.println("----------------------------------------");
            System.out.println("Request finished");
        } finally {
            httpclient.close();
        }
    }

    private static HttpRequestRetryHandler retryHandler(){
        return (exception, executionCount, context) -> {

            System.out.println("try request: " + executionCount);

            if (executionCount >= 5) {
                // Do not retry if over max retry count
                return false;
            }
            if (exception instanceof InterruptedIOException) {
                // Timeout
                return false;
            }
            if (exception instanceof UnknownHostException) {
                // Unknown host
                return false;
            }
            if (exception instanceof SSLException) {
                // SSL handshake exception
                return false;
            }
            HttpClientContext clientContext = HttpClientContext.adapt(context);
            HttpRequest request = clientContext.getRequest();
            boolean idempotent = !(request instanceof HttpEntityEnclosingRequest);
            if (idempotent) {
                // Retry if the request is considered idempotent
                return true;
            }
            return false;
        };
    }
}

问题是,为什么这个例子只有 try/finally 没有 catch ?这是否意味着所有异常都会转到 retryHandler() ?

【问题讨论】:

    标签: java apache-httpclient-4.x closeablehttpresponse


    【解决方案1】:
    1. 异常逻辑由请求执行管道内部的HttpClient实现。 HttpRequestRetryHandler 只是一种决策策略,用于确定是否会重新执行失败的请求。我承认HttpRequestRetryHandler 可能是用词不当。它实际上不是一个处理程序。

    2. 只有 I/O 异常被认为是可恢复的。运行时异常会传播给调用者。

    【讨论】:

    • 我看到了你的另一篇帖子stackoverflow.com/questions/48541329/…,所以我的理解是,最好的解决方案是使用 setServiceUnavailableRetryStrategy() 重试所有可以重试的可能。对于请求超时,猜测是你提到的I/O异常,会属于setRetryHandler()而不是setServiceUnavailableRetryStrategy()中的异常。只是为了确认。
    • 另一个问题是:上面的例子只有try/finally,你是否建议将“catch”也用于运行时异常?如果是错误的参数或空指针,重试将无济于事,但还有其他情况值得重试吗?
    • 没有。 UnavailableRetryStrategy 可用于重试消息交换,从而产生有效的 HTTP 响应消息。它不能用于从运行时异常等异常情况中恢复。
    • 上面的代码在很多方面都很糟糕。请查看 HttpClient 5.0 迁移指南中有关 HttpClient 4.5 最佳实践的部分ok2c.github.io/httpclient-migration-guide/preparation.html
    • 差不多。请确保 1. 重复使用 CloseableHttpClient 实例,2. 使用 try-with-resources 关闭 CloseableHttpResponse 实例以避免资源泄漏。
    猜你喜欢
    • 1970-01-01
    • 2014-03-03
    • 2010-09-25
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多