Spring RestTemplate 시간 초과
내 웹 애플리케이션에서 사용하는 나머지 서비스에 대한 연결 시간 제한을 설정하고 싶습니다. Spring의 RestTemplate을 사용하여 내 서비스와 대화하고 있습니다. 나는 약간의 조사를 해왔고 시간 제한을 설정하는 것으로 생각되는 아래 xml (내 응용 프로그램 xml에서)을 찾아서 사용했습니다. 저는 Spring 3.0을 사용하고 있습니다.
또한 RestTemplate을 사용하여 Spring 웹 서비스에 대한 Timeout 구성 에서 동일한 문제를 보았지만 솔루션이 깨끗 하지 않은 것 같습니다. 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>
readTimeout을 설정하면 다음과 같이 표시됩니다.
네트워크 케이블 연결 끊김 : 약 20 초 동안 대기하고 다음 예외를보고합니다.
org.springframework.web.client.ResourceAccessExcep tion : I / O error : No route to host : connect; 중첩 된 예외는 java.net.NoRouteToHostException : 호스트에 대한 경로 없음 : connect
URL이 잘못되어 나머지 서비스에서 404가 반환 됨 : 약 10 초 동안 대기하고 다음 예외를보고합니다.
org.springframework.web.client.HttpClientErrorException : 404 찾을 수 없음
내 요구 사항에는 더 짧은 시간 제한이 필요하므로이를 변경할 수 있어야합니다. 내가 뭘 잘못하고 있는지에 대한 아이디어가 있습니까?
감사합니다.
들어 봄 부팅> 1.4 =
@Configuration
public class AppConfig
{
@Bean
public RestTemplate restTemplate(RestTemplateBuilder restTemplateBuilder)
{
return restTemplateBuilder
.setConnectTimeout(...)
.setReadTimeout(...)
.build();
}
}
들어 봄 부팅 <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());
}
}
다음 당신의 application.properties
custom.rest.connection.connection-request-timeout=...
custom.rest.connection.connect-timeout=...
custom.rest.connection.read-timeout=...
때문에이 작품 HttpComponentsClientHttpRequestFactory
공개 세터을 가지고 connectionRequestTimeout
, connectTimeout
그리고 readTimeout
그리고 @ConfigurationProperties
당신을 위해 세트를.
들어 봄 부팅없이 스프링 4.1 스프링 (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);
}
}
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...
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 HttpComponentsClientHttpRequestFactory
class used by the RestTemplate
. Therefore, all subsequent calls made by RestTemplate
will use the timeout settings defined above.
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 RestOperations
interface in my code and get the timeout values from a properties file.
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:
@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.
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;
}
Here are my 2 cents. Nothing new, but some explanations, improvements and newer code.
By default, RestTemplate
has 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.
I am going to use annotations, which these days are preferred over 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 SimpleClientHttpRequestFactory
to set the connection and read time outs. It is then passed to the constructor of 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.
Edit Tested with Spring Boot 2.1.0 and Java 11.
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 SimpleClientHttpRequestFactory
for 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.
@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;
}
참고URL : https://stackoverflow.com/questions/13837012/spring-resttemplate-timeout
'Programming' 카테고리의 다른 글
자바 : CPU 코어에 따라 스레드를 확장하는 방법은 무엇입니까? (0) | 2020.08.17 |
---|---|
* 문자 *로 너비 지정 (0) | 2020.08.17 |
SOAP 메시지와 WSDL의 차이점은 무엇입니까? (0) | 2020.08.15 |
프로덕션에서 Rails 콘솔 실행 (0) | 2020.08.15 |
문자열에서 숫자를 추출하고 정수 배열을 얻는 방법은 무엇입니까? (0) | 2020.08.15 |