Hertz的优雅退出
Hertz 停止服务时提供的优雅退出功能。
Hertz 支持优雅退出,优雅退出过程如下:
-
设置
engine
状态为closed
-
顺序非阻塞触发回调函数
[]OnShutDown
(与标准包 net/http 一致),Select
等待回调函数执行完成或者超时返回 -
注册中心注销对应服务
-
关闭网络库的信号监听
-
对处于关闭过程中的请求回包统一带上
Connection:Close
header -
Select等待业务协程退出:
- 对于 netpoll 网络库,开启默认 1s(netpoll 中设置,暂时不可更改)的
ticker
,定时查看active conn
(业务 handle 退出且连接不处于阻塞读状态)是否为 0;对于 go net 网络库,则关闭监听,不对连接做处理。 - 等待超时时间为
ExitWaitTime
的 context 触发,默认 5s
- 对于 netpoll 网络库,开启默认 1s(netpoll 中设置,暂时不可更改)的
如需修改等待超时时间,可通过 server.WithExitWaitTime()
进行配置。
如需注册退出 hook
函数,可通过获取到 Engine
后进行注册:
h.Engine.OnShutdown = append(h.Engine.OnShutdown, shutDownFunc)
例如
package main
import (
"context"
"fmt"
"github.com/cloudwego/hertz/pkg/app"
"github.com/cloudwego/hertz/pkg/app/server"
"github.com/cloudwego/hertz/pkg/common/utils"
"github.com/cloudwego/hertz/pkg/protocol/consts"
"time"
)
func GroupMiddleware() app.HandlerFunc {
return func(ctx context.Context, c *app.RequestContext) {
fmt.Println("group middleware")
c.Next(ctx)
}
}
func main() {
h := server.Default(
server.WithHostPorts("127.0.0.1:8888"),
server.WithExitWaitTime(10*time.Second),
)
h.GET(
"/ping", func(ctx context.Context, c *app.RequestContext) {
c.JSON(consts.StatusOK, utils.H{"message": "pong"})
},
)
h.OnShutdown = append(
h.OnShutdown, func(ctx context.Context) {
fmt.Println("开始退出了1")
}, func(ctx context.Context) {
fmt.Println("开始退出了2")
}, func(ctx context.Context) {
fmt.Println("开始退出了3")
},
func(ctx context.Context) {
fmt.Println("开始退出了4")
},
)
h.Spin()
}
Hertz 使用 waitSignal
函数作为信号处理的默认实现方式,处理如下:
- 当接收到
SIGTERM
系统信号时触发立即退出。 - 当接收到
SIGHUP|SIGINT
系统信号时触发优雅退出。
当信号处理的默认实现方式无法满足需求时,可通过 SetCustomSignalWaiter
来自定义信号处理方式。
package main
import (
"context"
"fmt"
"github.com/cloudwego/hertz/pkg/app"
"github.com/cloudwego/hertz/pkg/app/server"
"github.com/cloudwego/hertz/pkg/common/utils"
"github.com/cloudwego/hertz/pkg/protocol/consts"
"os"
"os/signal"
"syscall"
"time"
)
func GroupMiddleware() app.HandlerFunc {
return func(ctx context.Context, c *app.RequestContext) {
fmt.Println("group middleware")
c.Next(ctx)
}
}
func main() {
h := server.Default(
server.WithHostPorts("127.0.0.1:8888"),
server.WithExitWaitTime(10*time.Second),
)
h.GET(
"/ping", func(ctx context.Context, c *app.RequestContext) {
c.JSON(consts.StatusOK, utils.H{"message": "pong"})
},
)
// 设置自定义信号处理函数
h.SetCustomSignalWaiter(
func(errChan chan error) error {
// 创建一个 channel 用于接收系统信号
sigChan := make(chan os.Signal, 1)
// 监听 SIGHUP、SIGINT 和 SIGTERM 信号
signal.Notify(sigChan, syscall.SIGHUP, syscall.SIGINT, syscall.SIGTERM)
// 等待信号
sig := <-sigChan
fmt.Printf("Received signal: %v\n", sig)
// 根据信号类型决定退出行为
switch sig {
case syscall.SIGTERM:
// 如果是 SIGTERM,返回 error 触发立即退出
return fmt.Errorf("received SIGTERM, exiting immediately")
case syscall.SIGHUP, syscall.SIGINT:
// 如果是 SIGHUP 或 SIGINT,不返回 error,触发优雅退出
fmt.Println("Received SIGHUP or SIGINT, starting graceful shutdown")
return nil
default:
// 其他信号,默认优雅退出
return nil
}
},
)
h.Spin()
}
当自定义信号处理函数返回 error
时 Hertz 会立即退出,其他情况下则会优雅退出。
本文来自博客园,作者:厚礼蝎,转载请注明原文链接:https://www.cnblogs.com/guangdelw/p/18742616
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 25岁的心里话
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列01:轻松3步本地部署deepseek,普通电脑可用
· 按钮权限的设计及实现
2023-02-28 shell中产生随机字符串的方法