Spring Boot REST API - время ожидания запроса?

У меня есть служба загрузки REST Spring, которая иногда вызывает услуги сторонних поставщиков как часть запроса. Я хотел бы установить тайм-аут для всех моих ресурсов (пусть говорят 5 секунд), так что если любая обработка запроса (целая цепочка, от входящего ответа) занимает более 5 секунд, мои контроллеры отвечают HTTP 503 вместо фактического ответа, Было бы замечательно, если бы это было просто свойство Spring, например установка

spring.mvc.async.request-timeout=5000

но мне не повезло с этим. Я также попытался расширить WebMvcConfigurationSupport и переопределить configureAsyncSupport:

@Override
public void configureAsyncSupport(final AsyncSupportConfigurer configurer) {
    configurer.setDefaultTimeout(5000);
    configurer.registerCallableInterceptors(timeoutInterceptor());
}

@Bean
public TimeoutCallableProcessingInterceptor timeoutInterceptor() {
    return new TimeoutCallableProcessingInterceptor();
}

без везения.

Я подозреваю, что мне приходится вручную набирать все мои сторонние звонки, и если они задерживаются слишком долго, выбросьте исключение тайм-аута. Это правильно? Или есть ли более простое целостное решение, которое охватывает все мои конечные точки запроса?

Ответ 1

Вам нужно вернуть Callable<> если вы хотите, чтобы spring.mvc.async.request-timeout=5000 работал.

@RequestMapping(method = RequestMethod.GET)
public Callable<String> getFoobar() throws InterruptedException {
    return new Callable<String>() {
        @Override
        public String call() throws Exception {
            Thread.sleep(8000); //this will cause a timeout
            return "foobar";
        }
    };
}

Ответ 2

Аннотация @Transactional принимает параметр timeout, в котором вы можете указать время ожидания в секундах для определенного метода в @RestController.

@RequestMapping(value = "/method",
    method = RequestMethod.POST,
    produces = MediaType.APPLICATION_JSON_VALUE)
@Timed
@Transactional(timeout = 120)

Ответ 3

если вы используете RestTemplate, чем использовать следующий код для реализации тайм-аутов

@Bean
public RestTemplate restTemplate() {
    return new RestTemplate(clientHttpRequestFactory());
}

private ClientHttpRequestFactory clientHttpRequestFactory() {
    HttpComponentsClientHttpRequestFactory factory = new HttpComponentsClientHttpRequestFactory();
    factory.setReadTimeout(2000);
    factory.setConnectTimeout(2000);
    return factory;
}}

Конфигурация xml

<bean class="org.springframework.web.client.RestTemplate">
<constructor-arg>
    <bean class="org.springframework.http.client.HttpComponentsClientHttpRequestFactory"
        p:readTimeout="2000"
        p:connectTimeout="2000" />
</constructor-arg>

Ответ 4

Я бы посоветовал вам взглянуть на стартер Spring Cloud Netflix Hystrix для обработки потенциально ненадежных/медленных удаленных вызовов. Он реализует шаблон автоматического выключателя, который предназначен именно для этой вещи.

Подробнее см. официальные документы.

Ответ 5

Вы можете попробовать server.connection-timeout=5000 в своем приложении application.properties. В официальной документации :

server.connection-timeout = # Время в миллисекундах, которое будет дождитесь следующего HTTP-запроса перед закрытием соединения. Когда нет set, будет использоваться значение по умолчанию для контейнера-контейнера. Использовать значение -1 для указания отсутствия (т.е. бесконечного) тайм-аута.

С другой стороны, вы можете использовать тайм-ауты на стороне клиента, используя шаблон Circuit Breaker, как я уже описал в своем ответе здесь: fooobar.com/questions/1000318/...

Ответ 6

В файлах свойств Spring вы не можете просто указать число для этого свойства. Вам также необходимо указать единицу. Таким образом, вы можете сказать spring.mvc.async.request-timeout=5000ms или spring.mvc.async.request-timeout=5000ms spring.mvc.async.request-timeout=5s, оба из которых дадут вам 5-секундный тайм-аут.