Saltar al contenido

RestTemplate establece el tiempo de espera por solicitud

Tenemos la mejor solución que encontramos online. Deseamos que te sea de ayuda y si quieres compartir algo que nos pueda ayudar a mejorar hazlo con libertad.

Solución:

Opción 1: más de una RestTemplate

Si está cambiando las propiedades de las conexiones creadas, necesitará tener una RestTemplate por configuración. Tuve este mismo problema recientemente y tuve dos versiones de RestTemplate, uno para “tiempo de espera corto” y otro para “tiempo de espera prolongado”. Dentro de cada grupo (corto / largo) pude compartir que RestTemplate.

Hacer que sus llamadas cambien la configuración del tiempo de espera, creen una conexión y esperen lo mejor es una condición de carrera que está a punto de suceder. Jugaría esto seguro y crearía más de uno. RestTemplate.

Ejemplo:

@Configuration
public class RestTemplateConfigs 
    @Bean("shortTimeoutRestTemplate")
    public RestTemplate shortTimeoutRestTemplate() 
       // Create template with short timeout, see docs.
    
    @Bean("longTimeoutRestTemplate")
    public RestTemplate longTimeoutRestTemplate() 
       // Create template with short timeout, see docs.
    

Y luego puede conectarlos a sus servicios según sea necesario:

@Service
public class MyService 
    private final RestTemplate shortTimeout;
    private final RestTemplate longTimeout;

    @Autowired
    public MyService(@Qualifier("shortTimeoutRestTemplate") RestTemplate shortTimeout, 
                     @Qualifier("longTimeoutRestTemplate") RestTemplate longTimeout) 
        this.shortTimeout = shortTimeout;
        this.longTimeout = longTimeout;
    

    // Your business methods here...

Opción 2: envolver llamadas en un disyuntor

Si está llamando a servicios externos, probablemente debería usar un disyuntor para esto. Spring Boot funciona bien con Hystrix, una implementación popular del patrón de disyuntor. Con hystrix puede controlar la reserva para cada servicio al que llama y los tiempos de espera.

Suponga que tiene dos opciones para el Servicio A: 1) Barato pero a veces lento 2) Caro pero rápido. Puede usar Hystrix para renunciar a Barato / Lento y usar Caro / Rápido cuando realmente lo necesite. O puede no tener una copia de seguridad y simplemente hacer que Hystrix llame a un método que proporcione un valor predeterminado razonable.

Ejemplo no probado:

@EnableCircuitBreaker
public class MyApp 
    public static void main(String[] args) 
        SpringApplication.run(MyApp .class, args);
    


@Service
public class MyService 
    private final RestTemplate restTemplate;

    public BookService(RestTemplate rest) 
        this.restTemplate = rest;
    

    @HystrixCommand(
        fallbackMethod = "fooMethodFallback",
        commandProperties =  
            @HystrixProperty(
                 name = "execution.isolation.thread.timeoutInMilliseconds", 
                 value="5000"
            )
        
    )
    public String fooMethod() 
        // Your logic here.
        restTemplate.exchange(...); 
    

    public String fooMethodFallback(Throwable t) 
        log.error("Fallback happened", t);
        return "Sensible Default Here!"
    

El método alternativo también tiene opciones. Podrías anotar ese método con @HystrixCommand e intente otra llamada de servicio. O bien, podría simplemente proporcionar un valor predeterminado razonable.

Supongo que desea leer los tiempos de espera en caso de que la respuesta tarde demasiado.

Una posible solución sería implementar el tiempo de espera usted mismo cancelando la solicitud si no se ha completado en el tiempo especificado.

Para lograr esto, puede usar un AsyncRestTemplate en su lugar, que tiene soporte incorporado para operaciones asincrónicas como tiempo de espera y cancelación.

Esto le da más control sobre el tiempo de espera para cada solicitud, por ejemplo:

ListenableFuture> future =
                asyncRestTemplate.getForEntity(url, Potato.class);

ResponseEntity response = future.get(5, TimeUnit.SECONDS);

Cambio de tiempos de espera de fábrica después RestTemplate La inicialización es solo una condición de carrera a la espera de que ocurra (como explicó Todd). RestTemplate fue realmente diseñado para construirse con tiempos de espera preconfigurados y para que esos tiempos de espera permanezcan intactos después de la inicialización. Si utiliza Apache HttpClient entonces sí, puedes establecer un RequestConfig por solicitud y ese es el diseño adecuado en mi opinión.

Ya estamos usando RestTemplate en todas partes de nuestro proyecto y realmente no podemos permitirnos la refactorización en este momento, ya que se produciría un cambio de cliente http.

Por ahora terminé con un RestTemplate solución de agrupación, creé una clase llamada RestTemplateManager y le di toda la responsabilidad de crear plantillas y agruparlas. Este administrador tiene un caché local de plantillas agrupadas por servicio y readTimeout. Imagine un mapa de hash de caché con la siguiente estructura:

ServiceA | 1000 -> RestTemplate

ServiceA | 3000 -> RestTemplate

ServiceB | 1000 -> RestTemplate

El número en el key es el readTimeout en milisegundos (key se puede adaptar para admitir más de readTimeout más adelante). Entonces, cuando ServiceA solicita una plantilla con un tiempo de espera de lectura de 1000 ms, el administrador devolverá la instancia en caché, si no existe, se creará y devolverá.

En este enfoque, me salvé de predefinir RestTemplates, solo tengo que solicitar un RestTemplate al administrador anterior. Esto también mantiene las inicializaciones al mínimo.

Esto funcionará hasta que tenga tiempo de deshacerme de RestTemplate y usar una solución más apropiada.

Recuerda algo, que tienes la capacidad de parafrasear tu experiencia si te fue de ayuda.

¡Haz clic para puntuar esta entrada!
(Votos: 0 Promedio: 0)



Utiliza Nuestro Buscador

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *