Gracefully shutdown Go API server connected to Database.
Go offers scalable and robust mechanism for creating API servers. As most of APIs talk to some database, on a scaled infrastructure receiving a lot of requests per second, it is important to shutdown gracefully in order to prevent goroutine leaks. This means closing two things in our case.
HTTP Server and DB connection.
Go net/http
package offers Shutdown
function to gracefully shutdown your http server. https://godoc.org/net/http#Server.Shutdown.
Go database/sql
package offers Close
function to gracefully close the connection to sql. https://godoc.org/database/sql#DB.Close
1) Create a minimal HTTP API service using a Database.
2) Change your server function “srv.ListenAndServe()” to run in a goroutine.
go func() {
panic(srv.ListenAndServe())
}()
This is done to ensure that main
will not exit when srv.ListenAndServe()
returns on stop signal and waits for database to be closed. Note that we’re using panic
rather than log.Fatal
to capture errors from srv.ListenAndServe()
in order to be able to call defer in next steps.
3) Create a channel to receive stop signals.
stop := make(chan os.Signal, 1)
signal.Notify(stop, os.Interrupt)
signal.Notify(stop, syscall.SIGTERM)
Bonus point: If you’re using kubernetes, note that it sends SIGTERM
signal to its pods for shutting down. Interrupt
is normally sent
4) Listen to the stop signals and handle the shutdown of your HTTP Server. You can use defer to close your db connection.
<-stop
Note that we are shutting down HTTP server before closing db because server will need database to handle its API requests.