Skip to content

Instantly share code, notes, and snippets.

@DigDeeply
Created January 16, 2019 06:41
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 DigDeeply/6c23ec60705cc284f54f2c5cfbf2c4ca to your computer and use it in GitHub Desktop.
Save DigDeeply/6c23ec60705cc284f54f2c5cfbf2c4ca to your computer and use it in GitHub Desktop.
a graceful http demo.
package main
import (
"context"
"fmt"
"io"
"log"
"net"
"net/http"
"os"
"os/exec"
"os/signal"
"syscall"
"time"
)
var ln net.Listener
var srv http.Server
func main() {
fmt.Println("start")
fmt.Printf("%v\n", os.Environ())
http.HandleFunc("/hello", getPidHandle)
Addr := ":8080"
var err error
if os.Getenv("_GRACEFUL") == "true" {
fd := os.NewFile(3, "")
ln, err = net.FileListener(fd)
if err != nil {
log.Fatal(err)
}
} else {
ln, err = net.Listen("tcp", Addr)
if err != nil {
log.Fatal(err)
}
}
go srv.Serve(ln)
sig := make(chan os.Signal, 1)
signal.Notify(sig, syscall.SIGUSR2)
s := <-sig
for {
switch s {
case syscall.SIGUSR2:
fmt.Printf("%v\n", s)
reload()
stop()
return
}
}
fmt.Println("Exiting")
}
func getPidHandle(w http.ResponseWriter, r *http.Request) {
io.WriteString(w, "Hello, world!\n"+fmt.Sprintf("%d\n", os.Getpid()))
}
func reload() {
tcp, ok := ln.(*net.TCPListener)
if !ok {
log.Fatal("tcp listener tcp not ok")
}
f, err := tcp.File()
if err != nil {
log.Fatal(err)
}
cmd := exec.Command(os.Args[0])
os.Setenv("_GRACEFUL", "true")
cmd.ExtraFiles = []*os.File{f}
err = cmd.Start()
if err != nil {
log.Fatal(err)
}
}
func stop() {
// shutdown old service
ctx, cancleHandle := context.WithTimeout(context.Background(), 5*time.Second)
defer cancleHandle()
err := srv.Shutdown(ctx)
if err != nil {
log.Fatal(err)
}
time.Sleep(6 * time.Second)
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment