Hertz中的钩子函数

Hertz 提供的钩子函数功能。

钩子函数(Hooks)是一个通用的概念,表示某事件触发时所伴随的操作。

Hertz 提供了全局的 Hook 注入能力,用于在服务触发启动后退出前注入自己的处理逻辑。

阶段 执行方式 存储 签名
StartHook 端口监听器前执行 顺序依次执行 OnRun 属性存储 type CtxErrCallback func(ctx context.Context) error
ShutdownHook 服务推出前 并发执行,不讲顺序 OnShutdown 属性存储 type CtxCallback func(ctx context.Context)
OnAccept 建立连接前,不可读取数据 OnAccept func(conn net.Conn) context.Context
OnConnect 建立连接后,可读取数据 OnConnect func(ctx context.Context, conn network.Conn) context.Context

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(ctx context.Context, c *app.RequestContext) {
        c.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(ctx context.Context, c *app.RequestContext) {
        c.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(ctx context.Context, c *app.RequestContext) {
		c.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

OnAccept

OnAccept 是一个在连接建立后且被添加到 epoll 前调用的函数。

OnAccept func(conn net.Conn) context.Context

示例代码:

package main

import (
    "context"
    "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"
    "github.com/cloudwego/hertz/pkg/common/hlog"
    "net"
)

func main() {

    h := server.New(
        server.WithOnAccept(func(conn net.Conn) context.Context {
            hlog.Info("run the onAccept")
            return context.Background()
        }),
        server.WithHostPorts("localhost:9230"))
    h.GET("", func(ctx context.Context, c *app.RequestContext) {
        hlog.Info("pong")
        c.JSON(consts.StatusOK, utils.H{"ping": "pong"})
    })

    h.Spin()

}

提示:在发出请求后,将在控制台打印 OnAccept 函数的日志。

main.go:32: [Info] run the onAccept
main.go:38: [Info] pong

OnConnect

OnConnect 是一个在其被添加到 epoll 后调用的函数。它和 OnAccept 的不同之处在于它可以获取数据但是 OnAccept 不可以。

OnConnect func(ctx context.Context, conn network.Conn) context.Context

示例代码:

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/network"
	"github.com/cloudwego/hertz/pkg/protocol/consts"
)

func main() {

	h := server.New(
		server.WithHostPorts("localhost:9229"),
		server.WithOnConnect(func(ctx context.Context, conn network.Conn) context.Context {
			b, _ := conn.Peek(3)
			hlog.Info("onconnect")
			hlog.Info(b)
			return ctx
		}))
	h.GET("/ping", func(ctx context.Context, c *app.RequestContext) {
		c.JSON(consts.StatusOK, utils.H{"ping": "pong"})
	})
	h.Spin()

}

提示:在发出请求后,将在控制台打印 OnConnect 函数的日志。

main.go:19: [Info] onconnect
main.go:20: [Info] [71 69 84]
posted @ 2025-03-02 10:43  厚礼蝎  阅读(39)  评论(0)    收藏  举报