[英]How to set a timeout on a 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 日志。
卡住線程的 ID 和名稱可通過 JMX 中的卡住線程 ID 和卡住線程名稱屬性獲得。 這些 ID 可與標准線程 JVM MBean (java.lang:type=Threading) 一起使用,以檢索有關每個卡住線程的其他信息。
@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)
您可以設置此屬性配置
server.connection-timeout=30000
在您的 application.properties 中。 根據官方文檔說:
server.connection-timeout = # 連接器在關閉連接之前等待另一個 HTTP 請求的時間。 如果未設置,則使用連接器特定於容器的默認值。 使用值 -1 表示沒有(即無限)超時。
使用 Spring Boot 2.3 / Tomcat 9,您可以通過安裝 Tomcat StuckThreadDetectionValve
為所有傳入的 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
您可以使用未來超時:
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);
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.