init commit
This commit is contained in:
113
archive/go/hot-restart/main.go
Normal file
113
archive/go/hot-restart/main.go
Normal file
@ -0,0 +1,113 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"context"
|
||||
"flag"
|
||||
"net"
|
||||
"net/http"
|
||||
"os"
|
||||
"os/exec"
|
||||
"os/signal"
|
||||
"sync"
|
||||
"syscall"
|
||||
"time"
|
||||
)
|
||||
|
||||
// 一个停止的信号量
|
||||
var (
|
||||
isStop bool
|
||||
lock sync.WaitGroup
|
||||
server *http.Server
|
||||
listener net.Listener
|
||||
isReload bool
|
||||
)
|
||||
|
||||
func init() {
|
||||
flag.BoolVar(&isReload, "reload", false, "")
|
||||
flag.Parse()
|
||||
}
|
||||
|
||||
// 优雅停止中间件
|
||||
func GracefulStop(handel func(http.ResponseWriter, *http.Request)) func(http.ResponseWriter, *http.Request) {
|
||||
return func(writer http.ResponseWriter, request *http.Request) {
|
||||
lock.Add(1)
|
||||
if isStop {
|
||||
//不再接收新的请求
|
||||
writer.WriteHeader(400)
|
||||
writer.Write([]byte("server is stop"))
|
||||
} else {
|
||||
handel(writer, request)
|
||||
}
|
||||
lock.Done()
|
||||
}
|
||||
}
|
||||
|
||||
// 一个会耗时很长的方法
|
||||
func LongTime(writer http.ResponseWriter, request *http.Request) {
|
||||
time.Sleep(time.Second * 5)
|
||||
writer.Write([]byte("Hello"))
|
||||
}
|
||||
|
||||
func Normal(writer http.ResponseWriter, request *http.Request) {
|
||||
writer.Write([]byte("Hello"))
|
||||
}
|
||||
|
||||
func main() {
|
||||
|
||||
http.HandleFunc("/normal", Normal)
|
||||
http.HandleFunc("/long-time", GracefulStop(LongTime))
|
||||
|
||||
//监听信号
|
||||
go func() {
|
||||
ch := make(chan os.Signal, 1)
|
||||
signal.Notify(ch, syscall.SIGINT, syscall.SIGTERM, syscall.SIGUSR1)
|
||||
for {
|
||||
sign := <-ch
|
||||
ctx, _ := context.WithTimeout(context.Background(), 20*time.Second)
|
||||
switch sign {
|
||||
case syscall.SIGINT, syscall.SIGTERM:
|
||||
{
|
||||
println("stop...")
|
||||
//停止
|
||||
isStop = true
|
||||
lock.Wait()
|
||||
//结束
|
||||
signal.Stop(ch)
|
||||
server.Shutdown(ctx)
|
||||
println("stop")
|
||||
return
|
||||
}
|
||||
case syscall.SIGUSR1:
|
||||
{
|
||||
println("reload...")
|
||||
//热重启
|
||||
tl, _ := listener.(*net.TCPListener)
|
||||
f, _ := tl.File()
|
||||
cmd := exec.Command(os.Args[0], "--reload")
|
||||
cmd.Stdout = os.Stdout
|
||||
cmd.Stdin = os.Stdin
|
||||
cmd.Stderr = os.Stderr
|
||||
cmd.ExtraFiles = []*os.File{f}
|
||||
cmd.Start()
|
||||
signal.Stop(ch)
|
||||
server.Shutdown(ctx)
|
||||
println("father stop")
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
}()
|
||||
if isReload {
|
||||
f := os.NewFile(3, "")
|
||||
listener, _ = net.FileListener(f)
|
||||
println("child start")
|
||||
} else {
|
||||
listener, _ = net.Listen("tcp", ":8080")
|
||||
}
|
||||
server = &http.Server{
|
||||
Addr: ":8080",
|
||||
Handler: nil,
|
||||
}
|
||||
|
||||
server.Serve(listener)
|
||||
}
|
14
archive/go/hot-restart/readme.md
Normal file
14
archive/go/hot-restart/readme.md
Normal file
@ -0,0 +1,14 @@
|
||||
# 热重启
|
||||
|
||||
可以通过nginx来实现热重启
|
||||
|
||||
这里尝试使用fork的方式实现热重启
|
||||
|
||||
某些信号量需要linux才有
|
||||
|
||||
使用`kill pid `
|
||||
|
||||
# 优雅结束
|
||||
将请求处理完之后再结束
|
||||
|
||||
|
Reference in New Issue
Block a user