Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Spring - server.connection-timeout not working

In my application.properties file I have...

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

I know that the file is being loaded correctly because the server is running on port 8086.

In the application I have a RestController

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

When I call the endpoint, the request never times out, it just hangs indefinitely.

Am I missing something?

NOTE: I've also been informed that Tomcat uses this field in minutes, not milliseconds (rather unusual choice IMO). I've tried setting this to server.connection-timeout=1 denoting 1 minute, but this didn't work either.

NOTE: I don't want another HTTP request to cause the previous request to time out, I want each HTTP request to timeout of it's own accord, should too much time elapse to serve the request.

like image 347
Matthew Layton Avatar asked Jun 27 '18 15:06

Matthew Layton


People also ask

How do I change my spring boot timeout?

@Transactional Timeouts One way we can implement a request timeout on database calls is to take advantage of Spring's @Transactional annotation. It has a timeout property that we can set. The default value for this property is -1, which is equivalent to not having any timeout at all.

How do I fix socket timeout exception?

Using try/catch/finally If you are a developer, so you can surround the socket connection part of your code in a try/catch/finally and handle the error in the catch. You might try connecting a second time, or try connecting to another possible socket, or simply exit the program cleanly.


2 Answers

connection-timeout does not apply to long running requests. It does apply to the initial connection, when the server waits for the client to say something.

Tomcat docs (not Spring Boot) define it as The number of milliseconds this Connector will wait, after accepting a connection, for the request URI line to be presented [...]

To test the setting server.connection-timeout=4000 I connect using netcat and I don't send any HTTP request/headers. I get:

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

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

Alternatives

1) Async

From brightinventions.pl - Spring MVC Thread Pool Timeouts:

In Spring MVC there is no way to configure a timeout unless you use async method. With async method one can use spring.mvc.async.request-timeout= to set amount of time (in milliseconds) before asynchronous request handling times out.

I've set spring.mvc.async.request-timeout=4000 and I get a timeout in the browser with this:

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

See Spring Boot REST API - request timeout?

2) Servlet filter

Another solution would be to use a servlet filter brightinventions.pl - Request timeouts in 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 Stuck Thread Detection Valve?

Tomcat has a Stuck Thread Detection Valve but I don't know if this can be configured programmatically using Spring Boot.

like image 159
Andrei Damian-Fekete Avatar answered Oct 07 '22 19:10

Andrei Damian-Fekete


From the official docs:

server.connection-timeout= # Time that connectors wait for another HTTP request before closing the connection. When not set, the connector's container-specific default is used. Use a value of -1 to indicate no (that is, an infinite) timeout.

Another ref, also mentions the same. It should work for you.

like image 34
Pankaj Singhal Avatar answered Oct 07 '22 19:10

Pankaj Singhal