복붙노트

[SPRING] 봄 RestTemplate 시간 초과

SPRING

봄 RestTemplate 시간 초과

내 웹 응용 프로그램에서 사용하는 휴식 서비스에 대한 연결 시간 초과를 설정하고 싶습니다. 내 서비스와 이야기하기 위해 Spring의 RestTemplate을 사용하고 있습니다. 나는 약간의 연구를 해봤고, 나는 (타임 라인을 설정하기위한 것으로 생각되는) 아래 xml을 찾았다. 저는 Spring 3.0을 사용하고 있습니다.

나는 또한 같은 문제를 보았습니다 RestTemplate을 사용하여 스프링 웹 서비스를위한 타임 아웃 구성을 보았습니다. 그러나 솔루션은 깨끗하게 보이지 않습니다. 스프링 구성을 통해 타임 아웃 값을 설정하는 것을 선호합니다.

<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.ResourceAccessExcepation : I / O 오류 : 호스트에 대한 경로 없음 : 연결; 중첩 예외는 java.net.NoRouteToHostException : 호스트에 대한 경로 없음 : connect

잘못된 서비스에 의해 404가 반환 된 URL이 잘못되었습니다. 약 10 초 동안 대기하고 예외가 발생하면보고합니다.

org.springframework.web.client.HttpClientErrorException : 404를 찾을 수 없음

내 요구 사항은 짧은 시간 초과가 필요하므로 변경할 수 있어야합니다. 내가 뭘 잘못하고 있는지에 대한 아이디어는?

많은 감사합니다.

해결법

  1. ==============================

    1.스프링 부트> = 1.4

    스프링 부트> = 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가이를 설정하기 때문에 작동합니다.

    XML 대신 @Configuration을 사용하여 Spring 부트가없는 Spring 4.1 또는 Spring 5 용

    @Configuration
    public class AppConfig
    {
        @Bean
        public RestTemplate customRestTemplate()
        {
            HttpComponentsClientHttpRequestFactory httpRequestFactory = new HttpComponentsClientHttpRequestFactory();
            httpRequestFactory.setConnectionRequestTimeout(...);
            httpRequestFactory.setConnectTimeout(...);
            httpRequestFactory.setReadTimeout(...);
    
            return new RestTemplate(httpRequestFactory);
        }
    }
    
  2. ==============================

    2.나는이 일을 마침내 얻었다.

    나는이 일을 마침내 얻었다.

    저는 우리 프로젝트에 두 가지 다른 버전의 commons-httpclient jar가 있다고 생각합니다. 일단 내가 그것을 분류하면 두 가지를 할 수 있다는 것을 알았습니다 ...

    코드에는 다음을 넣을 수 있습니다.

    HttpComponentsClientHttpRequestFactory rf =
        (HttpComponentsClientHttpRequestFactory) restTemplate.getRequestFactory();
    rf.setReadTimeout(1 * 1000);
    rf.setConnectTimeout(1 * 1000);
    

    이 코드가 처음 호출되면 RestTemplate에서 사용하는 HttpComponentsClientHttpRequestFactory 클래스의 시간 초과가 설정됩니다. 따라서 RestTemplate에 의한 이후의 모든 호출은 위에 정의 된 시간 초과 설정을 사용합니다.

    또는 더 나은 방법은 이렇게하는 것입니다.

    <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>
    

    내 코드에서 RestOperations 인터페이스를 사용하고 속성 파일에서 시간 초과 값을 가져옵니다.

  3. ==============================

    3.이 질문은 스프링 부트 검색의 첫 번째 링크이므로 공식 문서에서 권장하는 해결책을 여기에 넣는 것이 좋습니다. 스프링 부트에는 자체적 인 빈 Bean이있다. RestTemplateBuilder :

    이 질문은 스프링 부트 검색의 첫 번째 링크이므로 공식 문서에서 권장하는 해결책을 여기에 넣는 것이 좋습니다. 스프링 부트에는 자체적 인 빈 Bean이있다. RestTemplateBuilder :

    @Bean
    public RestTemplate restTemplate(
            RestTemplateBuilder restTemplateBuilder) {
    
        return restTemplateBuilder
                .setConnectTimeout(500)
                .setReadTimeout(500)
                .build();
    }
    

    RestTemplate 인스턴스를 수동으로 생성하는 것은 다른 자동 구성 Bean이 수동으로 생성 된 인스턴스에 삽입되지 않기 때문에 잠재적으로 까다로운 접근 방법입니다.

  4. ==============================

    4.다음은 타임 아웃을 설정하는 아주 간단한 방법입니다.

    다음은 타임 아웃을 설정하는 아주 간단한 방법입니다.

    RestTemplate restTemplate = new RestTemplate(getClientHttpRequestFactory());
    
    private ClientHttpRequestFactory getClientHttpRequestFactory() {
        int timeout = 5000;
        HttpComponentsClientHttpRequestFactory clientHttpRequestFactory =
          new HttpComponentsClientHttpRequestFactory();
        clientHttpRequestFactory.setConnectTimeout(timeout);
        return clientHttpRequestFactory;
    }
    
  5. ==============================

    5.비슷한 시나리오가 있었지만 프록시를 설정해야했습니다. 가장 간단한 방법은 프록시 설정을 쉽게하기 위해 SimpleClientHttpRequestFactory를 확장하는 것이 었습니다 (비 프록시 대 프록시의 다른 프록시). 비록 당신이 비록 프록시를 요구하지 않더라도 이것은 여전히 ​​작동해야합니다. 그런 다음 확장 클래스에서 openConnection (URL url, 프록시 프록시) 메서드를 재정의하고 소스와 동일한 메서드를 사용하지만 반환하기 전에 시간 제한을 설정하면됩니다.

    비슷한 시나리오가 있었지만 프록시를 설정해야했습니다. 가장 간단한 방법은 프록시 설정을 쉽게하기 위해 SimpleClientHttpRequestFactory를 확장하는 것이 었습니다 (비 프록시 대 프록시의 다른 프록시). 비록 당신이 비록 프록시를 요구하지 않더라도 이것은 여전히 ​​작동해야합니다. 그런 다음 확장 클래스에서 openConnection (URL url, 프록시 프록시) 메서드를 재정의하고 소스와 동일한 메서드를 사용하지만 반환하기 전에 시간 제한을 설정하면됩니다.

    @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;
    }
    
  6. ==============================

    6.여기 내 2 센트입니다. 새로운 것은 없지만 몇 가지 설명, 개선 사항 및 최신 코드가 있습니다.

    여기 내 2 센트입니다. 새로운 것은 없지만 몇 가지 설명, 개선 사항 및 최신 코드가 있습니다.

    기본적으로 RestTemplate의 시간 제한은 무한합니다. 연결 시간 초과 및 읽기 시간 초과의 두 가지 종류의 시간 초과가 있습니다. 예를 들어, 서버에 연결할 수 있지만 데이터를 읽을 수 없습니다. 응용 프로그램이 걸려 있었고 당신은 아무 일도 일어나지 않습니다.

    요즘은 XML보다 선호되는 특수 효과를 사용할 예정입니다.

    @Configuration
    public class AppConfig {
    
        @Bean
        public RestTemplate restTemplate() {
    
            var factory = new SimpleClientHttpRequestFactory();
    
            factory.setConnectTimeout(3000);
            factory.setReadTimeout(3000);
    
            return new RestTemplate(factory);
        }
    }
    

    여기에서는 SimpleClientHttpRequestFactory를 사용하여 연결을 설정하고 시간 제한을 읽습니다. 그런 다음 RestTemplate의 생성자에 전달됩니다.

    @Configuration
    public class AppConfig {
    
        @Bean
        public RestTemplate restTemplate(RestTemplateBuilder builder) {
    
            return builder
                    .setConnectTimeout(Duration.ofMillis(3000))
                    .setReadTimeout(Duration.ofMillis(3000))
                    .build();
        }
    }
    

    두 번째 솔루션에서는 RestTemplateBuilder를 사용합니다. 또한 두 가지 방법의 매개 변수에 주목하십시오. Duration을 사용합니다. 직접 밀리 초가 걸리는 오버로드 된 메서드는 이제 더 이상 사용되지 않습니다.

  7. from https://stackoverflow.com/questions/13837012/spring-resttemplate-timeout by cc-by-sa and MIT license