refactor(app): 使用配置化关闭超时替代硬编码

移除硬编码的 shutdownTimeout 变量,改用配置中的 Shutdown.GracefulTimeout
和 Shutdown.FastTimeout:
- handleSignal 从配置读取超时值
- gracefulUpgrade 使用配置的优雅停止超时
- 添加防御性 nil-check 确保配置和服务器实例存在
- Windows 版本同步更新

Windows 和 Unix 平台行为一致化。

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
xfy 2026-04-13 11:25:47 +08:00
parent 0152dd1d35
commit 5bb67f13a0
2 changed files with 41 additions and 14 deletions

View File

@ -53,12 +53,6 @@ var (
BuildPlatform = "unknown"
)
// 应用状态。
var (
// shutdownTimeout 优雅停止超时时间
shutdownTimeout = 30 * time.Second
)
// App 应用程序结构。
//
// 管理服务器的完整生命周期,包括 HTTP 服务器、HTTP/3 服务器、Stream 服务器
@ -349,22 +343,42 @@ func (a *App) setupSignalHandlers(sigChan chan<- os.Signal) {
// handleSignal 处理信号,返回 false 表示退出。
func (a *App) handleSignal(sig os.Signal) bool {
// 防御性 nil-check确保 a.cfg 不为 nil
if a.cfg == nil {
a.logger.Error().Msg("信号处理失败: 配置为 nil使用默认超时")
// 使用默认超时继续处理信号
a.cfg = &config.Config{
Shutdown: config.ShutdownConfig{
GracefulTimeout: 30 * time.Second,
FastTimeout: 5 * time.Second,
},
}
}
switch sig {
case syscall.SIGQUIT:
// 优雅停止:等待请求完成
a.logger.LogSignal("SIGQUIT", fmt.Sprintf("优雅停止(等待 %v", shutdownTimeout))
timeout := a.cfg.Shutdown.GracefulTimeout
if timeout <= 0 {
timeout = 30 * time.Second // 默认值
}
a.logger.LogSignal("SIGQUIT", fmt.Sprintf("优雅停止(等待 %v", timeout))
a.shutdownHTTP2()
a.shutdownHTTP3()
_ = a.srv.GracefulStop(shutdownTimeout) //nolint:errcheck
_ = a.srv.GracefulStop(timeout) //nolint:errcheck
return false
case syscall.SIGTERM, syscall.SIGINT:
// 快速停止
timeout := a.cfg.Shutdown.FastTimeout
if timeout <= 0 {
timeout = 5 * time.Second // 默认值
}
sigTyped := sig.(syscall.Signal) //nolint:errcheck // 类型断言
a.logger.LogSignal(sigName(sigTyped), "停止服务器")
a.shutdownHTTP2()
a.shutdownHTTP3()
_ = a.srv.Stop() //nolint:errcheck
_ = a.srv.StopWithTimeout(timeout) //nolint:errcheck // 使用新方法
return false
case syscall.SIGHUP:
@ -442,6 +456,12 @@ func (a *App) gracefulUpgrade() {
return
}
// 防御性 nil-check确保 srv 不为 nil
if a.srv == nil {
a.logger.Error().Msg("热升级失败: 服务器实例为 nil")
return
}
// 尝试从服务器获取监听器
listeners := a.srv.GetListeners()
if len(listeners) == 0 {
@ -461,10 +481,14 @@ func (a *App) gracefulUpgrade() {
a.logger.LogStartup("热升级已启动,新进程正在接管", nil)
// 当前进程优雅停止
// 当前进程优雅停止 - 使用配置的超时
timeout := a.cfg.Shutdown.GracefulTimeout
if timeout <= 0 {
timeout = 30 * time.Second
}
a.shutdownHTTP2()
a.shutdownHTTP3()
_ = a.srv.GracefulStop(shutdownTimeout) //nolint:errcheck
_ = a.srv.GracefulStop(timeout) //nolint:errcheck
}
// sigName 返回信号名称(用于日志输出)。

View File

@ -36,8 +36,6 @@ var (
BuildPlatform = "unknown"
)
var shutdownTimeout = 30 * time.Second
// App 应用程序结构Windows 版本)。
type App struct {
cfgPath string
@ -282,10 +280,15 @@ func (a *App) setupSignalHandlers(sigChan chan<- os.Signal) {
func (a *App) handleSignal(sig os.Signal) bool {
switch sig {
case syscall.SIGTERM, syscall.SIGINT:
// 快速停止
timeout := a.cfg.Shutdown.FastTimeout
if timeout <= 0 {
timeout = 5 * time.Second // 默认值
}
a.logger.LogSignal(sigName(sig.(syscall.Signal)), "停止服务器")
a.shutdownHTTP2()
a.shutdownHTTP3()
_ = a.srv.Stop()
_ = a.srv.StopWithTimeout(timeout) //nolint:errcheck // 使用新方法
return false
default:
a.logger.Info().Str("signal", sig.String()).Msg("收到信号Windows 忽略)")