graceful
Inspired by overseer and endless, with minimum codes and handy api to make http server graceful.
Prerequisite
- golang 1.8+
- linux/darwin(windows not supported)
Feature
- Graceful reload http servers, zero downtime on upgrade.
- Compatible with systemd, supervisor, etc.
- Drop-in placement for
http.ListenAndServe
Example
type handler struct {
}
func (h *handler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
fmt.Fprintf(w, "Hello, port: %v, %q", r.Host, html.EscapeString(r.URL.Path))
}
func main(){
graceful.ListenAndServe(":9222", &handler{})
}
multi servers:
func main(){
server := graceful.NewServer()
server.Register("0.0.0.0:9223", &handler{})
server.Register("0.0.0.0:9224", &handler{})
server.Register("0.0.0.0:9225", &handler{})
err := server.Run()
fmt.Printf("error: %v\n", err)
}
More example checkout example folder.
Reload
SIGHUP
and SIGUSR1
on master proccess are used as default to reload server. server.Reload()
func works as well from your code.
Drawbacks
graceful
starts a master process to keep pid unchaged for process managers(systemd, supervisor, etc.), and a worker proccess listen to actual addrs. That means graceful
starts one more process. Fortunately, master proccess waits for signals and reload worker when neccessary, which is costless since reload is usually low-frequency action.
Default values
StopTimeout
. Unfinished old connections will be drop in{StopTimeout}
seconds, default 20s, after new server is up.
server := graceful.NewServer(graceful.WithStopTimeout(time.Duration(4 * time.Hour)))
server.Register(addr, handler)
if err := server.Run(); err != nil {
log.Fatal(err)
}
Signals
. Default reload signals:syscall.SIGHUP, syscall.SIGUSR1
and stop signals:syscall.SIGKILL, syscall.SIGTERM, syscall.SIGINT
could be overwrited with:
server := graceful.NewServer(graceful.WithStopSignals([]syscall.Signal{syscall.SIGKILL}), graceful.WithReloadSignals([]syscall.Signal{syscall.SIGHUP}))
server.Register(addr, handler)
if err := server.Run(); err != nil {
log.Fatal(err)
}
TODO
- ListenAndServeTLS
- Add alternative api: Run in single process without master-worker