You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

实时端点OS信号处理:服务器收SIGTERM时如何应对忙碌请求?

Gin框架下捕获SIGTERM信号优雅处理请求并关闭数据库连接

核心处理逻辑

  • 监听SIGTERM信号,触发优雅关闭流程
  • 先停止服务器接收新请求,等待正在处理的请求完成(可设置超时上限)
  • 待请求处理完毕后,关闭所有数据库连接
  • 最终安全退出程序

完整代码示例

package main

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

    "github.com/gin-gonic/gin"
    "gorm.io/driver/mysql"
    "gorm.io/gorm"
)

var db *gorm.DB

// 初始化数据库连接(示例用GORM,可替换为你的数据库驱动)
func initDB() {
    dsn := "user:password@tcp(127.0.0.1:3306)/dbname?charset=utf8mb4&parseTime=True&loc=Local"
    var err error
    db, err = gorm.Open(mysql.Open(dsn), &gorm.Config{})
    if err != nil {
        log.Fatalf("数据库连接失败: %v", err)
    }

    sqlDB, err := db.DB()
    if err != nil {
        log.Fatalf("获取底层sql连接失败: %v", err)
    }
    // 配置连接池参数(可选)
    sqlDB.SetMaxOpenConns(10)
    sqlDB.SetMaxIdleConns(5)
}

func main() {
    initDB()

    r := gin.Default()

    // 模拟处理大数据的耗时端点
    r.GET("/big-data", func(c *gin.Context) {
        log.Println("开始处理大数据请求")
        // 模拟5秒耗时操作
        time.Sleep(5 * time.Second)
        c.JSON(http.StatusOK, gin.H{"message": "大数据处理完成"})
        log.Println("大数据请求处理完成")
    })

    srv := &http.Server{
        Addr:    ":8080",
        Handler: r,
    }

    // 启动服务器(后台goroutine)
    go func() {
        if err := srv.ListenAndServe(); err != nil && err != http.ErrServerClosed {
            log.Fatalf("监听端口失败: %s", err)
        }
    }()

    // 监听SIGTERM信号
    quit := make(chan os.Signal, 1)
    signal.Notify(quit, syscall.SIGTERM)
    <-quit
    log.Println("收到SIGTERM信号,启动优雅关闭流程")

    // 设置上下文,给活跃请求最多30秒处理时间
    ctx, cancel := context.WithTimeout(context.Background(), 30*time.Second)
    defer cancel()

    // 停止接收新请求,等待活跃请求处理完成
    if err := srv.Shutdown(ctx); err != nil {
        log.Fatalf("服务器优雅关闭失败: %v", err)
    }
    log.Println("服务器已停止接收新请求,等待活跃请求收尾")

    // 关闭数据库连接
    sqlDB, err := db.DB()
    if err != nil {
        log.Fatalf("获取sql连接实例失败: %v", err)
    }
    if err := sqlDB.Close(); err != nil {
        log.Fatalf("数据库连接关闭失败: %v", err)
    }
    log.Println("所有数据库连接已关闭")

    log.Println("服务器已安全退出")
}

关键细节说明

  • 信号监听:通过signal.Notify捕获SIGTERM信号,避免直接强制终止程序
  • 优雅关闭服务器:srv.Shutdown(ctx)会自动停止端口监听、拒绝新请求,但会保留当前活跃连接直到处理完成或超时
  • 数据库连接时机:必须等所有请求处理完毕后再关闭数据库,否则正在执行的数据库操作会直接报错
  • 超时控制:通过context.WithTimeout设置最大等待时间,防止因个别超长耗时请求导致程序无法退出

内容的提问来源于stack exchange,提问作者GurbaniX

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.03 14:15:35