Spring RestTemplate timeout

Chciałbym ustawić timeouty połączenia dla usługi rest używanej przez moją aplikację internetową. Używam Resttemplate Springa do rozmowy z moim serwisem. Zrobiłem kilka badań i znalazłem i użyłem xml poniżej (w mojej aplikacji xml), który moim zdaniem ma na celu ustawić timeout. Używam Spring 3.0.

Widziałem również ten sam problem tutaj Konfiguracja Timeout dla spring webservices z RestTemplate ale rozwiązania nie wydają się czyste , wolałbym ustawianie wartości timeout za pomocą Spring config

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

Wydaje mi się, że cokolwiek ustawiłem na readTimeout dostaję następujące:

Kabel Sieciowy odłączony: Czeka około 20 sekund i zgłasza następujący wyjątek:

Org.springframework.www.klient.ResourceAccessExcep tion: I/O error: No route to host: connect; zagnieżdżonym wyjątkiem jest java. net. NoRouteToHostException: No route to host: connect

Adres URL nieprawidłowy so 404 zwrócony przez serwis rest: Waits około 10 sekund i zgłasza następujący wyjątek:

Org.springframework.www.klient.HttpClientErrorException: 404 Not Found

Moje wymagania wymagają krótszych terminów, więc muszę być w stanie je zmienić. Jakieś pomysły, co robię źle?

Wielkie dzięki.
Author: Community, 2012-12-12

5 answers

Do Wiosennego Buta >= 1.4

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

Do Wiosennego Buta

@Configuration
public class AppConfig
{
    @Bean
    @ConfigurationProperties(prefix = "custom.rest.connection")
    public HttpComponentsClientHttpRequestFactory customHttpRequestFactory() 
    {
        return new HttpComponentsClientHttpRequestFactory();
    }

    @Bean
    public RestTemplate customRestTemplate()
    {
        return new RestTemplate(customHttpRequestFactory());
    }
}

Potem w Twoim application.properties

custom.rest.connection.connection-request-timeout=...
custom.rest.connection.connect-timeout=...
custom.rest.connection.read-timeout=...

To działa, ponieważ HttpComponentsClientHttpRequestFactory ma publiczne setery connectionRequestTimeout, connectTimeout, i readTimeout i @ConfigurationProperties ustawia je dla Ciebie.


Dla Sprężyna 4.1 lub sprężyna 5 Bez sprężyny używając @Configuration zamiast XML

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

        return new RestTemplate(httpRequestFactory);
    }
}
 97
Author: dustin.schultz,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-08-23 03:36:05

W końcu to zadziałało.

Myślę, że fakt, że nasz projekt miał dwie różne wersje commons-httpclient jar nie pomógł. Kiedy już to wyjaśniłem, odkryłem, że możesz zrobić dwie rzeczy...

W kodzie można umieścić:

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

Przy pierwszym wywołaniu tego kodu ustawia limit czasu dla HttpComponentsClientHttpRequestFactory klasy używanej przez RestTemplate. Dlatego wszystkie kolejne wywołania wykonywane przez RestTemplate będą używać ustawień timeout zdefiniowanych powyżej.

Albo lepszym rozwiązaniem jest aby to zrobić:

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

Gdzie używam interfejsu RestOperations w moim kodzie i pobieram wartości timeout z pliku właściwości.

 62
Author: sardo,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-10-27 17:43:22

To pytanie jest pierwszym linkiem do wyszukiwania Spring Boot, dlatego dobrze byłoby umieścić tutaj rozwiązanie zalecane w oficjalnej dokumentacji . Sprężynowy But ma swoją wygodę RestTemplateBuilder :

@Bean
public RestTemplate restTemplate(
        RestTemplateBuilder restTemplateBuilder) {

    return restTemplateBuilder
            .setConnectTimeout(500)
            .setReadTimeout(500)
            .build();
}

Ręczne tworzenie instancji RestTemplate jest potencjalnie kłopotliwym podejściem, ponieważ Inne automatycznie skonfigurowane fasolki nie są wstrzykiwane w ręcznie tworzone instancje.

 13
Author: heldev,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-09-10 23:06:00

Oto bardzo prosty sposób na ustawienie limitu czasu:

RestTemplate restTemplate = new RestTemplate(getClientHttpRequestFactory());

private ClientHttpRequestFactory getClientHttpRequestFactory() {
    int timeout = 5000;
    HttpComponentsClientHttpRequestFactory clientHttpRequestFactory =
      new HttpComponentsClientHttpRequestFactory();
    clientHttpRequestFactory.setConnectTimeout(timeout);
    return clientHttpRequestFactory;
}
 12
Author: benscabbia,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-08-15 05:47:10

Miałem podobny scenariusz, ale musiałem też ustawić Proxy. Najprostszym sposobem, jaki mogłem to zrobić, było rozszerzenie SimpleClientHttpRequestFactory dla ułatwienia ustawiania proxy(różne proxy dla non-prod vs prod). Powinno to nadal działać, nawet jeśli nie potrzebujesz serwera proxy. Następnie w mojej rozszerzonej klasie nadpisuję metodę openConnection(URL url, Proxy proxy), używając tego samego co Źródło , ale po prostu ustawiam timeouty przed powrotem.

@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;
}
 0
Author: Ryan D,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-10-04 15:10:10