Programming

Spring RestTemplate 시간 초과

procodes 2020. 8. 15. 15:36
반응형

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

반응형