feat(http2): 实现服务器优雅关闭功能
添加 GracefulShutdownTimeout 配置项,实现连接池管理和优雅关闭逻辑: - HTTP2Config 新增 graceful_shutdown_timeout 字段(默认30秒) - Server 添加连接池和等待组跟踪活跃连接 - Stop() 方法等待所有连接完成或超时后再退出 Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
parent
4053634b4c
commit
50a960c539
@ -117,6 +117,7 @@ type HTTP2Config struct {
|
|||||||
Enabled bool `yaml:"enabled"`
|
Enabled bool `yaml:"enabled"`
|
||||||
PushEnabled bool `yaml:"push_enabled"`
|
PushEnabled bool `yaml:"push_enabled"`
|
||||||
H2CEnabled bool `yaml:"h2c_enabled"`
|
H2CEnabled bool `yaml:"h2c_enabled"`
|
||||||
|
GracefulShutdownTimeout time.Duration `yaml:"graceful_shutdown_timeout"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// HTTP3Config HTTP/3 (QUIC) 配置。
|
// HTTP3Config HTTP/3 (QUIC) 配置。
|
||||||
|
|||||||
@ -74,6 +74,7 @@ func DefaultConfig() *Config {
|
|||||||
IdleTimeout: 120 * time.Second,
|
IdleTimeout: 120 * time.Second,
|
||||||
PushEnabled: false,
|
PushEnabled: false,
|
||||||
H2CEnabled: false,
|
H2CEnabled: false,
|
||||||
|
GracefulShutdownTimeout: 30 * time.Second,
|
||||||
},
|
},
|
||||||
SessionTickets: SessionTicketsConfig{
|
SessionTickets: SessionTicketsConfig{
|
||||||
Enabled: false,
|
Enabled: false,
|
||||||
|
|||||||
@ -59,6 +59,15 @@ type Server struct {
|
|||||||
|
|
||||||
// running 服务器运行状态
|
// running 服务器运行状态
|
||||||
running bool
|
running bool
|
||||||
|
|
||||||
|
// pool 连接池
|
||||||
|
pool *connectionPool
|
||||||
|
|
||||||
|
// connWg 连接等待组,用于优雅关闭
|
||||||
|
connWg sync.WaitGroup
|
||||||
|
|
||||||
|
// GracefulShutdownTimeout 优雅关闭超时时间
|
||||||
|
GracefulShutdownTimeout time.Duration
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewServer 创建 HTTP/2 服务器。
|
// NewServer 创建 HTTP/2 服务器。
|
||||||
@ -96,6 +105,11 @@ func NewServer(cfg *config.HTTP2Config, handler fasthttp.RequestHandler, tlsConf
|
|||||||
idleTimeout = 120 * time.Second
|
idleTimeout = 120 * time.Second
|
||||||
}
|
}
|
||||||
|
|
||||||
|
gracefulTimeout := cfg.GracefulShutdownTimeout
|
||||||
|
if gracefulTimeout <= 0 {
|
||||||
|
gracefulTimeout = 30 * time.Second
|
||||||
|
}
|
||||||
|
|
||||||
// 创建 HTTP/2 服务器
|
// 创建 HTTP/2 服务器
|
||||||
h2s := &http2.Server{
|
h2s := &http2.Server{
|
||||||
MaxConcurrentStreams: uint32(maxConcurrentStreams),
|
MaxConcurrentStreams: uint32(maxConcurrentStreams),
|
||||||
@ -112,6 +126,8 @@ func NewServer(cfg *config.HTTP2Config, handler fasthttp.RequestHandler, tlsConf
|
|||||||
config: cfg,
|
config: cfg,
|
||||||
tlsConfig: tlsConfig,
|
tlsConfig: tlsConfig,
|
||||||
handler: handler,
|
handler: handler,
|
||||||
|
pool: newConnectionPool(),
|
||||||
|
GracefulShutdownTimeout: gracefulTimeout,
|
||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -166,6 +182,7 @@ func (s *Server) Serve(ln net.Listener) error {
|
|||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
|
s.connWg.Add(1)
|
||||||
go s.handleConnection(conn)
|
go s.handleConnection(conn)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -174,7 +191,11 @@ func (s *Server) Serve(ln net.Listener) error {
|
|||||||
//
|
//
|
||||||
// 根据连接类型(TLS 或明文)和 ALPN 协商结果,选择合适的协议处理。
|
// 根据连接类型(TLS 或明文)和 ALPN 协商结果,选择合适的协议处理。
|
||||||
func (s *Server) handleConnection(conn net.Conn) {
|
func (s *Server) handleConnection(conn net.Conn) {
|
||||||
|
key := conn.RemoteAddr().String()
|
||||||
|
s.pool.add(key, conn)
|
||||||
defer func() {
|
defer func() {
|
||||||
|
s.pool.remove(key, conn)
|
||||||
|
s.connWg.Done()
|
||||||
if err := conn.Close(); err != nil {
|
if err := conn.Close(); err != nil {
|
||||||
logging.Error().Err(err).Msg("HTTP/2 connection close error")
|
logging.Error().Err(err).Msg("HTTP/2 connection close error")
|
||||||
}
|
}
|
||||||
@ -263,7 +284,23 @@ func (s *Server) Stop() error {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
logging.Info().Msg("HTTP/2 server stopped")
|
// 关闭所有连接
|
||||||
|
s.pool.closeAll()
|
||||||
|
|
||||||
|
// 等待所有连接完成或超时
|
||||||
|
done := make(chan struct{})
|
||||||
|
go func() {
|
||||||
|
s.connWg.Wait()
|
||||||
|
close(done)
|
||||||
|
}()
|
||||||
|
|
||||||
|
select {
|
||||||
|
case <-done:
|
||||||
|
logging.Info().Msg("HTTP/2 server stopped gracefully")
|
||||||
|
case <-time.After(s.GracefulShutdownTimeout):
|
||||||
|
logging.Warn().Msg("HTTP/2 server graceful shutdown timed out")
|
||||||
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user