Last active
June 13, 2019 22:01
-
-
Save owais/9d79156b2c394cd317519f8039e990d4 to your computer and use it in GitHub Desktop.
graceful shutdown blocks from shutting down on close
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package main | |
import ( | |
"flag" | |
) | |
var ( | |
listenAddr string | |
) | |
func main() { | |
flag.StringVar(&listenAddr, "listen-addr", ":5000", "server listen address") | |
flag.Parse() | |
server, err := NewServer(listenAddr) | |
if err != nil { | |
panic(err) | |
} | |
server.Start() | |
} | |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package main | |
import ( | |
"context" | |
"io" | |
"log" | |
"net/http" | |
"os" | |
"os/signal" | |
"time" | |
) | |
// Server provides an http.Server | |
type Server struct { | |
log *log.Logger | |
*http.Server | |
} | |
// NewServer creates and configures an APIServer serving all application routes. | |
func NewServer(listenAddr string) (*Server, error) { | |
logger := log.New(os.Stdout, "http: ", log.LstdFlags) | |
api := http.NewServeMux() | |
api.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) { | |
io.WriteString(w, "Hello World\n") | |
}) | |
srv := http.Server{ | |
Addr: listenAddr, | |
Handler: api, | |
ErrorLog: logger, | |
ReadTimeout: 5 * time.Second, | |
WriteTimeout: 10 * time.Second, | |
IdleTimeout: 15 * time.Second, | |
} | |
return &Server{logger, &srv}, nil | |
} | |
// Start runs ListenAndServe on the http.Server with graceful shutdown | |
func (srv *Server) Start() { | |
srv.log.Println("Starting server...") | |
done := make(chan bool, 1) | |
go srv.gracefullShutdown(done) | |
srv.log.Println("Gracefull shutdown interupt signal registered") | |
// code below will not run until interupt signal is given using ctrl+c | |
srv.log.Println("Server is ready to handle requests at", srv.Addr) | |
go func() { | |
time.Sleep(5 * time.Second) | |
srv.Close() | |
}() | |
if err := srv.ListenAndServe(); err != nil && err != http.ErrServerClosed { | |
srv.log.Fatalf("Could not listen on %s: %v\n", srv.Addr, err) | |
} | |
//<-done | |
srv.log.Println("Server stopped") | |
} | |
func (srv *Server) gracefullShutdown(done chan<- bool) { | |
quit := make(chan os.Signal) | |
signal.Notify(quit, os.Interrupt) | |
sig := <-quit | |
srv.log.Println("Server is shutting down... Reason:", sig) | |
ctx, cancel := context.WithTimeout(context.Background(), 30*time.Second) | |
defer cancel() | |
srv.SetKeepAlivesEnabled(false) | |
if err := srv.Shutdown(ctx); err != nil { | |
srv.log.Fatalf("Could not gracefully shutdown the server: %v\n", err) | |
} | |
close(done) | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment