Hooks
钩子函数(Hooks)是一个通用的概念,表示某事件触发时所伴随的操作。
Hertz 提供了全局的 Hook 注入能力,用于在服务触发启动后和退出前注入自己的处理逻辑。
StartHook
StartHook
在 Hertz 当中表示服务触发启动后需调用的函数,使用 CtxErrCallback
类型表示。Hertz 使用 OnRun
属性存储 StartHook
列表。
// CtxErrCallback 参见下方其函数签名
OnRun []CtxErrCallback
触发 Server 启动后,框架会按函数声明顺序依次调用所有的 StartHook
函数,完成调用之后,才会正式开始端口监听,如果发生错误,则立刻终止服务。
函数签名:
type CtxErrCallback func(ctx context.Context) error
示例代码:
package main
import (
"context"
"github.com/cloudwego/hertz/pkg/app"
"github.com/cloudwego/hertz/pkg/app/server"
"github.com/cloudwego/hertz/pkg/common/hlog"
"github.com/cloudwego/hertz/pkg/common/utils"
"github.com/cloudwego/hertz/pkg/protocol/consts"
)
func main() {
h := server.Default()
h.OnRun = append(h.OnRun, func(ctx context.Context) error {
hlog.Info("run the first start hook")
return nil
})
h.OnRun = append(h.OnRun, func(ctx context.Context) error {
hlog.Info("run the second start hook")
return nil
})
h.OnRun = append(h.OnRun, func(ctx context.Context) error {
hlog.Info("run the third start hook")
return nil
})
h.GET("/ping", func(c context.Context, ctx *app.RequestContext) {
ctx.JSON(consts.StatusOK, utils.H{"ping": "pong"})
})
h.Spin()
}
提示:启动服务,将在控制台顺序打印三个 StartHook
函数的日志。
main.go:17: [Info] run the first start hook
main.go:21: [Info] run the second start hook
main.go:25: [Info] run the third start hook
ShutdownHook
ShutdownHook
在 Hertz 当中表示服务退出前需调用的函数,使用 CtxCallback
类型表示。Hertz 使用 OnShutdown
属性存储 ShutdownHook
列表。
Server 退出前,框架会并发地调用所有声明的 ShutdownHook
函数,并且可以通过 server.WithExitWaitTime
配置最大等待时长,默认为5秒,如果超时,则立刻终止服务。
ShutdownHook
的调用本质上是 Hertz 优雅退出 的一环。
函数签名:
type CtxCallback func(ctx context.Context)
示例代码1:
package main
import (
"context"
"github.com/cloudwego/hertz/pkg/app"
"github.com/cloudwego/hertz/pkg/app/server"
"github.com/cloudwego/hertz/pkg/common/hlog"
"github.com/cloudwego/hertz/pkg/common/utils"
"github.com/cloudwego/hertz/pkg/protocol/consts"
)
func main() {
h := server.Default()
h.OnShutdown = append(h.OnShutdown, func(ctx context.Context) {
hlog.Info("run the first shutdown hook")
})
h.OnShutdown = append(h.OnShutdown, func(ctx context.Context) {
hlog.Info("run the second shutdown hook")
})
h.OnShutdown = append(h.OnShutdown, func(ctx context.Context) {
hlog.Info("run the third shutdown hook")
})
h.GET("/ping", func(c context.Context, ctx *app.RequestContext) {
ctx.JSON(consts.StatusOK, utils.H{"ping": "pong"})
})
h.Spin()
}
提示:终止服务,将在控制台乱序打印三个 ShutdownHook
函数的日志。
hertz.go:77: [Info] HERTZ: Begin graceful shutdown, wait at most num=5 seconds...
main.go:22: [Info] run the third shutdown hook
main.go:16: [Info] run the first shutdown hook
main.go:19: [Info] run the second shutdown hook
engine.go:279: [Info] HERTZ: Execute OnShutdownHooks finish
示例代码2:
package main
import (
"context"
"time"
"github.com/cloudwego/hertz/pkg/app"
"github.com/cloudwego/hertz/pkg/app/server"
"github.com/cloudwego/hertz/pkg/common/hlog"
"github.com/cloudwego/hertz/pkg/common/utils"
"github.com/cloudwego/hertz/pkg/protocol/consts"
)
func main() {
h := server.Default(server.WithExitWaitTime(time.Second * 2))
h.OnShutdown = append(h.OnShutdown, func(ctx context.Context) {
hlog.Info("run shutdown hook")
time.Sleep(time.Second * 5)
})
h.GET("/ping", func(c context.Context, ctx *app.RequestContext) {
ctx.JSON(consts.StatusOK, utils.H{"ping": "pong"})
})
h.Spin()
}
提示:终止服务时,因为钩子函数执行时间超过2秒,打印超时日志。
hertz.go:77: [Info] HERTZ: Begin graceful shutdown, wait at most num=2 seconds...
main.go:17: [Info] run shutdown hook
engine.go:276: [Info] HERTZ: Execute OnShutdownHooks timeout: error=context deadline exceeded
最后修改
April 18, 2023
: docs(wip): request context handler (36ea2d4)