Tomcat and Servlet 3.x: where does this timeout comes from?
If you use the Servlet 3.0 AsyncContext on Tomcat (or derived like TomEE) you can notice you get sometimes a timeout you don't expect. Where is it coming from?
Reminder: Servlet 3.x and asynchronism
In plain Servlet 3.x the asynchronous API often looks like:
AsyncContext context = request.startAsync();
doWorkInACustomThread(() -> {
// do some work
context.complete();
});
AsyncContext is the handler used to control the request processing in a custom thread (you almost always have this notion of "handler" when doing asynchronism).
If you use JAX-RS 2.0 code is simpler but relies on the exact same feature:
@GET
public void async(@Suspended AsyncResponse response) {
doInCustomThread(() -> response.resume(new MyResponse()));
}
Tomcat throws a timeout...but I didn't set it?
Out of the box you can expect Tomcat to consider the lack of timeout set (you can set it on the context) as an infinite timeout. However this has a small pitfall: after some time you can lock the container and prevent any new request to come in.
For that reason Tomcat has a configuration on the Connector to handle this timeout. It just process each seconds all the current request ("processor" in tomcat semantic) and check if they exceed their timeout. The default is however 20s which can be low for some application - in particular when using asynchonism for long processing).
Configure this asynchronous timeout
To control it just set asyncTimeout on the Tomcat connector:
<Connector port="8080" protocol="HTTP/1.1" asyncTimeout="60000" />
With this configuration the timeout will be of 1mn by default instead of 20s. It doesn't prevent you to customize it manually on the AsyncContext for particular request but the default behavior is under control this way.
If your application uses AsyncContext in a lot of different manners you should consider to setup a dedicated configuration and just set it on the context before starting your task:
AsyncContext ctx = request.startAsync();
ctx.setTimeout(45000); // 45s
myThreadPool.submit(() -> {
doProcess(request, response);
ctx.complete();
});
Conclusion
When starting to use asynchronism, getting control over the timeouts of the system is far more important than for blocking systems. Servlet 3.0 provides this control but used behind JAX-RS 2.0 it is a bit harder and often needs to rely on container specific features or integration so ensure to know how your system behaves ;).
From the same author:
In the same category: