【问题标题】:SimpleClientHttpRequestFactory vs HttpComponentsClientHttpRequestFactory for Http Request timeout with RestTemplate?SimpleClientHttpRequestFactory 与 HttpComponentsClientHttpRequestFactory 与 RestTemplate 的 Http 请求超时?
【发布时间】:2014-10-31 03:02:55
【问题描述】:

我正在处理一个项目,在该项目中我需要对运行 Restful 服务的服务器进行 HTTP URL 调用,该服务以JSON String 的形式返回响应。

下面是我使用future和callables的主要代码:

public class TimeoutThreadExample {

    private ExecutorService executor = Executors.newFixedThreadPool(10);
    private RestTemplate restTemplate = new RestTemplate();

    public String getData() {
        Future<String> future = executor.submit(new Task(restTemplate));
        String response = null;

        try {
            response = future.get(500, TimeUnit.MILLISECONDS);
        } catch (TimeoutException e) {
            e.printStackTrace();
        } catch (InterruptedException e) {
            e.printStackTrace();
        } catch (ExecutionException e) {
            e.printStackTrace();
        }

        return response;
    }
}

下面是我的Task 类,它实现了Callable 接口并使用RestTemplate

class Task implements Callable<String> {

    private RestTemplate restTemplate;

    public Task(RestTemplate restTemplate) {
        this.restTemplate = restTemplate;
    }

    public String call() throws Exception {

        String url = "some_url";
        String response = restTemplate.getForObject(url, String.class);

        return response;
    }
}

问题陈述:

正如您在上面看到的,我使用默认方式使用RestTemplate 执行 URL,它不使用任何 Http 请求超时,这意味着它在内部使用 -1 作为 readconnection暂停。

现在我想做的是,我想在上面的代码中使用RestTemplate 有效地设置 Http 请求超时。而且我不确定我需要使用哪个类,我可以看到 HttpComponentsClientHttpRequestFactorySimpleClientHttpRequestFactory 所以不确定我需要使用哪个类?

任何基于我上面代码的简单示例将帮助我更好地理解如何使用RestTemplate 设置 Http 请求超时。

而且我的 Http 请求超时值是否应该小于未来的超时值?

  • HttpComponentsClientHttpRequestFactorySimpleClientHttpRequestFactory。使用哪一个?
  • 我的 Http 请求超时值是否应该小于将来的超时值?

【问题讨论】:

    标签: java multithreading spring httprequest resttemplate


    【解决方案1】:

    默认情况下,RestTemplate 使用SimpleClientHttpRequestFactory,这取决于HttpURLConnection 的默认配置。

    您可以使用以下属性来配置它们:

    -Dsun.net.client.defaultConnectTimeout=TimeoutInMiliSec 
    -Dsun.net.client.defaultReadTimeout=TimeoutInMiliSec 
    

    如果你想使用HttpComponentsClientHttpRequestFactory - 它有一个SimpleClientHttpRequestFactory 没有的连接池配置。

    使用HttpComponentsClientHttpRequestFactory的示例代码:

    public class TimeoutThreadExample {
    
        private ExecutorService executor = Executors.newFixedThreadPool(10);
        private static final RestTemplate restTemplate = createRestTemplate();
    
        private static RestTemplate createRestTemplate(){
           HttpComponentsClientHttpRequestFactory requestFactory = new HttpComponentsClientHttpRequestFactory();
           requestFactory.setReadTimeout(READ_TIME_OUT);
           requestFactory.setConnectTimeout(CONNECTION_TIME_OUT);
           return new RestTemplate(requestFactory);
         }
    
        public String getData() {
            Future<String> future = executor.submit(new Task(restTemplate));
            String response = null;
    
            try {
                response = future.get(500, TimeUnit.MILLISECONDS);
            } catch (TimeoutException e) {
                e.printStackTrace();
            } catch (InterruptedException e) {
                e.printStackTrace();
            } catch (ExecutionException e) {
                e.printStackTrace();
            }
    
            return response;
        }
    }
    

    【讨论】:

    • 感谢您的建议。你知道我们应该使用哪一个吗?或者我们可以使用这两者中的任何一个?还有我如何在上面的代码库中有效地使用requestFactory?我从您的示例中了解如何使用它,但是我在上面的代码库中适合requestFactory,因为我使用 DI 来传递 RestTemplate。
    • 这取决于你,但在我们个人的大型项目中,我们使用了 HttpComponentsClientHttpRequestFactory。但我想这两种方法都不应该有任何问题。使用HttpComponentsClientHttpRequestFactory,您可以使用自己的HttpClient 配置更多选项。要在您的代码库中使用,只需传递 HttpComponentsClientHttpRequestFactory 实例,就像我在答案末尾写的代码一样
    • 当然,我正在考虑使用HttpComponentsClientHttpRequestFactory。我不明白你要我通过哪个实例?如果您可以在我的代码库上提供示例基础,那么我会更好地理解您的意思是什么?
    • 请查看更新后的答案,您需要创建一个 RestTemplate 的单例共享实例,因为它是线程安全且要创建的繁重实例。 PS:我没有测试过代码。
    • 感谢编辑。现在我很清楚你之前的意思了。最后一个问题,READ TimeoutConnection Timeout 这里有什么区别?
    【解决方案2】:

    SimpleClientHttpRequestFactory 使用标准 JDK 的 HTTP 库,因此不支持像 HttpMethod.PATCH 这样的方法。因此,最好现在使用HttpComponentsClientHttpRequestFactory,而不是以后需要时更改它。

    【讨论】: