Graceful shutdown
how Jetty does?
it adds a Shutdown Hook to JVM and JVM will execute run function of that hook before exit.
how dropwizard does?
it attach managed object's lifecycle to Jetty's lifecycle.
what should we do?
We might need to make our resources be managed first and register their lifecycle to Jetty, we also need to provide close() function for those resource. For example, let them implement AutoCloseable interface.
Both kill -15 and kill -2 can cause JVM to exit and trigger Shutdown hook.
kill -9 might be used after graceful shutdown is timeout because SIGKILL will stop JVM immediately and no shutdown hook will be executed.
shutdownGracePeriod is 30 seconds by default which means Jetty will wait at most 30 seconds to shutdown nested graceful handlers (currently, I am not sure what they are). After 30 seconds, Jetty will cancel unfinished shutdown tasks.
For managed objects, they will be closed after shutdown graceful handlers. and I don't find any time limit in this step. So It looks like Jetty will keep running until all managed objects are closed. That might be related to when we should execute kill -9 to force exit.
Source Code
Lifecycle
This is Environment class.
uploading-image-90650.png
Its lifecycle() will return an LifecycleEnvironment instance.
uploading-image-48702.png
Application run() method will call LifecycleEnvironment's manage() method.
The manage() method will create a JettyManaged Lifecycle base on given instance and add that lifecycle in the list managed by LifecycleEnvironment.
The given instance here is managed object.
Server Command
when application server starts to run, it will call ServerCommand run(). In that function, dropwizard will build a server using ServerFactory which could be specified in configuration.
Server Factory
if we don't specify server factory in configuration, DefaultServerFactory will be used.
It will buildServer.
In buildServer() method, it will call LifecycleEnvironment's attach method. That will bind lifecycles inside LifecycleEnvironment to Jetty server's lifecycle.
(As we mentioned above, LifecycleEnvironment maintains a list of Lifecycle objects and also provides a manage() function which could add managed object lifecycle to that list.)
In attach() method, the managed objects lifecycle are added into container and Jetty Server is that container. At this moment, managed objects lifecycle are attached to Jetty server's lifecycle.
Jetty Server & ShutdownThread
In buildServer() method, it calls setStopAtShutdown(true)
The register() method will register Jetty Server lifecycle to a ShutdownThread. Please notice here Jetty server is not only a Container, but also a sort of Lifecycle.
The hook() method will add ShutdownThread to JVM runtime, and the shutdownThread's run function will be executed before JVM exit.
JVM
addShutdownHook()
addShutdownHook() doc string
ShutdownThread
ShutdownThread run() method will call Jetty sever's stop(), and the stop() method will finally call Jetty server's doStop() method.
Jetty Server
Jetty doStop() method will shutdown server gracefully.
first, it will shutdown network connectors to stop accepting new connections.
second, shutdown all nested graceful handlers
third, stop the connectors
then, finally stop everything else. All managed objects will be closed in this step.
In doStop() method, it will call stop on each managed Lifecycle.
Lifecycle
Lifecycle's stop() method will call the managed object's stop()
Now what we need to do is providing stop() method for resource we want to stop when Jetty server stop.
We can use AutoCloseableManager and AutoCloseable to solve it.
AutoCloseableManager
It implements Managed.
Example
Let us use ConsumerThreadPool as an example, it is created in Mapping Service and already AutoCloseable.
ConsumerThreadPool
Its close() method
Example Step
Create an AutoCloseable instance, here it is ConsumerThreadPool
Create an new AutoCloseableManager instance using AutoCloseable instance created in the step 1.
call LifecycleEnvironment's manage() method, at this moment the lifecycle of ConsumerThreadPool will be bind to Jetty Server's lifecycle.
End