流式处理Hertz 提供 Server 和 Client 的流式处理能力 。HTTP 的文件场景是十分常见的场景,除了 Server 侧的上传场景之外,Client 的下载场景也十分常见 。为此,Hertz 支持了 Server 和 Client 的流式处理 。在内部网关场景中,从 Gin 迁移到 Hertz 后,cpu 使用量随流量大小不同可节省 30%-60% 不等,服务压力越大,收益越大 。Hertz 开启流式功能的方式也很容易,只需要在 Server 上或 Client 上添加一个配置即可,可参考 CloudWeGo 官网 Hertz 文档的流式处理部分 。
由于 Netpoll 采用 LT 的触发模式,由网络库主动将将数据从 TCP 缓冲区读到用户态,并存储到 buffer 中,否则 epoll 事件会持续触发 。因此 Server 在超大请求的场景下,由于 Netpoll 持续将数据读到用户态内存中,可能会有 OOM 的风险 。HTTP 文件上传场景就是一个典型的场景,但 HTTP 上传服务又是很常见的场景,因此我们支持标准网络库 go net,并针对 Hertz 做了特殊优化,暴露出 Read() 接口,防止 OOM 发生 。
对于 Client,情况并不相同 。流式场景下会将连接封装成 Reader 暴露给用户,而 Client 有连接池管理,那这样连接就多了一种状态,何时关连接,何时复用连接成了一个问题 。由于框架侧并不知道该连接何时会用完,框架侧复用该连接不现实,会导致串包问题 。由于 GC 会关闭连接,因此我们起初设想流式场景下的连接交由用户后,由 GC 负责关闭,这样也不会导致资源泄漏 。但是在测试后发现,由于 GC 存在一定时间间隔,另外 TCP 中主动关闭连接的一方需要等待 2RTT,在高并发场景下会导致 fd 被打满的情况 。最终我们提供了复用连接的接口,对于性能有场要求用户,在使用完连接后可以将连接重新放入连接池中复用 。
性能表现Hertz 使用字节跳动自研高性能网络库 Netpoll,在提高网络库效率方面有诸多实践,参考已发布文章字节跳动在 Go 网络库上的实践 。除此之外,Netpoll 还针对 HTTP 场景进行优化,通过减少拷贝和系统调用次数提高吞吐以及降低时延 。为了衡量 Hertz 性能指标,我们选取了社区中有代表性的框架 Gin(net/http)和 Fasthttp 作为对比,如图 3 所示 。可以看到,Hertz 的极限吞吐、TP99 等指标均处于业界领先水平 。未来,Hertz 还将继续和 Netpoll 深度配合,探索 HTTP 框架性能的极限 。
文章插图
图 3:Hertz 和其他框架性能对比
一个 Demo下面简单演示一下 Hertz 是如何开发一个服务的 。
- 首先,定义 IDL,这里使用 Thrift 作为 IDL 的定义(也支持使用 Protobuf 定义的 IDL),编写一个名为 Demo 的 service 。这个服务有一个 API: Hello,它的请求参数是一个 query,响应是一个包含一个 RespBody 字段的 Json 。
// idl/hello.thriftnamespace go hello.examplestruct HelloReq {1: string Name (api.query="name");}struct HelloResp {1: string RespBody;}service HelloService {HelloResp Hello(1: HelloReq request) (api.get="/hello");}
- 接下来我们使用 hz 生成代码,并整理和拉取依赖
$ hz new -idl idl/hello.thrift -mod Demo$ go mod tidy && go mod verify
- 填充业务逻辑,比如我们返回 hello,${Name},那我们在biz/handler/example/hello_service.go 中添加以下代码即可
// Hello .// @router /hello [GET]func Hello(ctx context.Context, c *app.RequestContext) {var err errorvar req example.HelloReqerr = c.BindAndValidate(&req)if err != nil {c.String(400, err.Error())return}resp := new(example.HelloResp)resp.RespBody = "hello, " + req.Namec.JSON(200, resp)}
- 编译并运行项目
$ go build$ ./Demo
到现在一个简单的 Hertz 项目已经生成,下面我们来测试一下$ curl http://localhost:8888/hello?name=Xiaoming// 如果看到以下返回说明服务已经正常启动起来啦$ {"RespBody":"hello, Xiaoming"}
(以上 demo 可以在 hertz-examples 中查看) 之后就可以愉快的构建自己的项目了 。后记希望以上的分享能够让大家对 Hertz 有一个整体上的认识 。同时,我们也在不断地迭代 Hertz、完善 CloudWeGo 整体生态 。欢迎各位感兴趣的同学们加入我们,共同建设 CloudWeGo 。
参考资料
- Hertz: https://github.com/cloudwego/hertz
- Hertz Doc: https://www.cloudwego.io/zh/docs/hertz/
- 字节跳动在 Go 网络库上的实践: https://www.cloudwego.io/zh/blog/2021/10/09/%E5%AD%97%E8%8A%82%E8%B7%B3%E5%8A%A8%E5%9C%A8-go-%E7%BD%91%E7%BB%9C%E5%BA%93%E4%B8%8A%E7%9A%84%E5%AE%9E%E8%B7%B5/
推荐阅读
- RustDesk - 免费开源的远程控制软件,流畅不限速,代替TeamViewer
- 抖音国际版起诉特朗普胜算几何-tiktok计划起诉特朗普政府-字节跳动将正式起诉特朗普政府
- 字节跳动将正式起诉特朗普政府-字节跳动起诉美国政府-字节跳动起诉美国政府有用吗
- 字节跳动将正式起诉特朗普政府-字节跳动为什么被美国制裁
- 字节跳动回应若不公正对待将起诉-字节跳动回应美国总统令
- 字节跳动回应:若不公正对待将起诉-若不公正对待诉诸美国法院
- 房颤和房扑哪个严重
- 字节否认微软求购TikTok全球业务-字节否认微软求购
- node-xlsx 简单几行代码处理导入导出 excel 数据,免费开源的 js 库
- 字节跳动将TikTok总部迁至伦敦-TikTok总部设在伦敦