简体   繁体   English

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

[英]How to set a timeout on a Spring Boot REST API?

I have some REST APIs that may take a while to execute, and I want to limit their execution duration.我有一些 REST API 可能需要一段时间才能执行,我想限制它们的执行时间。 Preferably, if 30 seconds passed and the request didn't return, I would like to return a specific HTTP code / data and terminate that request completly.最好是,如果 30 秒过去了并且请求没有返回,我想返回一个特定的 HTTP 代码/数据并完全终止该请求。

The current code:当前代码:

@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
}

It looks like you are describing the Circuit Breaker pattern .看起来您正在描述断路器模式 If you have control over both the client and server code and want to explore Spring Cloud and Netflix Hysterix libraries you can take a look at Getting Started: Circuit Breaker guide.如果您可以控制客户端和服务器代码,并且想要探索 Spring Cloud 和 Netflix Hysterix 库,您可以查看入门:断路器指南。

If you are using Apache Tomcat as your servlet container you can configure Stuck Thread Detection Valve :如果您使用 Apache Tomcat 作为 servlet 容器,您可以配置Stuck Thread Detection Valve

This valve allows to detect requests that take a long time to process, which might indicate that the thread that is processing it is stuck.这个阀允许检测需要很长时间处理的请求,这可能表明正在处理它的线程被卡住了。 Additionally it can optionally interrupt such threads to try and unblock them.此外,它可以选择性地中断此类线程以尝试解除对它们的阻止。

When such a request is detected, the current stack trace of its thread is written to Tomcat log with a WARN level.当检测到这样的请求时,其线程的当前堆栈跟踪会以 WARN 级别写入 Tomcat 日志。

The IDs and names of the stuck threads are available through JMX in the stuckThreadIds and stuckThreadNames attributes.卡住线程的 ID 和名称可通过 JMX 中的卡住线程 ID 和卡住线程名称属性获得。 The IDs can be used with the standard Threading JVM MBean (java.lang:type=Threading) to retrieve other information about each stuck thread.这些 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";
    }
  };
}

Future you can use or annotation @Timed @Transactional(timeout = 3000)未来你可以使用或注解@Timed @Transactional(timeout = 3000)

You can set this property configuration您可以设置此属性配置

 server.connection-timeout=30000 

in your application.properties.在您的 application.properties 中。 Based on official documentation says:根据官方文档说:

server.connection-timeout= # Time that connectors wait for another HTTP request before closing the connection. server.connection-timeout = # 连接器在关闭连接之前等待另一个 HTTP 请求的时间。 When not set, the connector's container-specific default is used.如果未设置,则使用连接器特定于容器的默认值。 Use a value of -1 to indicate no (that is, an infinite) timeout.使用值 -1 表示没有(即无限)超时。

With Spring Boot 2.3 / Tomcat 9, you can set a timeout for ALL incoming HTTP requests to complete by installing a Tomcat StuckThreadDetectionValve .使用 Spring Boot 2.3 / Tomcat 9,您可以通过安装 Tomcat StuckThreadDetectionValve所有传入的 HTTP 请求设置超时以完成。 Here's the Spring configuration code you'll need (it's Kotlin):这是您需要的 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)
        }
}

Then you just need the property in application.properties to control it:然后你只需要application.properties的属性来控制它:

app.tomcat.stuck-thread-detection.request-timeout.seconds=130

You can use 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);
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM