Skip to content

Instantly share code, notes, and snippets.

@owais
Last active June 13, 2019 22:01
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save owais/9d79156b2c394cd317519f8039e990d4 to your computer and use it in GitHub Desktop.
Save owais/9d79156b2c394cd317519f8039e990d4 to your computer and use it in GitHub Desktop.
graceful shutdown blocks from shutting down on close
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()
}
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