我有一个Spring Boot REST服务,有时会将第三方服务作为请求的一部分。我想在我的所有资源上设置超时(让我们说5秒),这样如果任何请求处理(整个链,从传入到响应)花费的时间超过5秒,我的控制器会用HTTP 503响应实际的回应。如果这只是一个Spring属性,例如设置
,那将是非常棒的code
但是我还没有运气。我也尝试过扩展WebMvcConfigurationSupport并覆盖configureAsyncSupport:
<h3 id="SectionID">Section With ID</h3>
没有任何运气。
我怀疑我必须手动计算所有第三方呼叫的时间,如果花费的时间太长,则抛出超时异常。是对的吗?或者是否有涵盖我所有请求端点的更简单,整体的解决方案?
答案 0 :(得分:16)
如果您希望$csv | select vds, protgroup, vlan, ports | Export-Csv $csv
正常工作,则需要返回Callable<>
。
spring.mvc.async.request-timeout=5000
答案 1 :(得分:7)
@Transactional批注带有一个超时参数,您可以在其中为@RestController中的特定方法指定以秒为单位的超时
@RequestMapping(value = "/method",
method = RequestMethod.POST,
produces = MediaType.APPLICATION_JSON_VALUE)
@Timed
@Transactional(timeout = 120)
答案 2 :(得分:4)
由于server.connection-timeout=5000
已弃用,因此需要 Spring Boot 2.2 的新答案。每个服务器的行为都不同,因此建议使用服务器特定的属性。
如果尚未使用Jetty或其他工具重新配置,SpringBoot默认会嵌入Tomcat。 使用服务器特定的应用程序属性,例如server.tomcat.connection-timeout
或server.jetty.idle-timeout
。
答案 3 :(得分: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 :(得分:3)
Resilience4j 是一个主要用于管理远程通信容错的库。它的 TimeLimiter 模块正是我们在这里感兴趣的。
首先,我们必须在我们的项目中包含 resilience4j-timelimiter 依赖项:
<dependency>
<groupId>io.github.resilience4j</groupId>
<artifactId>resilience4j-timelimiter</artifactId>
<version>1.6.1</version>
</dependency>
接下来,让我们定义一个简单的 TimeLimiter,它的超时持续时间为 500 毫秒:
private TimeLimiter ourTimeLimiter = TimeLimiter.of(TimeLimiterConfig.custom()
.timeoutDuration(Duration.ofMillis(500)).build());
这可以很容易地从外部配置。
@GetMapping("/author/resilience4j")
public Callable<String> getWithResilience4jTimeLimiter(@RequestParam String title) {
return TimeLimiter.decorateFutureSupplier(ourTimeLimiter, () ->
CompletableFuture.supplyAsync(() -> {
bookRepository.wasteTime();
return bookRepository.findById(title)
.map(Book::getAuthor)
.orElse("No book found for this title.");
}));
}
TimeLimiter 与 @Transactional 解决方案相比具有多项优势。即,它支持亚秒级精度和超时响应的即时通知。但是,它仍然必须手动包含在所有需要超时的端点中,它需要一些冗长的包装代码,并且它产生的错误仍然是一个通用的 500 HTTP 错误。此外,它需要返回一个 Callable 而不是原始的 String。
TimeLimiter 仅包含来自 Resilience4j 的功能子集,并与 Circuit Breaker 模式很好地接口。
您也可以使用注解来声明 TimeLimiter, here you have an example.
答案 5 :(得分:2)
我建议您查看Spring Cloud Netflix Hystrix启动器来处理可能不可靠/慢速的远程调用。它实现了断路器模式,适用于这种类型的东西。
答案 6 :(得分:2)
您可以在application.properties中尝试server.connection-timeout=5000
。来自official documentation:
server.connection-timeout =#连接器将以毫秒为单位的时间 在关闭连接之前等待另一个HTTP请求。什么时候不 set,将使用连接器的特定于容器的默认值。用一个 值-1表示无(即无限)超时。
另一方面,您可能希望使用Circuit Breaker模式处理客户端的超时,正如我在此处的回答中所述:https://stackoverflow.com/a/44484579/2328781
答案 7 :(得分:0)
我觉得没有答案能真正解决问题。我认为您需要告诉Spring Boot的嵌入式服务器什么是处理请求的最长时间。我们究竟如何做到这一点取决于所使用的嵌入式服务器的类型。
对于Undertow,可以执行以下操作:
@Component
class WebServerCustomizer : WebServerFactoryCustomizer<UndertowServletWebServerFactory> {
override fun customize(factory: UndertowServletWebServerFactory) {
factory.addBuilderCustomizers(UndertowBuilderCustomizer {
it.setSocketOption(Options.READ_TIMEOUT, 5000)
it.setSocketOption(Options.WRITE_TIMEOUT, 25000)
})
}
}
Spring Boot官方文档:https://docs.spring.io/spring-boot/docs/2.2.0.RELEASE/reference/html/howto.html#howto-configure-webserver
答案 8 :(得分:0)
您可以为Springboot REST服务配置异步线程执行器。 setKeepAliveSeconds()应该考虑请求链的执行时间。设置ThreadPoolExecutor的keep-alive秒。默认值为60。可以在运行时修改此设置,例如通过JMX。
@Bean(name="asyncExec")
public Executor asyncExecutor()
{
ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
executor.setCorePoolSize(3);
executor.setMaxPoolSize(3);
executor.setQueueCapacity(10);
executor.setThreadNamePrefix("AsynchThread-");
executor.setAllowCoreThreadTimeOut(true);
executor.setKeepAliveSeconds(10);
executor.initialize();
return executor;
}
然后您可以按以下方式定义REST端点
@Async("asyncExec")
@PostMapping("/delayedService")
public CompletableFuture<String> doDelay()
{
String response = service.callDelayedService();
return CompletableFuture.completedFuture(response);
}
答案 9 :(得分:-1)
在Spring属性文件中,您不能仅为此属性指定数字。您还需要指定一个单位。因此,您可以说spring.mvc.async.request-timeout=5000ms
或spring.mvc.async.request-timeout=5s
,两者都会给您5秒钟的超时时间。