Skip to content
gqlxj1987's Blog
Go back

Go Graceful优雅重启

Edit page

原文链接

优雅关闭部分:

就是服务器要关闭了, 会拒绝新的连接,但是老的连接不会被强制关闭,而是 会等待一定时间, 等待客户端主动关闭, 除非客户端一直没有关闭, 到了预设的超时时间才进行服务器端关闭.

func (srv *Server) shutdown(shutdown chan chan struct{}, kill chan struct{}) {
	// Request done notification
	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
	}
	// Close the stopChan to wake up any blocked goroutines.
	srv.chanLock.Lock()
	if srv.stopChan != nil {
		close(srv.stopChan)
	}
	srv.chanLock.Unlock()
}

当进行shutdown部分,会关闭stopChan这个channel

func main() { // goroutine 0
	goAway := false
	go func() {  // goroutine 1
		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()  // goroutine 2
		<- srv.StopChan() // goroutine 0
		fmt.Println("Stopped")
	}
}

得到stopChan channel关闭的消息,这样for循环又可以启动,重新接收相关的请求,重新初始化部分

可以在同一个socket对上, 共享同一个监听套接字地址, 然后在多个goroutine中执行accept函数,也就是http server中的accept操作

l := ln.(*net.TCPListener)
newFile, _ := l.File()
fmt.Println(newFile.Fd())

anotherListener, _ := net.FileListener(newFile)

套接字部分,转换给文件描述符

关于fork部分的操作

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()

Edit page
Share this post on:

Previous Post
Vim Practise
Next Post
Install Kubernetes Cluster guide