admin管理员组文章数量:1446757
grpc:好的部分
原文地址: /posts/grpc-the-good-parts/
虽然 REST API 仍是 Web 服务开发的主流选择,但 gRPC 正凭借其卓越的性能、效率和开发体验,受到越来越多的青睐。你可能看过我的文章《gRPC 的不足之处[1]》,其中提到了我对 gRPC 的一些不满。根据那篇文章的众多反馈,我本可以再写一篇续集来继续吐槽。但今天,我们换个角度,来探讨 gRPC 优秀 的一面。 gRPC:坏的部分
显然,许多人没有读完上篇文章的结尾——我曾指出,文中提到的许多问题如今已不复存在。因此,我决定专门写一篇文章,聚焦 gRPC 的优势。 让我们深入探讨 gRPC 在现代 Web 开发中的关键价值。
性能
这一点可能会引发争议,但 Protocol Buffers[2] 确实比 JSON 和 XML 更高效。多项测试[3]都证明了这一点。Protobuf 的高效性主要体现在以下几个方面:
- • 字段名不包含在消息中:Protobuf 使用数字标识字段,而 JSON 需要存储完整的字段名。通常,Protobuf 的字段编号仅占 1-2 字节,而 JSON 的字段名可能远超这个大小。
- • VARINT 类型优化[4]:小整数即使声明为 int64 也只需 1 字节。在大多数应用场景中,我们很少使用大整数,这种优化能显著减少数据占用,相比 ASCII 编码的数字更加高效。
- • 压缩优化:虽然 Protobuf 在字符串和字节数组方面并无特别优势,但 gRPC 支持数据压缩,使其至少能与 HTTP/JSON 方案持平。
在实际应用中,改用 Protobuf 编码后,我亲眼见证了数据传输量减少 50% 的效果。 当然,仍然有人质疑 Protobuf[5]。对我而言,最“致命”的缺陷是「map 的值不能是另一个 map」。从实现角度来看,这本应是可行的,但实际上并不被支持。例如:
代码语言:javascript代码运行次数:0运行复制message MapMessage {
map<string, MapValue> values = 1;
}
message MapValue {
map<string, string> nested = 1;
}
最令人困惑的是,我不明白为什么 value_type
不能是 map。最终只能通过包装类型来嵌套 map,虽然可行,但略显繁琐。这类问题在 gRPC 中时有发生。哎,这明明是一篇夸奖 gRPC 的文章,我们回到正题。
总的来说,Protobuf 在许多方面优于 JSON。当然,如果你更喜欢 JSON,gRPC 也完全支持 JSON[6]。虽然 gRPC 消息前会有少量二进制帧字节(不可读),但如果你真的在意这些,可以参考下文 ConnectRPC[7] 章节。
此外,大多数 gRPC 实现都支持自定义编码,因此你甚至可以采用自定义的序列化方案。
API 契约
告别松散的 API 类型推测。gRPC 依靠 protobuf
定义,提供了严谨的客户端-服务端契约,带来诸多优势:
- • 更少错误:明确的数据类型要求减少了数据不匹配的风险。
- • 更好的代码生成:支持多语言客户端/服务端代码自动生成,节省开发时间。
- • 更顺畅的 API 演进:有了稳定的契约,API 迭代时不易破坏已有客户端。
- • 自动化文档生成:API 定义即文档,始终与实现保持同步。
API 契约的强大之处,在我的另一篇文章《用契约构建 API[8]》中有更深入的讨论。
流式通信
gRPC 提供了一流的流式通信支持,消除了许多场景下的轮询需求,特别适用于:
- • 实时聊天应用:支持双向消息流,确保低延迟。
- • 实时更新:无需轮询,服务器可主动推送数据。
- • 需要持续通信的场景:如游戏、金融数据传输等。
如果你来自网络开发领域,可能知道基于 gRPC 的 gNMI 已取代 SNMP。通过 gNMI 订阅计数器更新,无需每分钟轮询网络设备。更多讨论可见《2024 年为何要选择 gNMI 而非 SNMP[9]》。
跨语言支持
gRPC 天然支持多语言,几乎涵盖所有主流编程语言。借助代码生成工具,你可以在不同技术栈之间无缝集成。
这一特性极大提升了团队协作效率,也让开发者能自由选择最适合的工具。
推动 HTTP/2 发展
gRPC 是 HTTP/2 普及的有力推动者,借助 HTTP/2 提供:
- • 多路复用:单连接支持多个请求/响应,提升传输效率。
- • 头部压缩:减少冗余数据,提高传输速度。
- • 整体性能优化:HTTP/2 是更现代的 Web 通信方式。
HTTP/3 进展
gRPC 正在推进对 HTTP/3 的支持。尽管官方进展缓慢,但已有多个社区实现,如:
- • .NET 的 dotnet-grpc
- • Rust 的 Tonic(基于 Hyper)
- • Go 语言的 ConnectRPC 与 quic-go
HTTP/3 进一步优化了连接建立速度、解决了队头阻塞[10]问题,并改善了丢包恢复能力。
逐步替换
若想逐步采用 gRPC 或需支持现有 REST 客户端,当前已有成熟方案:
JSON/HTTP 转码
使用 gRPC-Gateway[11]、Google Cloud Endpoints[12] 或 Envoy[13] 等工具,可以在后端享受 gRPC 优势的同时暴露 REST 风格接口。例如定义如下服务:
代码语言:javascript代码运行次数:0运行复制service Greeter {
rpc SayHello (HelloRequest) returns (HelloResponse) {
option (google.api.http) = {
get: "/v1/greeter/{name}"
};
}
}
即可通过 REST 端点访问:
代码语言:javascript代码运行次数:0运行复制curl http://localhost:8080/v1/greeter/world
这种自动转换能大幅减少支持多种 API 格式的工作量。
gRPC-Web
由于浏览器对 HTTP trailers 的支持限制,传统 gRPC 无法直接在 Web 使用。gRPC-Web 协议解决了这个问题,使浏览器也能使用 gRPC,并为仍在使用 HTTP/1.1 的平台(如某些 Unity[14] 版本)提供支持。
ConnectRPC
ConnectRPC[15] 能够从 gRPC 定义自动生成 JSON/HTTP API,同时保持与 gRPC/gRPC-Web 兼容。Connect 协议[16]更严格遵循 HTTP 标准,支持如下直观的 curl 调用:
代码语言:javascript代码运行次数:0运行复制curl \
--header "Content-Type: application/json" \
--data '{"name": "world"}' \
http://localhost:8080/greeter.v1.GreeterService/SayHello
Twirp
Twirp[17] 由 Twitch 开发,采用类似思路。其规范[18]通过 protobuf 生成更符合 HTTP 惯例的 API,但不直接支持 gRPC 协议,需要额外工作实现互操作。
工具生态
虽然官方工具链仍有不足,但社区生态蓬勃发展:
Buf CLI
Buf[19] 公司推出的 Buf CLI[20] 完全取代了官方的 protoc 编译器。它通过配置化管理 proto 文件依赖和代码生成,提供:
- • lint 检查:强制代码规范
- • 破坏性变更检测:防止协议不兼容修改
- • 简化工作流:替代 Makefile 等临时方案
第三方插件与工具
gRPC 拥有丰富的插件体系,比如:
- • protoc-gen-doc[21]:多格式文档生成,支持自定义模板
- • protoc-gen-connect-openapi[22](作者自荐):为 ConnectRPC 生成 OpenAPI 规范
- • protovalidate[23]:直接在 proto 中定义验证规则,期待其 TypeScript 支持[24]实现前后端验证逻辑共享 此外,Postman、Insomnia、k6 等主流工具都已加入 gRPC 支持阵营。
结语
gRPC 以卓越的性能、强类型契约、流式通信、跨语言能力和 HTTP/2 基础,成为现代 Web 开发的强大工具。无论你是要优化 API 交互,还是构建高效可扩展的系统,gRPC 都值得一试。 随着生态的持续发展,gRPC 的未来充满可能。如果你追求快速、可靠的 API 设计,不妨深入了解并尝试 gRPC,它或许能彻底改变你的开发方式。
引用链接
[1]
gRPC 的不足之处:/posts/grpc-the-bad-parts/
[2]
Protocol Buffers:/
[3]
多项测试:/
[4]
VARINT 类型优化:/%E8%A7%A3%E6%9E%90go-varint-%E7%9A%84%E4%BD%BF%E7%94%A8%E4%B8%8E%E5%AE%9E%E7%8E%B0%E5%8E%9F%E7%90%86/
[5]
质疑 Protobuf:/
[6]
gRPC 也完全支持 JSON:/programming-guides/proto3/#json
[7]
ConnectRPC:/posts/grpc-the-good-parts/#connectrpc
[8]
用契约构建 API:/posts/api-contracts/
[9]
2024 年为何要选择 gNMI 而非 SNMP:/posts/gnmi/
[10]
队头阻塞:
[11]
gRPC-Gateway:
[12]
Google Cloud Endpoints:
[13]
Envoy:/
[14]
Unity:.1030510/
[15]
ConnectRPC:/
[16]
Connect 协议:/
[17]
Twirp:/
[18]
其规范:.html
[19]
Buf:/
[20]
Buf CLI:/product/cli
[21]
protoc-gen-doc:
[22]
protoc-gen-connect-openapi:
[23]
protovalidate:
[24]
TypeScript 支持:
本文标签: grpc好的部分
版权声明:本文标题:grpc:好的部分 内容由网友自发贡献,该文观点仅代表作者本人, 转载请联系作者并注明出处:http://www.betaflare.com/biancheng/1748310271a2843193.html, 本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容,一经查实,本站将立刻删除。
发表评论