mirror of
https://github.com/infinite-iroha/touka.git
synced 2026-02-03 00:41:10 +08:00
Merge pull request #48 from infinite-iroha/dev
add RunShutdownWithContext
This commit is contained in:
commit
1e7682ad84
3 changed files with 92 additions and 1 deletions
2
go.mod
2
go.mod
|
|
@ -5,7 +5,7 @@ go 1.24.5
|
|||
require (
|
||||
github.com/WJQSERVER-STUDIO/go-utils/iox v0.0.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
|
||||
)
|
||||
|
||||
|
|
|
|||
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/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.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/go.mod h1:TiCD2a1pcmjd7YnhGH0f/zKNcCD06B029pHhzV23c2M=
|
||||
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
|
||||
}
|
||||
|
||||
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 启动一个不支持优雅关闭的 HTTP 服务器
|
||||
|
|
@ -163,6 +236,22 @@ func (engine *Engine) RunShutdown(addr string, timeouts ...time.Duration) error
|
|||
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 服务器
|
||||
func (engine *Engine) RunTLS(addr string, tlsConfig *tls.Config, timeouts ...time.Duration) error {
|
||||
if tlsConfig == nil {
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue