Tiempo de espera de la placa de descanso de primavera


Me gustaría establecer los tiempos de espera de conexión para un servicio rest utilizado por mi aplicación web. Estoy usando el RestTemplate de Spring para hablar con mi servicio. He hecho algunas investigaciones y he encontrado y utilizado el xml a continuación (en mi aplicación xml) que creo que está destinado a establecer el tiempo de espera. Estoy usando Spring 3.0.

También he visto el mismo problema aquí Configuración de tiempo de espera para spring webservices con RestTemplate pero las soluciones no parecen que limpio , preferiría establezca los valores de tiempo de espera mediante 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>

Parece que sea lo que sea que establezca el ReadTimeout, obtengo lo siguiente:

Cable de red desconectado: Espera unos 20 segundos e informa de la siguiente excepción:

Org.springframework.web.cliente.resourceaccessexception: E / S error: No route to host: connect; la excepción anidada es java.net.NoRouteToHostException: No route to host: connect

Url incorrecto so 404 devuelto por rest service: Esperar alrededor de 10 segundos e informes siguientes excepción:

Org.springframework.web.cliente.HttpClientErrorException: 404 No encontrado

Mis requisitos requieren tiempos de espera más cortos, por lo que necesito poder cambiarlos. ¿Alguna idea de lo que estoy haciendo mal?

Muchas gracias.

Author: Community, 2012-12-12

5 answers

Para Bota de resorte >= 1.4

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

Para Bota de resorte

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

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

Luego en su application.properties

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

Esto funciona porque HttpComponentsClientHttpRequestFactory tiene configuradores públicosconnectionRequestTimeout, connectTimeout, y readTimeout y @ConfigurationProperties los establece para ti.


Para Spring 4.1 o Spring 5 sin Spring Boot usando @Configuration en lugar de 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/ajaxhispano.com/template/agent.layouts/content.php on line 61
2018-08-23 03:36:05

Finalmente conseguí que esto funcionara.

Creo que el hecho de que nuestro proyecto tuviera dos versiones diferentes del jar commons-httpclient no estaba ayudando. Una vez que lo resolví descubrí que puedes hacer dos cosas...

En el código se puede poner lo siguiente:

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

La primera vez que se llame a este código, establecerá el tiempo de espera para la clase HttpComponentsClientHttpRequestFactory utilizada por el RestTemplate. Por lo tanto, todas las llamadas posteriores realizadas por RestTemplate usarán la configuración de tiempo de espera definida anteriormente.

O la mejor opción es para hacer esto:

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

Donde uso la interfaz RestOperations en mi código y obtengo los valores de tiempo de espera de un archivo de propiedades.

 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/ajaxhispano.com/template/agent.layouts/content.php on line 61
2013-10-27 17:43:22

Esta pregunta es el primer enlace para una búsqueda de Spring Boot, por lo tanto, sería genial poner aquí la solución recomendada en la documentación oficial. Spring Boot tiene su propia conveniencia bean RestTemplateBuilder :

@Bean
public RestTemplate restTemplate(
        RestTemplateBuilder restTemplateBuilder) {

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

La creación manual de instancias RestTemplate es un enfoque potencialmente problemático porque otros beans configurados automáticamente no se inyectan en instancias creadas manualmente.

 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/ajaxhispano.com/template/agent.layouts/content.php on line 61
2018-09-10 23:06:00

Aquí hay una manera muy sencilla de establecer el tiempo de espera:

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/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-08-15 05:47:10

Tenía un escenario similar, pero también era necesario establecer un Proxy. La forma más sencilla que pude ver para hacer esto fue extender el SimpleClientHttpRequestFactory para la facilidad de configuración del proxy (diferentes proxies para no prod vs prod). Sin embargo, esto debería funcionar incluso si no requiere el proxy. Luego, en mi clase extendida, sobrescribo el método openConnection(URL url, Proxy proxy), usando lo mismo que la fuente , pero simplemente ajustando los tiempos de espera antes de regresar.

@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/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-10-04 15:10:10