原文链接
优雅关闭部分:
就是服务器要关闭了, 会拒绝新的连接,但是老的连接不会被强制关闭,而是 会等待一定时间, 等待客户端主动关闭, 除非客户端一直没有关闭, 到了预设的超时时间才进行服务器端关闭.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 func (srv *Server) shutdown(shutdown chan chan struct {}, kill chan struct {}) { done := make (chan struct {}) shutdown <- done srv.stopLock.Lock() defer srv.stopLock.Unlock() if srv.Timeout > 0 { select { case <-done: case <-time.After(srv.Timeout): close (kill) } } else { <-done } srv.chanLock.Lock() if srv.stopChan != nil { close (srv.stopChan) } srv.chanLock.Unlock() }
当进行shutdown部分,会关闭stopChan这个channel
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 func main () { goAway := false go func () { sig := <-sigs fmt.Println("I have to go..." , sig) goAway = true srv.Stop(10 * time.Second) }() for { if (goAway){ break } fmt.Println("Started" ) srv = &graceful.Server{ Timeout: 10 * time.Second, NoSignalHandling: true , ConnState: func (conn net.Conn, state http.ConnState) { fmt.Println( "Connection " , state) }, Server: &http.Server{ Addr: ":8001" , Handler: userRouter, }, } go srv.ListenAndServe() <- srv.StopChan() fmt.Println("Stopped" ) } }
得到stopChan channel关闭的消息,这样for循环又可以启动,重新接收相关的请求,重新初始化部分
可以在同一个socket对上, 共享同一个监听套接字地址, 然后在多个goroutine中执行accept函数,也就是http server中的accept操作
1 2 3 4 5 6 l := ln.(*net.TCPListener) newFile, _ := l.File() fmt.Println(newFile.Fd()) anotherListener, _ := net.FileListener(newFile)
套接字部分,转换给文件描述符
关于fork部分的操作
1 2 3 4 cmd := exec.Command(os.Args[0 ], "-graceful" ) cmd.Stdin, cmd.Stdout, cmd.Stderr = os.Stdin, os.Stdout, os.Stderr cmd.ExtraFiles = []*os.File{newFD} cmd.Run()