弹簧 - 服务器.连接超时不起作用

2022-09-02 10:18:42

在我的文件中,我有...application.properties

server.port=8086
server.connection-timeout=15000

我知道文件正在正确加载,因为服务器正在端口8086上运行。

在应用程序中,我有一个RestController

@RestController
class TestController {
    @GetMapping()
    fun getValues(): ResponseEntity<*> {
        return someLongRunningProcessPossiblyHanging()
    }
}

当我调用端点时,请求永远不会超时,它只是无限期地挂起。

我错过了什么吗?

注意:我还被告知,Tomcat在几分钟内使用此字段,而不是毫秒(相当不寻常的选择IMO)。我尝试将其设置为表示1分钟,但这也不起作用。server.connection-timeout=1

注意:我不希望另一个HTTP请求导致前一个请求超时,我希望每个HTTP请求自行超时,如果花费太多时间来处理请求。


答案 1

connection-timeout不适用于长时间运行的请求。它确实适用于初始连接,当服务器等待客户端说出某些内容时。

Tomcat文档(不是Spring Boot)将其定义为此连接器在接受连接后等待请求URI行显示的毫秒数[...]

为了测试设置,我使用连接并且我不发送任何HTTP请求/标头。我得到:server.connection-timeout=4000netcat

$ time nc -vv localhost 1234
Connection to localhost 1234 port [tcp/*] succeeded!

real    0m4.015s
user    0m0.000s
sys     0m0.000s

选择

1) 异步

brightinventions.pl - 春季 MVC 线程池超时

在Spring MVC中,除非您使用异步方法,否则无法配置超时。使用异步方法,可以使用 spring.mvc.async.request-timeout= 来设置异步请求处理超时之前的时间量(以毫秒为单位)。

我已经设置了,我在浏览器中得到了一个超时:这样:spring.mvc.async.request-timeout=4000

@GetMapping("/test-async")
public Callable<String> getFoobar() {
   return () -> {
      Thread.sleep(12000); //this will cause a timeout
      return "foobar";
   };
}

请参阅 Spring Boot REST API - 请求超时?

2) Servlet 过滤器

另一种解决方案是使用 servlet 过滤器 brightinventions.pl - 在 Spring MVC (Kotlin) 中请求超时

override fun doFilterInternal(request: HttpServletRequest, response: HttpServletResponse, filterChain: FilterChain) {
    val completed = AtomicBoolean(false)
    val requestHandlingThread = Thread.currentThread()
    val timeout = timeoutsPool.schedule({
        if (completed.compareAndSet(false, true)) {
            requestHandlingThread.interrupt()
        }
    }, 5, TimeUnit.SECONDS)

    try {
        filterChain.doFilter(request, response)
        timeout.cancel(false)
    } finally {
        completed.set(true)
    }
}

3)雄猫卡住螺纹检测阀?

Tomcat有一个卡住的线程检测阀,但我不知道是否可以使用Spring Boot以编程方式配置。


答案 2

来自官方文档

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

另一个参考文献也提到了同样的情况。它应该为你工作。


推荐