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 方法的实际源码可能包含更多细节和处理逻辑,但核心思想是在关闭过程中确保所有活跃连接得到处理,并在超时或取消时优雅退出。