Hertz 高性能框架
Hertz 是字节开源的高性能 HTTP 框架,采用自研网络层和 Reactor 模型,性能卓越。
一、架构概览
1.1 核心组件
Hertz 架构
├── Network Layer(网络层)
│ ├── netpoll(自研网络库)
│ └── I/O Multiplexing(IO 多路复用)
├── Protocol Layer(协议层)
│ ├── HTTP/1.1
│ ├── HTTP/2
│ └── WebSocket
├── Router(路由)
│ └── Radix Tree(基数树)
└── Middleware(中间件)
└── Chain(责任链)
1.2 快速入门
package main
import (
"github.com/cloudwego/hertz/pkg/app"
"github.com/cloudwego/hertz/pkg/app/server"
)
func main() {
h := server.Default()
h.GET("/hello", func(c context.Context, ctx *app.RequestContext) {
ctx.JSON(200, map[string]string{
"message": "Hello Hertz",
})
})
h.Spin()
}
二、netpoll 网络层
2.1 Reactor 模型
Hertz Reactor 模型
├── Main Reactor(主反应器)
│ └── 接受连接
├── Sub Reactors(子反应器)
│ ├── Reactor 1
│ ├── Reactor 2
│ └── Reactor N
└── Worker Pool(工作池)
└── 处理业务逻辑
2.2 事件循环
// 简化的事件循环
type EventLoop struct {
poller *Poller
conn *Conn
}
func (el *EventLoop) Run() {
for {
events, err := el.poller.Wait()
if err != nil {
continue
}
for _, event := range events {
switch event.Type {
case ReadEvent:
el.handleRead(event)
case WriteEvent:
el.handleWrite(event)
}
}
}
}
2.3 零拷贝
// 使用 nocopy 优化
type Request struct {
nocopy nocopy.NoCopy // 禁止复制
Header RequestHeader
Body []byte
}
// 内存池
var requestPool = sync.Pool{
New: func() any {
return &Request{}
},
}
func getRequest() *Request {
return requestPool.Get().(*Request)
}
func putRequest(req *Request) {
req.Reset()
requestPool.Put(req)
}
三、路由系统
3.1 基数树路由
// 路由注册
h.GET("/users/:id", handler)
h.GET("/users/:id/posts/:postId", handler)
// 路由匹配过程
// /users/123/posts/456
// ↓
// 匹配 /users/:id/posts/:postId
// ↓
// 提取参数 id=123, postId=456
3.2 路由组
// 路由组
v1 := h.Group("/api/v1")
{
v1.GET("/users", listUsers)
v1.POST("/users", createUser)
}
// 带中间件的路由组
auth := h.Group("/admin", AuthMiddleware())
{
auth.GET("/dashboard", dashboard)
}
四、中间件系统
4.1 中间件定义
// 中间件函数
type HandlerFunc func(c context.Context, ctx *app.RequestContext)
// 日志中间件
func Logger() app.HandlerFunc {
return func(c context.Context, ctx *app.RequestContext) {
start := time.Now()
path := string(ctx.Request.URI().Path())
ctx.Next(c)
latency := time.Since(start)
status := ctx.Response.StatusCode()
hertzlog.Infof("[%d] %s %v", status, path, latency)
}
}
4.2 中间件链
// 注册中间件
h.Use(Recovery(), Logger(), CORS())
// 执行顺序
// 1. Recovery (Before)
// 2. Logger (Before)
// 3. CORS (Before)
// 4. Handler
// 5. CORS (After)
// 6. Logger (After)
// 7. Recovery (After)
五、性能优化
5.1 内存池
// 字节切片池
var bytePool = sync.Pool{
New: func() any {
return make([]byte, 4096)
},
}
func getBuffer() []byte {
return bytePool.Get().([]byte)
}
func putBuffer(buf []byte) {
if cap(buf) == 4096 {
bytePool.Put(buf[:0])
}
}
5.2 连接复用
// Keep-Alive 支持
h := server.Default(
server.WithKeepAlive(true),
server.WithIdleTimeout(60 * time.Second),
)
// 连接池
transport := &http.Transport{
MaxIdleConns: 100,
MaxIdleConnsPerHost: 10,
IdleConnTimeout: 90 * time.Second,
}
5.3 性能对比
性能测试(Request/Second,越高越好)
Hertz: 150,000 req/s
Gin: 100,000 req/s
Echo: 95,000 req/s
net/http: 80,000 req/s
Hertz 性能优势:
1. 自研 netpoll 网络层
2. 零拷贝优化
3. 内存池复用
4. 智能预分配
六、最佳实践
6.1 项目结构
project/
├── cmd/
│ └── server/
│ └── main.go
├── internal/
│ ├── handler/
│ ├── middleware/
│ ├── model/
│ └── service/
├── pkg/
│ └── utils/
└── configs/
6.2 错误处理
// 统一错误处理
func handleError(c context.Context, ctx *app.RequestContext, err error) {
var httpErr *HTTPError
if errors.As(err, &httpErr) {
ctx.JSON(httpErr.Status, httpErr)
return
}
ctx.JSON(500, map[string]string{
"error": "Internal error",
})
}
6.3 优雅关闭
h := server.Default()
// 注册优雅关闭
h.OnShutdown = append(h.OnShutdown, func(ctx context.Context, server *server.Hertz) error {
log.Println("Shutting down...")
return nil
})
// 启动
h.Spin()
七、总结
Hertz 核心要点:
| 组件 | 实现 | 特点 |
|---|---|---|
| 网络层 | netpoll | 自研、Reactor 模型 |
| 路由 | 基数树 | O(log n) 匹配 |
| 中间件 | 责任链 | 灵活组合 |
| 性能 | 内存池 + 零拷贝 | 15 万 + QPS |
Hertz 通过自研网络层和零拷贝优化,实现了卓越的性能,适合高并发场景。