使用时间窗口的目的
使正在运行的服务停止接收新请求,并在最终关闭之前完成正在进行的请求。为了实现上述目的,可以创建一个带有超时的上下文,使用channel监听中断信号,为服务其关闭提供一个时间窗口。
代码实现
初始化通道
signalChan = make(chan os.Signal, 1)
signal.Notify(signalChan, os.Interrupt, syscall.SIGTERM)
func gracefulShutdown() {
select {
case msg := <-signalChan:
switch msg {
case syscall.SIGHUP, syscall.SIGINT, syscall.SIGQUIT, syscall.SIGKILL, syscall.SIGTERM:
global.Log.Info("API Server Shutdown......")
ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
defer cancel()
if err := server.Shutdown(ctx); err != nil {
global.Log.Error(fmt.Sprintf("API Server Shutdown Error: %+v", err))
}
}
os.Exit(0)
}
}
创建带时间窗口的上下文
ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
defer cancel()
关闭服务
if err := server.Shutdown(ctx); err != nil {
global.Log.Error(fmt.Sprintf("API Server Shutdown Error: %+v", err))
}
实现监听通道
select {
case msg := <-signalChan:
switch msg {
case syscall.SIGHUP, syscall.SIGINT, syscall.SIGQUIT, syscall.SIGKILL, syscall.SIGTERM:
global.Log.Info("API Server Shutdown......")
}
os.Exit(0)
}
整合代码
func main() {
flag.Parse()
config.Init(env)
signalChan = make(chan os.Signal, 1)
signal.Notify(signalChan, os.Interrupt, syscall.SIGTERM)
// 监听中止信号
go gracefulShutdown()
app, cancel, err := initServer()
defer cancel()
if err != nil {
panic(err)
}
server = app.Start()
global.Log.Info(fmt.Sprintf("API Server start at %s", server.Addr))
if err := server.ListenAndServe(); err != nil && err != http.ErrServerClosed {
global.Log.Fatal(fmt.Sprintf("start gamefi openapi server failed, err: %s", err))
}
}
func gracefulShutdown() {
select {
case msg := <-signalChan:
switch msg {
case syscall.SIGHUP, syscall.SIGINT, syscall.SIGQUIT, syscall.SIGKILL, syscall.SIGTERM:
global.Log.Info("API Server Shutdown......")
ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
defer cancel()
if err := server.Shutdown(ctx); err != nil {
global.Log.Error(fmt.Sprintf("API Server Shutdown Error: %+v", err))
}
}
os.Exit(0)
}
}
该代码示例展示了如何使用时间窗口来确保服务在接收到中断信号后停止接收新请求,并等待已完成的请求处理完毕后再优雅地关闭。通过创建一个信号通道,监听OS中断和SIGTERM信号,然后使用context.WithTimeout创建一个带超时的上下文,设定10秒的关闭时间窗口。在接收到信号后,服务将尝试在指定时间内关闭,如果出现错误则记录并退出。
493

被折叠的 条评论
为什么被折叠?



