【问题标题】:How do I set a timeout on Spring's AsyncRestTemplate?如何在 Spring 的 AsyncRestTemplate 上设置超时?
【发布时间】:2016-05-28 06:09:31
【问题描述】:

我在我的项目中设置了一个 RestTemplate 和一个 AsyncRestTemplate,类似于以下内容:

http://vincentdevillers.blogspot.fr/2013/10/a-best-spring-asyncresttemplate.html

我注意到连接超时实际上不起作用,除非我将 httpRequestFactory() bean 更改为以下内容:

@Bean
public ClientHttpRequestFactory httpRequestFactory() {
    HttpComponentsClientHttpRequestFactory factory = new HttpComponentsClientHttpRequestFactory(httpClient());
    factory.setConnectTimeout(DEFAULT_READ_TIMEOUT_MILLISECONDS);
    factory.setReadTimeout(DEFAULT_READ_TIMEOUT_MILLISECONDS);
    return factory;
}

如果我将 DEFAULT_READ_TIMEOUT_MILLISECONDS 设置为 5,当我使用 restTemplate 时会发生超时(如预期的那样)。但是,当我使用 AsyncRestTemplate 时,不会发生超时。我已经像 httpRequestFactory() 一样修改了 asyncHttpRequestFactory(),但没有骰子。

@Bean
public AsyncClientHttpRequestFactory asyncHttpRequestFactory() {
    HttpComponentsAsyncClientHttpRequestFactory factory = new HttpComponentsAsyncClientHttpRequestFactory(asyncHttpClient());
    factory.setConnectTimeout(DEFAULT_READ_TIMEOUT_MILLISECONDS);
    factory.setReadTimeout(DEFAULT_READ_TIMEOUT_MILLISECONDS);
    return factory;
}

这是我尝试在 Spring MVC 控制器中使用 AsyncRestTemplate 的方式:

String url = "...";
// Start the clock
long start = System.currentTimeMillis();

ListenableFuture<ResponseEntity<String>> results = asyncRestTemplate.getForEntity(url, String.class);
// Wait until the request is finished
while (!(results.isDone())) {
    Thread.sleep(10); //millisecond pause between each check
}
System.out.println("Elapsed time: " + (System.currentTimeMillis() - start));
return results.get().getBody();

如何让 AsyncRestTemplate 读取我的连接超时设置?

在相关说明中,https://spring.io/guides/gs/async-method/ 使用 @Async 和 RestTemplate 并且似乎完成了我正在寻找的内容。与 RestTemplate 相比,使用 AsyncRestTemplate 有什么优势?

【问题讨论】:

  • 查看源代码 HttpComponentsAsyncClientHttpRequestFactory 会忽略 connectTimeoutreadTimeout 属性。我不知道为什么。
  • 嗨。对不起,但有人可以解决这个问题吗?我有同样的疑问:stackoverflow.com/questions/50594022/…

标签: spring spring-mvc asynchronous resttemplate


【解决方案1】:

很像sync一:

final SimpleClientHttpRequestFactory requestFactory = new SimpleClientHttpRequestFactory();
requestFactory.setTaskExecutor(new SimpleAsyncTaskExecutor());
requestFactory.setConnectTimeout(connectTimeout);
requestFactory.setReadTimeout(readTimeout);

final AsyncRestTemplate asyncRestTemplate = new AsyncRestTemplate();
asyncRestTemplate.setAsyncRequestFactory(requestFactory); 

source code 可以看出,AsyncRestTemplate 实例是使用SimpleClientHttpRequestFactorySimpleAsyncTaskExecutor 创建的。因此,您可以使用设置了超时值的 SimpleClientHttpRequestFactory 实例来执行相同的操作。

【讨论】:

  • 可以使用一些编辑来更好地解释这如何回答问题。
【解决方案2】:

AsyncRestTemplate 依赖于 HTTP 客户端的 NIO 功能,因此您可以使用少量线程管理大量连接。要使用 @Async + RestTemplate 实现相同的目标,需要更多的资源。如果你只在几个地方做,那么它可能没问题,尽管 AsyncRestTemplate,因为它存在,对用例来说更好一点,更专业。

至于读取超时,它看起来可能是一个疏忽。随意创建一张票。快速查看this page,“HttpAsyncClient 配置”示例,显示使用:

IOReactorConfig.custom().setConnectTimeout(30000).

我想你可以快速尝试一下

【讨论】:

  • 我也有类似的问题here 使用AsyncRestTemplate 及其ListenableFuture,我对我正在尝试完成的问题几乎没有疑问。如果可能的话,你能帮我在那边吗?我发现AsyncRestTemplate 非常酷,因为它使用基于 NIO 的连接。
【解决方案3】:

我认为AsyncRestTemplate 的重点是ListenableFuture(您并没有真正使用其功能)。所以@Async 可能适合您的用例。另外,我认为results.get(5,TimeUnit.SECOND) 比使用Thread.sleep(...) 循环更有效(也更优雅),但我猜这取决于你。或者也许我错过了什么。

【讨论】:

  • 我也有类似的问题here 使用AsyncRestTemplate 及其ListenableFuture,我对我正在尝试完成的问题几乎没有疑问。如果可能的话,你能在有机会的时候帮我一下吗?非常感谢任何帮助。
  • 我认为这是一个错字。它应该是 results.get(5,TimeUnit.SECONDS) 而不是 results.get(5,TimeUnit.SECOND)
【解决方案4】:
public CloseableHttpAsyncClient asyncHttpClient() {
    IOReactorConfig ioReactorConfig = IOReactorConfig.custom().setConnectTimeout(getProperties().getConnectTimeout()).setSoTimeout(getProperties().getReadTimeout()).build()
    return  HttpAsyncClients.custom().setDefaultIOReactorConfig(ioReactorConfig).build();
}

这样,AsyncRestTemplate 超时配置就可以了。

【讨论】:

    猜你喜欢
    • 2011-04-11
    • 2019-06-02
    • 1970-01-01
    • 1970-01-01
    • 2020-11-27
    • 2014-12-14
    • 2016-05-18
    • 2015-10-16
    • 2010-11-19
    相关资源
    最近更新 更多