这是我参与「第五届青训营 」伴学笔记创作活动的第 3 天,记录一下对 hertz 框架的学习。
什么是 hertz
Hertz[həːts] 是一个 Golang 微服务 HTTP 框架,在设计之初参考了其他开源框架 fasthttp、gin、echo 的优势, 并结合字节跳动内部的需求,使其具有高易用性、高性能、高扩展性等特点,目前在字节跳动内部已广泛使用。
踩坑
可以根据官方文档快速搭建一个简单的 web 服务。
我按照文档的步骤进行服务搭建时,遇到了一点问题。
我使用的是 windows 环境,在运行go mod tidy命令之后下载的 hertz 的版本是 0.5.0。该版本的 hertz 在 windows 上存在 bug,尝试启动服务时出现了以下错误,可以看到原因是找不到unix.EPIPE和unix.ENOTCON两个常量。
# github.com/cloudwego/hertz/pkg/network/standard
C:\Users\86139\go\pkg\mod\github.com\cloudwego\hertz@v0.5.0\pkg\network\standard\connection.go:50:25: undefined: unix.EPIPE
C:\Users\86139\go\pkg\mod\github.com\cloudwego\hertz@v0.5.0\pkg\network\standard\connection.go:50:55: undefined: unix.ENOTCONN
去 github 看源码可以发现在 commit 3c814a3 已经修复了这个 bug,但最新的 release 版本(即0.5.0)在这个 commit 之前。因此要手动拉取一下最新的代码。
go get github.com/cloudwego/hertz@develop
当然,希望官方尽快发布新的 release 版本,解决 windows 用户的问题。
两个context
与 gin 不同的是,hertz 的 handler function 接收两个 context(context.Context 和 RequestContext)。
两个上下文主要有两点区别:
- 生命周期不同。RequestContext 的生命周期局限于一次 http 请求之内,而 context.Context 会在 RPC Client 或者日志、Tracing 等组件间传递,其生命周期可能是链路级别的;
- 协程安全性。RequestContext 协程不安全,不适合异步传递,但可以通过
Copy()方法获取一个协程安全的副本,而 context.Context 本身就是协程安全的。
// gin
r := gin.Default()
r.GET("/ping", func(ctx *gin.Context) {
ctx.JSON(http.StatusOK, gin.H{"message": "pong"})
})
// hertz
h := server.Default()
h.GET("/ping", func(c context.Context, ctx *app.RequestContext) {
ctx.JSON(consts.StatusOK, utils.H{"message": "pong"})
})