I'd like for the following quote in the Graceful Shutdown documentation to be clarified...

The exact way in which new requests are not permitted varies depending on the web server that is being used. Jetty, Reactor Netty, and Tomcat will stop accepting requests at the network layer.

Specifically, does "stop accepting requests at the network layer" refer to new connection requests (meaning the client would see connection refused) or new requests on existing (persistent) connections or both? If it stops accepting requests on existing connections with no requests currently being processed, are the existing connections closed immediately or after the graceful shutdown timeout?

Comment From: wilkinsona

Tomcat will reject new connections and reject a request on an existing idle connection, as covered by these two tests:

https://github.com/spring-projects/spring-boot/blob/0c036dfb8f03754d46bee6572eb0cb3bff93e8bd/spring-boot-project/spring-boot/src/test/java/org/springframework/boot/web/embedded/tomcat/TomcatServletWebServerFactoryTests.java#L600 https://github.com/spring-projects/spring-boot/blob/0c036dfb8f03754d46bee6572eb0cb3bff93e8bd/spring-boot-project/spring-boot/src/test/java/org/springframework/boot/web/embedded/tomcat/TomcatServletWebServerFactoryTests.java#L625

Jetty is similar, although not exactly the same. Like Tomcat, it will reject new connections. Unlike Tomcat, it will accept requests on an existing connection but will include a Connection: close header in the response, as covered by these two tests:

https://github.com/spring-projects/spring-boot/blob/0c036dfb8f03754d46bee6572eb0cb3bff93e8bd/spring-boot-project/spring-boot/src/test/java/org/springframework/boot/web/embedded/jetty/JettyServletWebServerFactoryTests.java#L314 https://github.com/spring-projects/spring-boot/blob/0c036dfb8f03754d46bee6572eb0cb3bff93e8bd/spring-boot-project/spring-boot/src/test/java/org/springframework/boot/web/embedded/jetty/JettyServletWebServerFactoryTests.java#L338

Reactor Netty will reject new connections as covered by this test:

https://github.com/spring-projects/spring-boot/blob/0c036dfb8f03754d46bee6572eb0cb3bff93e8bd/spring-boot-project/spring-boot/src/test/java/org/springframework/boot/web/embedded/netty/NettyReactiveWebServerFactoryTests.java#L152

We don't have a test for its behavior when a request is made on an existing connection.

Based on this information, and to answer the questions above:

does "stop accepting requests at the network layer" refer to new connection requests (meaning the client would see connection refused) or new requests on existing (persistent) connections or both?

Tomcat, Jetty, and Reactor Netty will all refuse new connections once graceful shutdown has begun.

Tomcat will refuse a request on an existing connection and should drop the connection. Jetty will respond to a request on an existing connection and instruct the client to close the connection. Reactor Netty's behavior is unknown at the moment as we don't have a test for it.

If it stops accepting requests on existing connections with no requests currently being processed, are the existing connections closed immediately or after the graceful shutdown timeout?

I believe they're closed at the soonest of:

  • a request being received on the connection
  • the keep-alive timeout elapsing
  • the graceful shutdown timeout elapsing

I'm not sure what we should document here as it's getting down into low-level container-specific behaviour. I think we could certainly say that new connections will be refused. We could then perhaps also say that handling of new requests on existing connections during the graceful shutdown period is web server-specific. My feeling is that saying anything more would be going into too much detail.

Comment From: philsttr

Thanks for the detailed info Andy! It is very helpful.

Perhaps this info could be documented in the javadocs on the webserver-specific WebServerFactory implementations. That seems like a logical place to me, since the behavior differs somewhat between implementations. The tests would then be testing documented behavior.

Then the reference guide could be kept somewhat generic, but also direct the user to the WebServerFactory implementations for exact details.

This approach would make the information more easily discoverable by those who need it, but not clutter up the reference guide too much.

What do you think?