这是我参与「第五届青训营 」伴学笔记创作活动的第 14 天
概览
Hertz是一个Golang 微服务HTTP框架,具有高易用性、高性能、高扩展性等特点,目前在字节跳动内部已广泛使用。
Hertz 架构设计
Hertz架构自底向上分为Transport,Protocol,Route,Application四层。
框架特点
- 高易用性
- 高性能
- 高扩展性 采用分层设计,提供了较多的接口以及默认的扩展实现,用户也可以自行扩展。
- 多协议支持 支持HTTP1.1、ALPN等协议,支持自定义构建协议解析逻辑
- 网络层切换能力 Hertz实现了Netpoll和Golong原生网络库间按需切换的能力。
Hertz路由
- hertz提供了GET、POST、PUT、DELETE、ANY等方法用于注册路由。
示例:
func RegisterRoute(h server.Hertz) {
h.GET("/get", func(ctx context.Context, c *app.RequestContext)) {
c.String(consts.StatusOK, "get")
}
}
- Hertz提供了路由组的组图,用于支持路由分组
v1 := h.Group("/v1")
v1.GET("/get", handler)
v1.POST("/post", handler)
v2 := h.Group("/v2")
v2.POST("/post", handler)
- Hertz 提供了参数路由和通配路由
- 路由优先级为静态路由 > 命名路由 > 通配路由
// 参数路由
h.GET("/hertz/:version")
// 通配路由
h.GET("/hertz/:version/*action")
Hertz参数绑定
hertz提供了Bind,Validate,BindAndValidate函数用于参数绑定和校验。
type Args struct {
Query string `query:"query"` //绑定query参数
QuerySlice []string `query:"q"`
Path string `path:"path"` //path参数
Header string `header:"header"` //header参数
Json string `json:"json"` //Json参数
Form string `form:"form"` //表单参数
Vd int `query:"vd" vd:"$==0||$==1"` //参数校验
}
func main() {
s := server.Default(server.WithHostPorts("127.0.0.1:8080"))
s.GET("/hello", func(c context.Context, ctx *app.RequestContext) {
// BindAndValidate
var args Args
err := ctx.BindAndValidate(&args)
})
}
Hertz中间件
Hertz的中间件主要分为客户端中间件和服务端中间件
服务端中间件
服务端中间件是 HTTP 请求-响应周期中的一个函数,提供了一种方便的机制来检查和过滤进入应用程序的 HTTP 请求, 例如记录每个请求或者启用CORS。中间件可以在请求更深入地传递到业务逻辑之前或之后执行。
实现一个中间件
// 方式一
func MyMiddleware() app.HandlerFunc {
return func(ctx context.Context, c *app.RequestContext) {
// pre-handle
// ...
c.Next(ctx)
}
}
// 方式二
func MyMiddleware() app.HandlerFunc {
return func(ctx context.Context, c *app.RequestContext) {
c.Next(ctx) // call the next middleware(handler)
// post-handle
// ...
}
}
中间件会按定义的先后顺序依次执行,可以使用以下方法终止中间件调用,但当前中间件将执行
Abort()终止后续调用AbortWithMsg(msg string, statusCode int)终止后续调用,并设置response中的body和状态码AbortWhitStatus(code int)终止后续调用,并设置状态码
设置中间件的方式
- Server级别中间件
h := server.Default()
h.Use(GlobalMiddleware())
- 路由组级别中间件
h := server.Default()
group := h.Group("/group")
group.Use(GroupMiddleware())
- 单一路由级别中间件
h.GET("/path", append(PathMiddleware(),
func(ctx context.Context, c *app.RequestContext) {
c.String(http.StatusOK, "path")
})...)
Hertz Client
Hertz提供了HTTP Client用于发送HTTP请求
c, err := client.NewClient()
if err != nil {
return
}
status, body, _ := c.Get(context.Background(), nil, url)