如何在Spring Boot REST API上设置超时



我有一些REST API可能需要一段时间才能执行,我想限制它们的执行持续时间。最好是,如果30秒过去了,请求没有返回,我想返回一个特定的HTTP代码/数据,并完全终止该请求。

当前代码:

@RestController
@CrossOrigin(origins = {"*"}, maxAge = 4800, allowCredentials = "false")
public class APIController {
@RequestMapping(value = "/api/myapifunc", method = RequestMethod.POST, produces = "application/json")
public ResponseEntity<?> optimize(@RequestParam(value="param1", defaultValue="")) {
// Code here
}

看起来您正在描述断路器模式。如果您可以控制客户端和服务器代码,并想探索Spring Cloud和Netflix Hysterix库,您可以查看《入门:断路器》指南。

如果您使用Apache Tomcat作为servlet容器,则可以配置Stuck Thread Detection Valve:

此阀允许检测需要很长时间处理的请求,这可能表明正在处理它的线程被卡住。此外,它还可以选择性地中断这些线程,以尝试解锁它们。

当检测到这样的请求时,其线程的当前堆栈跟踪将以WARN级别写入Tomcat日志。

通过stuckThreadId和stuckThreadNames属性中的JMX可以获得阻塞线程的ID和名称。ID可以与标准的线程JVM MBean(java.lang:type=Threading)一起使用,以检索有关每个阻塞线程的其他信息。

使用Spring Boot 2.3/Tomcat 9,您可以通过安装TomcatStuckThreadDetectionValve来设置ALL传入HTTP请求的超时。以下是您需要的Spring配置代码(它是Kotlin):

import org.apache.catalina.valves.StuckThreadDetectionValve
import org.springframework.beans.factory.annotation.Value
import org.springframework.boot.web.embedded.tomcat.TomcatServletWebServerFactory
import org.springframework.boot.web.server.WebServerFactoryCustomizer
import org.springframework.context.annotation.Bean
import org.springframework.context.annotation.Configuration
@Configuration
class RequestTimeoutConfiguration(
@Value("${app.tomcat.stuck-thread-detection.request-timeout.seconds}")
private val stuckThreadTimeoutSeconds: Int
) {
@Bean
fun stuckThreadDetectionValve() =
StuckThreadDetectionValve().apply {
threshold = stuckThreadTimeoutSeconds
interruptThreadThreshold = stuckThreadTimeoutSeconds
}
@Bean
fun stuckThreadDetectionWebServerFactoryCustomizer(valve: StuckThreadDetectionValve) =
WebServerFactoryCustomizer { factory: TomcatServletWebServerFactory ->
factory.addContextValves(valve)
}
}

那么你只需要application.properties中的属性来控制它:

app.tomcat.stuck-thread-detection.request-timeout.seconds=130
@RequestMapping(value = "/api/myapifunc", method = RequestMethod.POST, produces = 
"application/json")
public ResponseEntity<?> optimize(@RequestParam(value="param1", defaultValue="")) {
return new Callable<String>() {
@Override
public String call() throws Exception {
Thread.sleep(3000); //this will cause a timeout
return "foobar";
}
};
}

将来可以使用或注释@Timed @Transactional(timeout = 3000)

您可以使用Future timeout:

final Future<Object> submit = service.submit(new Callable<Object>() {
@Override
public Object call() throws Exception {
......YOUR CODE
return "";
}
});
try {
submit.get(3, TimeUnit.SECONDS);
} catch (Exception e) {
log.error("fail",e);
}

您可以设置此属性配置

server.connection-timeout=30000 

在application.properties中。根据官方文件显示:

server.connection timeout=#连接器在关闭连接之前等待另一个HTTP请求的时间。如果未设置,则使用连接器容器特定的默认值。使用值-1表示没有(即无限)超时。

相关内容

  • 没有找到相关文章

最新更新