mirror of
https://github.com/infinite-iroha/touka.git
synced 2026-02-02 16:31:11 +08:00
add RunShutdownWithContext
This commit is contained in:
parent
895cd6222b
commit
3cd8ef84a2
3 changed files with 92 additions and 1 deletions
2
go.mod
2
go.mod
|
|
@ -5,7 +5,7 @@ go 1.24.5
|
||||||
require (
|
require (
|
||||||
github.com/WJQSERVER-STUDIO/go-utils/iox v0.0.2
|
github.com/WJQSERVER-STUDIO/go-utils/iox v0.0.2
|
||||||
github.com/WJQSERVER-STUDIO/httpc v0.8.2
|
github.com/WJQSERVER-STUDIO/httpc v0.8.2
|
||||||
github.com/fenthope/reco v0.0.3
|
github.com/fenthope/reco v0.0.4
|
||||||
github.com/go-json-experiment/json v0.0.0-20250725192818-e39067aee2d2
|
github.com/go-json-experiment/json v0.0.0-20250725192818-e39067aee2d2
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
|
||||||
2
go.sum
2
go.sum
|
|
@ -4,6 +4,8 @@ github.com/WJQSERVER-STUDIO/httpc v0.8.2 h1:PFPLodV0QAfGEP6915J57vIqoKu9cGuuiXG/
|
||||||
github.com/WJQSERVER-STUDIO/httpc v0.8.2/go.mod h1:8WhHVRO+olDFBSvL5PC/bdMkb6U3vRdPJ4p4pnguV5Y=
|
github.com/WJQSERVER-STUDIO/httpc v0.8.2/go.mod h1:8WhHVRO+olDFBSvL5PC/bdMkb6U3vRdPJ4p4pnguV5Y=
|
||||||
github.com/fenthope/reco v0.0.3 h1:RmnQ0D9a8PWtwOODawitTe4BztTnS9wYwrDbipISNq4=
|
github.com/fenthope/reco v0.0.3 h1:RmnQ0D9a8PWtwOODawitTe4BztTnS9wYwrDbipISNq4=
|
||||||
github.com/fenthope/reco v0.0.3/go.mod h1:mDkGLHte5udWTIcjQTxrABRcf56SSdxBOCLgrRDwI/Y=
|
github.com/fenthope/reco v0.0.3/go.mod h1:mDkGLHte5udWTIcjQTxrABRcf56SSdxBOCLgrRDwI/Y=
|
||||||
|
github.com/fenthope/reco v0.0.4 h1:yo2g3aWwdoMpaZWZX4SdZOW7mCK82RQIU/YI8ZUQThM=
|
||||||
|
github.com/fenthope/reco v0.0.4/go.mod h1:eMyS8HpdMVdJ/2WJt6Cvt8P1EH9Igzj5lSJrgc+0jeg=
|
||||||
github.com/go-json-experiment/json v0.0.0-20250725192818-e39067aee2d2 h1:iizUGZ9pEquQS5jTGkh4AqeeHCMbfbjeb0zMt0aEFzs=
|
github.com/go-json-experiment/json v0.0.0-20250725192818-e39067aee2d2 h1:iizUGZ9pEquQS5jTGkh4AqeeHCMbfbjeb0zMt0aEFzs=
|
||||||
github.com/go-json-experiment/json v0.0.0-20250725192818-e39067aee2d2/go.mod h1:TiCD2a1pcmjd7YnhGH0f/zKNcCD06B029pHhzV23c2M=
|
github.com/go-json-experiment/json v0.0.0-20250725192818-e39067aee2d2/go.mod h1:TiCD2a1pcmjd7YnhGH0f/zKNcCD06B029pHhzV23c2M=
|
||||||
github.com/valyala/bytebufferpool v1.0.0 h1:GqA5TC/0021Y/b9FG4Oi9Mr3q7XYx6KllzawFIhcdPw=
|
github.com/valyala/bytebufferpool v1.0.0 h1:GqA5TC/0021Y/b9FG4Oi9Mr3q7XYx6KllzawFIhcdPw=
|
||||||
|
|
|
||||||
89
serve.go
89
serve.go
|
|
@ -128,6 +128,79 @@ func handleGracefulShutdown(servers []*http.Server, timeout time.Duration, logge
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func handleGracefulShutdownWithContext(servers []*http.Server, ctx context.Context, timeout time.Duration, logger *reco.Logger) error {
|
||||||
|
// 创建一个 channel 来接收操作系统信号
|
||||||
|
quit := make(chan os.Signal, 1)
|
||||||
|
signal.Notify(quit, syscall.SIGINT, syscall.SIGTERM) // 监听中断和终止信号
|
||||||
|
|
||||||
|
// 启动服务器
|
||||||
|
serverStopped := make(chan error, 1)
|
||||||
|
for _, srv := range servers {
|
||||||
|
go func(s *http.Server) {
|
||||||
|
serverStopped <- s.ListenAndServe()
|
||||||
|
}(srv)
|
||||||
|
}
|
||||||
|
|
||||||
|
select {
|
||||||
|
case <-ctx.Done():
|
||||||
|
// Context 被取消 (例如,通过外部取消函数)
|
||||||
|
log.Println("Context cancelled, shutting down Touka server(s)...")
|
||||||
|
case err := <-serverStopped:
|
||||||
|
// 服务器自身停止 (例如,端口被占用,或 ListenAndServe 返回错误)
|
||||||
|
if err != nil && !errors.Is(err, http.ErrServerClosed) {
|
||||||
|
return fmt.Errorf("Touka HTTP server failed: %w", err)
|
||||||
|
}
|
||||||
|
log.Println("Touka HTTP server stopped gracefully.")
|
||||||
|
return nil // 服务器已自行优雅关闭,无需进一步处理
|
||||||
|
case <-quit:
|
||||||
|
// 接收到操作系统信号
|
||||||
|
log.Println("Shutting down Touka server(s) due to OS signal...")
|
||||||
|
}
|
||||||
|
|
||||||
|
// 关闭日志记录器
|
||||||
|
if logger != nil {
|
||||||
|
go func() {
|
||||||
|
log.Println("Closing Touka logger...")
|
||||||
|
CloseLogger(logger)
|
||||||
|
}()
|
||||||
|
}
|
||||||
|
|
||||||
|
// 创建一个带超时的上下文,用于 Shutdown
|
||||||
|
shutdownCtx, cancel := context.WithTimeout(context.Background(), timeout)
|
||||||
|
defer cancel()
|
||||||
|
|
||||||
|
var wg sync.WaitGroup
|
||||||
|
errChan := make(chan error, len(servers)) // 用于收集关闭错误的 channel
|
||||||
|
|
||||||
|
// 并发地关闭所有服务器
|
||||||
|
for _, srv := range servers {
|
||||||
|
wg.Add(1)
|
||||||
|
go func(s *http.Server) {
|
||||||
|
defer wg.Done()
|
||||||
|
if err := s.Shutdown(shutdownCtx); err != nil {
|
||||||
|
// 将错误发送到 channel
|
||||||
|
errChan <- fmt.Errorf("server on %s shutdown failed: %w", s.Addr, err)
|
||||||
|
}
|
||||||
|
}(srv)
|
||||||
|
}
|
||||||
|
|
||||||
|
wg.Wait()
|
||||||
|
close(errChan) // 关闭 channel,以便可以安全地遍历它
|
||||||
|
|
||||||
|
// 收集所有关闭过程中发生的错误
|
||||||
|
var shutdownErrors []error
|
||||||
|
for err := range errChan {
|
||||||
|
shutdownErrors = append(shutdownErrors, err)
|
||||||
|
log.Printf("Shutdown error: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(shutdownErrors) > 0 {
|
||||||
|
return errors.Join(shutdownErrors...) // Go 1.20+ 的 errors.Join,用于合并多个错误
|
||||||
|
}
|
||||||
|
log.Println("Touka server(s) exited gracefully.")
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
// --- 公共 Run 方法 ---
|
// --- 公共 Run 方法 ---
|
||||||
|
|
||||||
// Run 启动一个不支持优雅关闭的 HTTP 服务器
|
// Run 启动一个不支持优雅关闭的 HTTP 服务器
|
||||||
|
|
@ -163,6 +236,22 @@ func (engine *Engine) RunShutdown(addr string, timeouts ...time.Duration) error
|
||||||
return handleGracefulShutdown([]*http.Server{srv}, getShutdownTimeout(timeouts), engine.LogReco)
|
return handleGracefulShutdown([]*http.Server{srv}, getShutdownTimeout(timeouts), engine.LogReco)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// RunShutdown 启动一个支持优雅关闭的 HTTP 服务器
|
||||||
|
func (engine *Engine) RunShutdownWithContext(addr string, ctx context.Context, timeouts ...time.Duration) error {
|
||||||
|
srv := &http.Server{
|
||||||
|
Addr: addr,
|
||||||
|
Handler: engine,
|
||||||
|
}
|
||||||
|
|
||||||
|
// 应用框架的默认配置和用户提供的自定义配置
|
||||||
|
//engine.applyDefaultServerConfig(srv)
|
||||||
|
if engine.ServerConfigurator != nil {
|
||||||
|
engine.ServerConfigurator(srv)
|
||||||
|
}
|
||||||
|
|
||||||
|
return handleGracefulShutdownWithContext([]*http.Server{srv}, ctx, getShutdownTimeout(timeouts), engine.LogReco)
|
||||||
|
}
|
||||||
|
|
||||||
// RunTLS 启动一个支持优雅关闭的 HTTPS 服务器
|
// RunTLS 启动一个支持优雅关闭的 HTTPS 服务器
|
||||||
func (engine *Engine) RunTLS(addr string, tlsConfig *tls.Config, timeouts ...time.Duration) error {
|
func (engine *Engine) RunTLS(addr string, tlsConfig *tls.Config, timeouts ...time.Duration) error {
|
||||||
if tlsConfig == nil {
|
if tlsConfig == nil {
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue