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-секундный тайм-аут.