srv.Shutdown(ctx)
是 Go 标准库 net/http
包中的 http.Server
类型的方法。它用于优雅地关闭 HTTP 服务器,确保所有正在处理的请求完成后再退出。
以下是 srv.Shutdown(ctx)
的核心代码示例,展示了如何在服务器关闭过程中等待所有请求完成。请注意,实际源码会有所不同,以下代码仅为核心逻辑的简化版本:
// http/server.go
// Shutdown initiates a graceful shutdown of the server, waiting for
// currently active connections to finish.
func (srv *Server) Shutdown(ctx context.Context) error {
// Signal the server to stop accepting new connections.
srv.setClosing()
// Close the listener so no new connections will be accepted.
if err := srv.Listener.Close(); err != nil && err != ErrServerClosed {
return err
}
// Create a channel to signal when all active connections have finished.
done := make(chan struct{})
// Start a goroutine to wait for active connections to close.
go func() {
srv.wg.Wait()
close(done)
}()
// Wait for either the connections to close or the context to timeout.
select {
case <-ctx.Done():
return ctx.Err() // Return context error if context is canceled or timed out.
case <-done:
return nil // Successfully closed after all connections are done.
}
}
// setClosing sets the server to a "closing" state to stop accepting new connections.
func (srv *Server) setClosing() {
srv.mu.Lock()
defer srv.mu.Unlock()
srv.closing = true
}
关键部分解析
-
停止接受新连接:
srv.setClosing()
设置服务器为关闭状态,标志着服务器将不再接受新的连接。
-
关闭监听器:
srv.Listener.Close()
关闭监听器,防止新的连接到达。注意,如果监听器已经关闭或者出现错误,Shutdown
方法会处理这些情况。
-
等待活跃连接关闭:
srv.wg.Wait()
等待所有活跃的连接处理完毕。srv.wg
是一个sync.WaitGroup
,用于跟踪活动连接的数量。
-
处理超时或完成信号:
select
语句用于等待ctx.Done()
(上下文的超时或取消)或done
通道(所有连接完成)。如果上下文超时或被取消,返回上下文错误;如果所有连接完成,则返回nil
。
相关代码
srv.wg
是sync.WaitGroup
类型,用于跟踪活动连接。srv.setClosing()
标记服务器状态为“关闭”,停止接受新连接。srv.Listener
是实际的网络监听器,负责接受新的连接。
Shutdown
方法的实际源码可能包含更多细节和处理逻辑,但核心思想是在关闭过程中确保所有活跃连接得到处理,并在超时或取消时优雅退出。