Hertz 是字节跳动服务框架团队研发的超大规模的企业级微服务 HTTP 框架,具有高易用性、易扩展、低时延等特点。在经过了字节跳动内部一年多的使用和迭代,如今已在 CloudWeGo 正式开源。目前,Hertz 已经成为了字节跳动内部最大的 HTTP 框架,线上接入的服务数量超过 1 万,峰值 QPS 超过 4 千万。除了各个业务线的同学使用外,也服务于内部很多基础组件,如:函数计算平台 FaaS、压测平台、各类网关、Service Mesh 控制面等,均收到不错的使用反馈。在如此大规模的场景下,Hertz 拥有极强的稳定性和性能,在内部实践中某些典型服务,如框架占比较高的服务、网关等服务,迁移 Hertz 后相比 Gin 框架,资源使用显著减少,CPU 使用率随流量大小降低 30%-60%,时延也有明显降低。
Hertz 坚持内外维护一套代码,为开源使用提供了强有力的保障。通过开源, Hertz 也将丰富云原生的 Golang 中间件体系,完善 CloudWeGo 生态矩阵,为更多开发者和企业搭建云原生化的大规模分布式系统,提供一种现代的、资源高效的的技术方案。
本文将重点关注 Hertz 的架构设计与功能特性。
最初,字节跳动内部的 HTTP 框架是对 Gin 框架的封装,具备不错的易用性、生态完善等优点。随着内部业务的不断发展,高性能、多场景的需求日渐强烈。而 Gin 是对 Golang 原生 net/http 进行的二次开发,在按需扩展和性能优化上受到很大局限。因此,为了满足业务需求,更好的服务各大业务线,2020 年初,字节跳动服务框架团队经过内部使用场景和外部主流开源 HTTP 框架 Fasthttp、Gin、Echo 的调研后,开始基于自研网络库 Netpoll 开发内部框架 Hertz,让 Hertz 在面对企业级需求时,有更好的性能及稳定性表现,也能够满足业务发展和应对不断演进的技术需求。
Hertz 设计之初调研了大量业界优秀的 HTTP 框架,同时参考了近年来内部实践中积累的经验。为了保证框架整体上满足:1. 极致性能优化的可能性;2. 面对未来不可控需求的扩展能力, Hertz 采用了 4 层分层设计,保证各个层级功能内聚,同时通过层级之间的接口达到灵活扩展的目标。整体架构图如图 1 所示。
图 1:Hertz 架构图
Hertz 从上到下分为:应用层、路由层、协议层和传输层,每一层各司其职,同时公共能力被统一抽象到公共层(common),做到跨层级复用。另外,同主库一同发布的还有作为子模块的 Hz 脚手架,它能够协助使用者快速搭建出项目核心骨架以及提供实用的构建工具链。
应用层是和用户直接交互的一层,提供丰富易用的 API,主要包括 Server、Client 和一些其他通用抽象。Server 提供了注册 HandlerFunc、Binding、Rendering 等能力;Client 提供了调用下游和服务发现等能力;以及抽象一个 HTTP 请求所必须涉及到的请求(Request)、响应(Response)、上下文(RequestContext)、中间件(Middleware)等等。Hertz 的 Server 和 Client 都能够提供中间件这样的扩展能力。
应用层中一个非常重要的抽象就是对 Server HandlerFunc 的抽象。早期,Hertz 路由的处理函数 (HandlerFunc)中并没有接收标准的 context.Context,我们在大量的实践过程中发现,业务方通常需要一个标准的上下文在 RPC Client 或者日志、Tracing 等组件间传递,但由于请求上下文(RequestContext)生命周期局限于一次 HTTP 请求之内,而以上提到的场景往往存在异步的传递和处理,导致如果直接传递请求上下文,会导致出现一些数据不一致的问题。为此我们做了诸多尝试,但是因为核心原因在于请求上下文(RequestContext)的生命周期无法优雅的按需延长,最终在各种设计权衡下,我们在路由的处理函数签名中增加一个标准的上下文入参,通过分离出生命周期长短各异的两个上下文的方式,从根本上解决各种因为上下文生命周期不一致导致的异常问题,即:
type HandlerFunc func(c context.Context, ctx *app.RequestContext)
路由层负责根据 URI 匹配对应的处理函数。
起初,Hertz 的路由基于 httprouter 开发,但随着使用的用户越来越多,httprouter 渐渐不能够满足需求,主要体现在 httprouter 不能够同时注册静态路由和参数路由,即 /a/b
,/:c/d
这两个路由不能够同时注册;甚至有一些更特殊的需求,如/a/b
、/:c/b
,当匹配 /a/b
路由时,两个路由都能够匹配上。
Hertz 为满足这些需求重新构造了路由树,用户在注册路由时拥有很高的自由度:支持静态路由、参数路由的注册;支持按优先级匹配,如上述例子会优先匹配静态路由 /a/b
;支持路由回溯,如注册 /a/b
、/:c/d
,当匹配 /a/d
时仍然能够匹配上;支持尾斜线重定向,如注册 /a/b
,当匹配 /a/b/
时能够重定向到 /a/b
上。Hertz 提供了丰富的路由能力来满足用户的需求,更多的功能可以参考 Hertz 配置文档。
协议层负责不同协议的实现和扩展。
Hertz 支持协议的扩展,用户只需要实现下面的接口便可以按照自己的需求在引擎(Engine) 上扩展协议,同时也支持通过 ALPN 协议协商的方式注册。Hertz 首批只开源了 HTTP1 实现,未来会陆续开源 HTTP2、QUIC 等实现。协议层扩展提供的灵活性甚至可以超越 HTTP 协议的范畴,用户完全可以按需注册任意符合自身需求的协议层实现,并且加入到 Hertz 的引擎中来,同时,也能够无缝享受到传输层带来的极致性能。
type ServerFactory interface {
New(core Core) (server protocol.Server, err error)
}
type Server interface {
Serve(c context.Context, conn network.Conn) error
}
传输层负责底层的网络库的抽象和实现。
Hertz 支持底层网络库的扩展。Hertz 原生完美适配 Netpoll,在时延方面有很多深度的优化,非常适合时延敏感的业务接入。Netpoll 对 TLS 能力的支持有待完善,而 TLS 能力又是 HTTP 框架必备能力,为此 Hertz 底层同时支持基于 Golang 标准网络库的实现适配,支持网络库的一键切换,用户可根据自己的需求选择合适的网络库进行替换。如果用户有更加高效的网络库或其他网络库需求,也完全可以根据需求自行扩展。
与 Hertz 一并开源的还有一个易用的命令行工具 Hz,用户只需提供一个 IDL,根据定义好的接口信息,Hz 便可以一键生成项目脚手架,让 Hertz 达到开箱即用的状态;Hz 也支持基于 IDL 的更新能力,能够基于 IDL 变动智能地更新项目代码。目前 Hz 支持了 Thrift 和 Protobuf 两种 IDL 定义。命令行工具内置丰富的选项,可以根据自己的需求使用。同时它底层依赖 Protobuf 官方的编译器和自研的 Thriftgo 的编译器,两者都支持自定义的生成代码插件。如果默认模板不能够满足需求,完全能够按需定义。
未来,我们将继续迭代 Hz,持续集成各种常用的中间件,提供更高层面的模块化构建能力。给 Hertz 的用户提供按需调整的能力,通过灵活的自定义配置打造一套满足自身开发需求的脚手架。
Common 组件主要存放一些公共的能力,比如错误处理、单元测试能力、可观测性相关能力(Log、Trace、Metrics 等)。对于服务可观测性的能力,Hertz 提供了默认的实现,用户可以按需装配;如果用户有特殊的需求,也可以通过 Hertz 提供的接口注入。比如对于 Trace 能力,Hertz 提供了默认的实现,也提供了将 Hertz 和 Kitex 串起来的 Example。如果想注入自己的实现,也可以实现下面的接口:
// Tracer is executed at the start and finish of an HTTP.
type Tracer interface {
Start(ctx context.Context, c *app.RequestContext) context.Context
Finish(ctx context.Context, c *app.RequestContext)
}
Hertz 除了提供 Server 的中间件能力,还提供了 Client 中间件能力。用户可以使用中间件能力将通用逻辑(如:日志记录、性能统计、异常处理、鉴权逻辑等等)和业务逻辑区分开,让用户更加专注于业务代码。Server 和 Client 中间件使用方式相同,使用 Use
方法注册中间件,中间件执行顺序和注册顺序相同,同时支持预处理和后处理逻辑。
Server 和 Client 的中间件实现方式并不相同。对于 Server 来说,我们希望减少栈的深度,同时也希望中间件能够默认的执行下一个,用户需要手动终止中间件的执行。因此,我们将 Server 的中间件分成了两种类型,即不在同一个函数调用栈(该中间件调用完后返回,由上一个中间件调用下一个中间件,如图 2 中 B 和 C)和在同一个函数调用栈的中间件(该中间件调用完后由该中间件继续调用下一个中间件,如图 2 中 C 和 Business Handler)。
图 2: 中间件链路
其核心是需要一个地方存下当前的调用位置 index,并始终保持其递增。恰好 RequestContext 就是一个存储 index 合适的位置。但是对于 Client,由于没有合适的地方存储 index,我们只能退而求其次,抛弃 index 的实现,将所有的中间件构造在同一调用链上,需要用户手动调用下一个中间件。
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 和其他框架性能对比
下面简单演示一下 Hertz 是如何开发一个服务的。
1 . 首先,定义 IDL,这里使用 Thrift 作为 IDL 的定义(也支持使用 Protobuf 定义的 IDL),编写一个名为 Demo 的 service。这个服务有一个 API: Hello,它的请求参数是一个 query,响应是一个包含一个 RespBody 字段的 Json。
// idl/hello.thrift
namespace go hello.example
struct HelloReq {
1: string Name (api.query="name");
}
struct HelloResp {
1: string RespBody;
}
service HelloService {
HelloResp Hello(1: HelloReq request) (api.get="/hello");
}
2 . 接下来我们使用 hz 生成代码,并整理和拉取依赖
$ hz new -idl idl/hello.thrift -mod Demo
$ go mod tidy && go mod verify
3 . 填充业务逻辑,比如我们返回 hello, ${Name}
,那我们在biz/handler/example/hello_service.go
中添加以下代码即可
// Hello .
// @router /hello [GET]
func Hello(ctx context.Context, c *app.RequestContext) {
var err error
var req example.HelloReq
err = c.BindAndValidate(&req)
if err != nil {
c.String(400, err.Error())
return
}
resp := new(example.HelloResp)
resp.RespBody = "hello, " + req.Name
c.JSON(200, resp)
}
4 . 编译并运行项目
$ go build
$ ./Demo
到现在一个简单的 Hertz 项目已经生成,下面我们来测试一下
$ curl http://localhost:8888/hello\?name\=Xiaoming
// 如果看到以下返回说明服务已经正常启动起来啦
$ {"RespBody":"hello, Xiaoming"}
(以上 demo 可以在 hertz-examples 中查看) 之后就可以愉快的构建自己的项目了。
希望以上的分享能够让大家对 Hertz 有一个整体上的认识。同时,我们也在不断地迭代 Hertz、完善 CloudWeGo 整体生态。
本文由哈喽比特于2年以前收录,如有侵权请联系我们。
文章来源:https://mp.weixin.qq.com/s/1rBn8yAT0FvgmcuxnSdTPg
京东创始人刘强东和其妻子章泽天最近成为了互联网舆论关注的焦点。有关他们“移民美国”和在美国购买豪宅的传言在互联网上广泛传播。然而,京东官方通过微博发言人发布的消息澄清了这些传言,称这些言论纯属虚假信息和蓄意捏造。
日前,据博主“@超能数码君老周”爆料,国内三大运营商中国移动、中国电信和中国联通预计将集体采购百万台规模的华为Mate60系列手机。
据报道,荷兰半导体设备公司ASML正看到美国对华遏制政策的负面影响。阿斯麦(ASML)CEO彼得·温宁克在一档电视节目中分享了他对中国大陆问题以及该公司面临的出口管制和保护主义的看法。彼得曾在多个场合表达了他对出口管制以及中荷经济关系的担忧。
今年早些时候,抖音悄然上线了一款名为“青桃”的 App,Slogan 为“看见你的热爱”,根据应用介绍可知,“青桃”是一个属于年轻人的兴趣知识视频平台,由抖音官方出品的中长视频关联版本,整体风格有些类似B站。
日前,威马汽车首席数据官梅松林转发了一份“世界各国地区拥车率排行榜”,同时,他发文表示:中国汽车普及率低于非洲国家尼日利亚,每百户家庭仅17户有车。意大利世界排名第一,每十户中九户有车。
近日,一项新的研究发现,维生素 C 和 E 等抗氧化剂会激活一种机制,刺激癌症肿瘤中新血管的生长,帮助它们生长和扩散。
据媒体援引消息人士报道,苹果公司正在测试使用3D打印技术来生产其智能手表的钢质底盘。消息传出后,3D系统一度大涨超10%,不过截至周三收盘,该股涨幅回落至2%以内。
9月2日,坐拥千万粉丝的网红主播“秀才”账号被封禁,在社交媒体平台上引发热议。平台相关负责人表示,“秀才”账号违反平台相关规定,已封禁。据知情人士透露,秀才近期被举报存在违法行为,这可能是他被封禁的部分原因。据悉,“秀才”年龄39岁,是安徽省亳州市蒙城县人,抖音网红,粉丝数量超1200万。他曾被称为“中老年...
9月3日消息,亚马逊的一些股东,包括持有该公司股票的一家养老基金,日前对亚马逊、其创始人贝索斯和其董事会提起诉讼,指控他们在为 Project Kuiper 卫星星座项目购买发射服务时“违反了信义义务”。
据消息,为推广自家应用,苹果现推出了一个名为“Apps by Apple”的网站,展示了苹果为旗下产品(如 iPhone、iPad、Apple Watch、Mac 和 Apple TV)开发的各种应用程序。
特斯拉本周在美国大幅下调Model S和X售价,引发了该公司一些最坚定支持者的不满。知名特斯拉多头、未来基金(Future Fund)管理合伙人加里·布莱克发帖称,降价是一种“短期麻醉剂”,会让潜在客户等待进一步降价。
据外媒9月2日报道,荷兰半导体设备制造商阿斯麦称,尽管荷兰政府颁布的半导体设备出口管制新规9月正式生效,但该公司已获得在2023年底以前向中国运送受限制芯片制造机器的许可。
近日,根据美国证券交易委员会的文件显示,苹果卫星服务提供商 Globalstar 近期向马斯克旗下的 SpaceX 支付 6400 万美元(约 4.65 亿元人民币)。用于在 2023-2025 年期间,发射卫星,进一步扩展苹果 iPhone 系列的 SOS 卫星服务。
据报道,马斯克旗下社交平台𝕏(推特)日前调整了隐私政策,允许 𝕏 使用用户发布的信息来训练其人工智能(AI)模型。新的隐私政策将于 9 月 29 日生效。新政策规定,𝕏可能会使用所收集到的平台信息和公开可用的信息,来帮助训练 𝕏 的机器学习或人工智能模型。
9月2日,荣耀CEO赵明在采访中谈及华为手机回归时表示,替老同事们高兴,觉得手机行业,由于华为的回归,让竞争充满了更多的可能性和更多的魅力,对行业来说也是件好事。
《自然》30日发表的一篇论文报道了一个名为Swift的人工智能(AI)系统,该系统驾驶无人机的能力可在真实世界中一对一冠军赛里战胜人类对手。
近日,非营利组织纽约真菌学会(NYMS)发出警告,表示亚马逊为代表的电商平台上,充斥着各种AI生成的蘑菇觅食科普书籍,其中存在诸多错误。
社交媒体平台𝕏(原推特)新隐私政策提到:“在您同意的情况下,我们可能出于安全、安保和身份识别目的收集和使用您的生物识别信息。”
2023年德国柏林消费电子展上,各大企业都带来了最新的理念和产品,而高端化、本土化的中国产品正在不断吸引欧洲等国际市场的目光。
罗永浩日前在直播中吐槽苹果即将推出的 iPhone 新品,具体内容为:“以我对我‘子公司’的了解,我认为 iPhone 15 跟 iPhone 14 不会有什么区别的,除了序(列)号变了,这个‘不要脸’的东西,这个‘臭厨子’。