Go 语言之 Shutdown 关机和fvbock/endless 重启
Shutdown 源码
[code]// Shutdown gracefully shuts down the server without interrupting any// active connections. Shutdown works by first closing all open// listeners, then closing all idle connections, and then waiting// indefinitely for connections to return to idle and then shut down.// If the provided context expires before the shutdown is complete,// Shutdown returns the context's error, otherwise it returns any// error returned from closing the Server's underlying Listener(s).//// When Shutdown is called, Serve, ListenAndServe, and// ListenAndServeTLS immediately return ErrServerClosed. Make sure the// program doesn't exit and waits instead for Shutdown to return.//// Shutdown does not attempt to close nor wait for hijacked// connections such as WebSockets. The caller of Shutdown should// separately notify such long-lived connections of shutdown and wait// for them to close, if desired. See RegisterOnShutdown for a way to// register shutdown notification functions.//// Once Shutdown has been called on a server, it may not be reused;// future calls to methods such as Serve will return ErrServerClosed.func (srv *Server) Shutdown(ctx context.Context) error { srv.inShutdown.Store(true) srv.mu.Lock() lnerr := srv.closeListenersLocked() for _, f := range srv.onShutdown { go f() } srv.mu.Unlock() srv.listenerGroup.Wait() pollIntervalBase := time.Millisecond nextPollInterval := func() time.Duration { // Add 10% jitter. interval := pollIntervalBase + time.Duration(rand.Intn(int(pollIntervalBase/10))) // Double and clamp for next time. pollIntervalBase *= 2 if pollIntervalBase > shutdownPollIntervalMax { pollIntervalBase = shutdownPollIntervalMax } return interval } timer := time.NewTimer(nextPollInterval()) defer timer.Stop() for { if srv.closeIdleConns() { return lnerr } select { case |