Spring RestTemplate 超时
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/13837012/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Spring RestTemplate timeout
提问by sardo
I would like to set the connection timeouts for a rest service used by my web application. I'm using Spring's RestTemplate to talk to my service. I've done some research and I've found and used the xml below (in my application xml) which I believe is meant to set the timeout. I'm using Spring 3.0.
我想为我的 Web 应用程序使用的休息服务设置连接超时。我正在使用 Spring 的 RestTemplate 与我的服务对话。我做了一些研究,发现并使用了下面的 xml(在我的应用程序 xml 中),我认为它是用来设置超时的。我正在使用 Spring 3.0。
I've also seen the same problem here Timeout configuration for spring webservices with RestTemplatebut the solutions don't seem that clean, I'd prefer to set the timeout values via Spring config
我在这里也看到了同样的问题,使用 RestTemplate 的 spring webservices 超时配置,但解决方案似乎不太干净,我更喜欢通过 Spring 配置设置超时值
<bean id="RestOperations" class="org.springframework.web.client.RestTemplate">
<constructor-arg>
<bean class="org.springframework.http.client.CommonsClientHttpRequestFactory">
<property name="readTimeout" value="${restURL.connectionTimeout}" />
</bean>
</constructor-arg>
</bean>
It seems whatever I set the readTimeout to be I get the following:
似乎无论我将 readTimeout 设置为什么,我都会得到以下信息:
Network cable disconnected:Waits about 20 seconds and reports following exception:
网线断开:等待约 20 秒并报告以下异常:
org.springframework.web.client.ResourceAccessExcep tion: I/O error: No route to host: connect; nested exception is java.net.NoRouteToHostException: No route to host: connect
org.springframework.web.client.ResourceAccessException: I/O error: No route to host: connect; 嵌套异常是 java.net.NoRouteToHostException: No route to host: connect
Url incorrect so 404 returned by rest service:Waits about 10 seconds and reports following exception:
Url 不正确所以 404 由休息服务返回:等待大约 10 秒并报告以下异常:
org.springframework.web.client.HttpClientErrorException: 404 Not Found
org.springframework.web.client.HttpClientErrorException: 404 未找到
My requirements require shorter timeouts so I need to be able to change these. Any ideas as to what I'm doing wrong?
我的要求需要更短的超时,所以我需要能够改变这些。关于我做错了什么的任何想法?
Many thanks.
非常感谢。
采纳答案by sardo
I finally got this working.
我终于得到了这个工作。
I think the fact that our project had two different versions of the commons-httpclient jar wasn't helping. Once I sorted that out I found you can do two things...
我认为我们的项目有两个不同版本的 commons-httpclient jar 的事实并没有帮助。一旦我解决了这个问题,我发现你可以做两件事......
In code you can put the following:
在代码中,您可以输入以下内容:
HttpComponentsClientHttpRequestFactory rf =
(HttpComponentsClientHttpRequestFactory) restTemplate.getRequestFactory();
rf.setReadTimeout(1 * 1000);
rf.setConnectTimeout(1 * 1000);
The first time this code is called it will set the timeout for the HttpComponentsClientHttpRequestFactoryclass used by the RestTemplate. Therefore, all subsequent calls made by RestTemplatewill use the timeout settings defined above.
第一次遇到这种代码被称为它将设置了超时HttpComponentsClientHttpRequestFactory由所使用的类RestTemplate。因此,所有后续调用都RestTemplate将使用上面定义的超时设置。
Or the better option is to do this:
或者更好的选择是这样做:
<bean id="RestOperations" class="org.springframework.web.client.RestTemplate">
<constructor-arg>
<bean class="org.springframework.http.client.HttpComponentsClientHttpRequestFactory">
<property name="readTimeout" value="${application.urlReadTimeout}" />
<property name="connectTimeout" value="${application.urlConnectionTimeout}" />
</bean>
</constructor-arg>
</bean>
Where I use the RestOperationsinterface in my code and get the timeout values from a properties file.
我RestOperations在代码中使用接口并从属性文件中获取超时值。
回答by dustin.schultz
For Spring Boot >= 1.4
对于Spring Boot >= 1.4
@Configuration
public class AppConfig
{
@Bean
public RestTemplate restTemplate(RestTemplateBuilder restTemplateBuilder)
{
return restTemplateBuilder
.setConnectTimeout(...)
.setReadTimeout(...)
.build();
}
}
For Spring Boot <= 1.3
对于Spring Boot <= 1.3
@Configuration
public class AppConfig
{
@Bean
@ConfigurationProperties(prefix = "custom.rest.connection")
public HttpComponentsClientHttpRequestFactory customHttpRequestFactory()
{
return new HttpComponentsClientHttpRequestFactory();
}
@Bean
public RestTemplate customRestTemplate()
{
return new RestTemplate(customHttpRequestFactory());
}
}
then in your application.properties
然后在你的 application.properties
custom.rest.connection.connection-request-timeout=...
custom.rest.connection.connect-timeout=...
custom.rest.connection.read-timeout=...
This works because HttpComponentsClientHttpRequestFactoryhas public setters connectionRequestTimeout, connectTimeout, and readTimeoutand @ConfigurationPropertiessets them for you.
这是有效的,因为HttpComponentsClientHttpRequestFactory有公共 setter connectionRequestTimeout、connectTimeout和readTimeout并@ConfigurationProperties为您设置它们。
For Spring 4.1 or Spring 5 without Spring Bootusing @Configurationinstead of XML
对于没有 Spring Boot 的 Spring 4.1 或 Spring 5使用@Configuration代替XML
@Configuration
public class AppConfig
{
@Bean
public RestTemplate customRestTemplate()
{
HttpComponentsClientHttpRequestFactory httpRequestFactory = new HttpComponentsClientHttpRequestFactory();
httpRequestFactory.setConnectionRequestTimeout(...);
httpRequestFactory.setConnectTimeout(...);
httpRequestFactory.setReadTimeout(...);
return new RestTemplate(httpRequestFactory);
}
}
回答by heldev
This question is the first link for a Spring Boot search, therefore, would be great to put here the solution recommended in the official documentation. Spring Boot has its own convenience bean RestTemplateBuilder:
这个问题是 Spring Boot 搜索的第一个链接,因此,将官方文档中推荐的解决方案放在这里会很棒。Spring Boot 有自己的便利 bean RestTemplateBuilder:
@Bean
public RestTemplate restTemplate(
RestTemplateBuilder restTemplateBuilder) {
return restTemplateBuilder
.setConnectTimeout(Duration.ofSeconds(500))
.setReadTimeout(Duration.ofSeconds(500))
.build();
}
Manual creation of RestTemplate instances is a potentially troublesome approach because other auto-configured beans are not being injected in manually created instances.
手动创建 RestTemplate 实例是一种潜在的麻烦方法,因为其他自动配置的 bean 不会被注入到手动创建的实例中。
回答by Jan Bodnar
Here are my 2 cents. Nothing new, but some explanations, improvements and newer code.
这是我的 2 美分。没有什么新东西,但有一些解释、改进和更新的代码。
By default, RestTemplatehas infinite timeout.
There are two kinds of timeouts: connection timeout and read time out. For instance, I could connect to the server but I could not read data. The application was hanging and you have no clue what's going on.
默认情况下,RestTemplate具有无限超时。有两种超时:连接超时和读取超时。例如,我可以连接到服务器,但无法读取数据。应用程序挂了,你不知道发生了什么。
I am going to use annotations, which these days are preferred over XML.
我将使用批注,现在它比 XML 更受欢迎。
@Configuration
public class AppConfig {
@Bean
public RestTemplate restTemplate() {
var factory = new SimpleClientHttpRequestFactory();
factory.setConnectTimeout(3000);
factory.setReadTimeout(3000);
return new RestTemplate(factory);
}
}
Here we use SimpleClientHttpRequestFactoryto set the connection and read time outs.
It is then passed to the constructor of RestTemplate.
这里我们SimpleClientHttpRequestFactory用来设置连接和读取超时。然后将其传递给 的构造函数RestTemplate。
@Configuration
public class AppConfig {
@Bean
public RestTemplate restTemplate(RestTemplateBuilder builder) {
return builder
.setConnectTimeout(Duration.ofMillis(3000))
.setReadTimeout(Duration.ofMillis(3000))
.build();
}
}
In the second solution, we use the RestTemplateBuilder. Also notice the parameters of the two methods: they take Duration. The overloaded methods that take directly milliseconds are now deprecated.
在第二种解决方案中,我们使用RestTemplateBuilder. 还要注意这两个方法的参数:它们采用Duration. 现在不推荐使用直接需要毫秒的重载方法。
EditTested with Spring Boot 2.1.0 and Java 11.
使用 Spring Boot 2.1.0 和 Java 11 进行编辑测试。
回答by benscabbia
Here is a really simple way to set the timeout:
这是设置超时的一种非常简单的方法:
RestTemplate restTemplate = new RestTemplate(getClientHttpRequestFactory());
private ClientHttpRequestFactory getClientHttpRequestFactory() {
int timeout = 5000;
HttpComponentsClientHttpRequestFactory clientHttpRequestFactory =
new HttpComponentsClientHttpRequestFactory();
clientHttpRequestFactory.setConnectTimeout(timeout);
return clientHttpRequestFactory;
}
回答by Ryan D
I had a similar scenario, but was also required to set a Proxy. The simplest way I could see to do this was to extend the SimpleClientHttpRequestFactoryfor the ease of setting the proxy (different proxies for non-prod vs prod). This should still work even if you don't require the proxy though. Then in my extended class I override the openConnection(URL url, Proxy proxy)method, using the same as the source, but just setting the timeouts before returning.
我有一个类似的场景,但也需要设置一个代理。我能看到的最简单的方法是扩展SimpleClientHttpRequestFactory以方便设置代理(非生产与生产的不同代理)。即使您不需要代理,这也应该仍然有效。然后在我的扩展类中,我覆盖了该openConnection(URL url, Proxy proxy)方法,使用与source相同的方法,但只是在返回之前设置超时。
@Override
protected HttpURLConnection openConnection(URL url, Proxy proxy) throws IOException {
URLConnection urlConnection = proxy != null ? url.openConnection(proxy) : url.openConnection();
Assert.isInstanceOf(HttpURLConnection.class, urlConnection);
urlConnection.setConnectTimeout(5000);
urlConnection.setReadTimeout(5000);
return (HttpURLConnection) urlConnection;
}
回答by Tasos Zervos
To expand on benscabbia'sanswer:
扩展benscabbia的回答:
private RestTemplate restCaller = new RestTemplate(getClientHttpRequestFactory());
private ClientHttpRequestFactory getClientHttpRequestFactory() {
int connectionTimeout = 5000; // milliseconds
int socketTimeout = 10000; // milliseconds
RequestConfig config = RequestConfig.custom()
.setConnectTimeout(connectionTimeout)
.setConnectionRequestTimeout(connectionTimeout)
.setSocketTimeout(socketTimeout)
.build();
CloseableHttpClient client = HttpClientBuilder
.create()
.setDefaultRequestConfig(config)
.build();
return new HttpComponentsClientHttpRequestFactory(client);
}

