Skip to content
graceful reload golang http server, zero downtime, compatible with systemd, supervisor
Go
Branch: master
Clone or download
kuangchanglang feat: add go.mod
Change-Id: Ie1dbc81b998cb80614d0b873164be409dfb354c3
Latest commit de7d444 Oct 25, 2019
Permalink
Type Name Latest commit message Commit time
Failed to load latest commit information.
example
.gitignore init Jan 4, 2018
LICENSE
README.md
go.mod feat: add go.mod Oct 25, 2019
graceful.go
master.go Merge pull request #7 from kuangchanglang/support_unix_socket Mar 19, 2019
worker.go remove os.Exit to avoid aborting user-defined clean up work Jan 16, 2018

README.md

graceful

Inspired by overseer and endless, with minimum codes and handy api to make http server graceful.

Prerequisite

golang 1.8+

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
You can’t perform that action at this time.