package main import ( "flag" "fmt" "net" "net/http" "os" "os/exec" "syscall" "time" "log" ) var FD *int = flag.Int("fd", 0, "Server socket FD") var PID int = syscall.Getpid() var listener1 net.Listener var file1 *os.File = nil var exit1 chan int = make(chan int) var stop1 = false func main() { fo1, err := os.Create(fmt.Sprintf("pid-%d.log", PID)) if err != nil { panic(err) } log.SetOutput(fo1) log.Println("Grace1 ", PID) flag.Parse() s := &http.Server{Addr: ":8080", ReadTimeout: 10 * time.Second, WriteTimeout: 10 * time.Second, } http.HandleFunc("/", DefHandler) http.HandleFunc("/stop", StopHandler) http.HandleFunc("/restart", RestartHandler) http.HandleFunc("/grace", GraceHandler) http.HandleFunc("/think", ThinkHandler) if *FD != 0 { log.Println("Starting with FD ", *FD) file1 = os.NewFile(uintptr(*FD), "parent socket") listener1, err = net.FileListener(file1) if err != nil { log.Fatalln("fd listener failed: ", err) } } else { log.Println("Virgin Start") listener1, err = net.Listen("tcp", s.Addr) if err != nil { log.Fatalln("listener failed: ", err) } } err = s.Serve(listener1) log.Println("EXITING", PID) <-exit1 log.Println("EXIT", PID) } func DefHandler(w http.ResponseWriter, req *http.Request) { fmt.Fprintf(w, "def handler %d %s", PID, time.Now().String()) } func ThinkHandler(w http.ResponseWriter, req *http.Request) { time.Sleep(5 * time.Second) fmt.Fprintf(w, "think handler %d %s", PID, time.Now().String()) } func StopHandler(w http.ResponseWriter, req *http.Request) { log.Println("StopHandler", req.Method) if(stop1){ fmt.Fprintf(w, "stopped %d %s", PID, time.Now().String()) } stop1 = true fmt.Fprintf(w, "stop %d %s", PID, time.Now().String()) go func() { listener1.Close() if file1 != nil { file1.Close() } exit1<-1 }() } func RestartHandler(w http.ResponseWriter, req *http.Request) { log.Println("RestartHandler", req.Method) if(stop1){ fmt.Fprintf(w, "stopped %d %s", PID, time.Now().String()) } stop1 = true fmt.Fprintf(w, "restart %d %s", PID, time.Now().String()) go func() { listener1.Close() if file1 != nil { file1.Close() } cmd := exec.Command("./grace1") err := cmd.Start() if err != nil { log.Fatalln("starting error:", err) } exit1<-1 }() } func GraceHandler(w http.ResponseWriter, req *http.Request) { log.Println("GraceHandler", req.Method) if(stop1){ fmt.Fprintf(w, "stopped %d %s", PID, time.Now().String()) } stop1 = true fmt.Fprintf(w, "grace %d %s", PID, time.Now().String()) go func() { defer func() { log.Println("GoodBye") }() listener2 := listener1.(*net.TCPListener) file2, err := listener2.File() if err != nil { log.Fatalln(err) } fd1 := int(file2.Fd()) fd2, err := syscall.Dup(fd1) if err != nil { log.Fatalln("Dup error:", err) } listener1.Close() if file1 != nil { file1.Close() } cmd := exec.Command("./grace1", fmt.Sprint("-fd=", fd2)) err = cmd.Start() if err != nil { log.Fatalln("grace starting error:", err) } log.Println("sleep11", PID) time.Sleep(10 * time.Second) log.Println("exit after sleep", PID) exit1<-1 }() }
go build grace1.go ./grace1
package main import ( "net/http" "time" ) func main() { nerr := 0 ngood := 0 for i := 0; i < 10000; i++ { resp, err := http.Get("http://127.0.0.1:8080/") if err != nil { // error print("E") nerr++ }else{ print("g") ngood++ resp.Body.Close() } time.Sleep(10 * time.Millisecond) } println() println("Good:", ngood, "Error", nerr) }
gggggggggggggggggggggggggggggggggggggggggggggggggggggggEEEEEgggggggggggggggggggg gggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggg gggggggggggggggggggggggggggggggggEEggggggggggggggggggggggggggggggggggggggggggggg ggggggggggggggggggggggggggggggggggggggggggggggggEEgggggggggggggggggggggggggggggg ggggggggggggggggggggggggEggggggggggggggggggggggggggggggggggggggggggggggggggggggg gggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggg gggEEggggggggggggggggggEgggggggggggggggggggEggggggggggggggggEEgggggggggggggggggE gggggggggggggggggggggEEgggggggggggggggggEggggggggggggggggggggEggggggggggggggggEE gggggggggggggggggEEgggggggggggggggggEEggggggggggggggggggEgggggggggggggggEEgggggg
Source: https://habr.com/ru/post/202584/
All Articles