Z
ZHANK
Web 与工程化

优雅关闭

signal.Notify 信号监听、Shutdown 等待连接完成、超时控制

优雅关闭

生产环境中直接 kill 进程 = 正在处理的请求丢失。优雅关闭等待请求完成再退出。

学完本章你将: 掌握 signal.Notify 信号监听、Shutdown 等待、超时控制。


完整优雅关闭

go
package main

import (
    "context"
    "log"
    "net/http"
    "os"
    "os/signal"
    "syscall"
    "time"
)

func main() {
    srv := &http.Server{Addr: ":8080"}

    // 在 goroutine 中启动服务器
    go func() {
        log.Println("服务器启动 :8080")
        if err := srv.ListenAndServe(); err != nil && err != http.ErrServerClosed {
            log.Fatal(err)
        }
    }()

    // 等待中断信号
    quit := make(chan os.Signal, 1)
    signal.Notify(quit, syscall.SIGINT, syscall.SIGTERM)
    <-quit  // 阻塞直到收到信号
    log.Println("正在关闭服务器...")

    // 5 秒超时——等待活跃请求完成
    ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
    defer cancel()

    if err := srv.Shutdown(ctx); err != nil {
        log.Fatal("强制关闭:", err)
    }
    log.Println("服务器已关闭")
}

关键步骤

go
// 1. 监听信号
signal.Notify(quit, syscall.SIGINT, syscall.SIGTERM)

// 2. Shutdown 而不是 Close
// srv.Close() —— 立即断开所有连接
// srv.Shutdown(ctx) —— 等待活跃请求完成

// 3. 超时保护
ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)