SuspendApp with Ktor
There are some cases where it is convenient to gracefully shutdown a Ktor server. Basically, it is about giving some time to the server to finish some pending processing before turning it off.
Kubernetes is a good example of this need. When we're working with Kubernetes we often need to
support Graceful Shutdown.
Kubernetes sends SIGTERM
to our Pod to signal it needs to gracefully shutdown.
However, there is an issue which doesn't allow us to immediately shutdown when we receive SIGTERM
from Kubernetes.
Our pod can still receive traffic after SIGTERM
, so we need to apply additional back-pressure to delay graceful
shutdown.
More information on this can be found in this blog by Phil Pearl, and on learnk8s.io.
The module suspendapp-ktor
provides a server
constructor that lifts the Ktor ApplicationEngine
in to a Resource,
representing the Engine running an Application
(i.e Netty
) while supporting auto-reload.
The example below introduces graceful shutdown for Kubernetes;
we additionally use awaitCancellation
to await SIGTERM
, SIGINT
or other shutdown hooks.
fun main() = SuspendApp {
resourceScope {
server(Netty) {
routing {
get("/ping") {
call.respond("pong")
}
}
}
awaitCancellation()
}
}
When the release
function of our ApplicationEngine
is called, there is a wait
period before the beginning of the stop
process (defaulted to 30.seconds
), this gives Kubernetes enough time to do all its network management before we shut down.
Two more parameters are available:
grace
which sets the number of seconds during which already inflight requests are allowed to continue before the shutdown process begins,timeout
which sets the number of seconds after which the server will be forceably shutdown.
In the case that Ktor server is set in
development mode, the wait
period is ignored.