介绍
依赖两大技术
- HTTP/2 作为传输协议
- gRPC 底层用 HTTP/2,它支持:
- 多路复用(在一条 TCP 连接中并行传输多个请求和响应)
- 二进制传输(更紧凑、高效)
- 流式传输(客户端流、服务端流、双向流)
- 相比传统 HTTP/1.1 的请求-应答模式,HTTP/2 能实现长连接、减少延迟。
- gRPC 底层用 HTTP/2,它支持:
- Protocol Buffers(Protobuf)作为序列化协议
- gRPC 用 Protobuf 来定义服务接口和数据结构,传输数据时用 Protobuf 二进制序列化,这样数据体积小,解析速度快。
可以把 gRPC 看成:
- 一种规范和框架,用 HTTP/2 来传数据
- 用 Protobuf 来描述和序列化接口数据
- 最终形成一种轻量、高效、高性能的 RPC 协议
也就是说,gRPC 没有重新造一个底层网络协议,而是在 HTTP/2 之上构建标准化、高性能的 RPC 调用规范。
💡 一句话总结:gRPC = RPC 框架(协议规范) + HTTP/2(传输层) + Protobuf(序列化格式)
HTTP/2
特性 | HTTP/1.1 | HTTP/2 |
---|---|---|
传输方式 | 基于纯文本 | 基于二进制帧 |
连接复用 | 一个连接只能串行传输一个请求(需多个 TCP 连接并发) | 单一 TCP 连接中支持多路复用(并行多个请求流,不再“队头阻塞”) |
头部压缩 | 没有 | 使用 HPACK 算法压缩头部减少冗余 |
传输效率 | 相对较低 | 高(减少 RTT 延迟、减少资源浪费) |
服务器推送 | 没有 | 有(服务端可主动向客户端推资源) |
性能 | 并行度差,需拼接多个域名或连接 | 并行度高,减少 TCP 握手延迟,网络利用率更好 |
🔥 HTTP/2 性能为啥快?
- 多个请求/响应在单一连接中同时传输 → 避免排队
- 用二进制减少解析开销
- HPACK 压缩请求头减少重复数据
- 有流优先级控制,能保证重要资源先传完
💡 其实 Nginx 并不是直接把 HTTP/1.1 “升级”为 HTTP/2,而是
对外客户端提供 HTTP/2 支持
也就是:
- 浏览器 → Nginx:用 HTTP/2
- Nginx → 你的服务:可能是 HTTP/1.1,也可能是 HTTP/2
这种中间转换称为反向代理,它负责帮你让前端用户能用 HTTP/2,而你的后台服务暂时不用改。
FastAPI 底层用的是 Uvicorn 或 Hypercorn 这样的 ASGI 服务器。这些服务器默认只实现 HTTP/1.1,也就是浏览器跟你的服务之间是 HTTP/1.1。
- 🔍 Uvicorn 默认:只支持 HTTP/1.1,不直接支持 HTTP/2
- 🔍 Hypercorn:可以通过 TLS 配置支持 HTTP/2
✅ Uvicorn 自己目前只支持 HTTP/1.1,而要用 HTTP/2 就要用前端反代或者换成支持 HTTP/2 的服务器(如 Hypercorn)。
Protobuf
Protobuf(Protocol Buffers) 是 Google 开发的一种二进制序列化协议,用来把结构化数据(像对象、消息、DTO)序列化成紧凑、高效的二进制流。
与 JSON 相比:
- JSON:人可读(纯文本),体积大,序列化/反序列化较慢。
- Protobuf:不可读二进制,需要 .proto 定义文件生成对应类,体积非常小,序列化/反序列化快。
对比点 | JSON | Protobuf |
---|---|---|
格式 | 文本(UTF-8) | 二进制(紧凑) |
消息定义 | 无需预先定义 | 需先定义 .proto |
序列化体积 | 大 | 小(字段编号、无冗余) |
序列化速度 | 慢 | 快(直接写入二进制缓冲区) |
易读性 | 人可读 | 不可读(需工具解码) |
是否可压缩 | 仍可 gzip | 也能 gzip(再小一层) |
换句话说:
- Protobuf 相当于把对象紧凑地按二进制序列化(去掉字段名,换成字段编号、可变长整型等),属于数据结构优化。
- gzip 相当于对一串二进制做通用压缩算法(熵编码/LZ77等),属于算法级压缩。
{"a": "b","count": 123
}
定义消息规范,比如 my_data.proto:
syntax = "proto3";message MyData {string a = 1;int32 count = 2;
}
JSON | Protobuf |
---|---|
{“a”: “b”, “count”: 123} | b’\n\x01b\x10{'(二进制) |
直接可读 | 需用 .proto 定义结构 |
序列化速度较慢 | 序列化速度快 |
体积大 | 体积非常小 |
本地命令行测试公开gPRC
brew install grpcurl
grpcurl -plaintext grpcb.in:9000 list
- grpcurl 工具
- plaintext 表示用明文(非 TLS 加密),因为测试站点 grpcb.in:9000 没有启用 TLS
- list 会列出该 gRPC 服务提供的所有服务名称。
返回结果:
addsvc.Add
grpc.gateway.examples.examplepb.ABitOfEverythingService
grpc.reflection.v1alpha.ServerReflection
grpcbin.GRPCBin
hello.HelloService
你先用 list grpcbin.GRPCBin 查看它的方法:
➜ ~ grpcurl -plaintext grpcb.in:9000 list grpcbin.GRPCBin
grpcbin.GRPCBin.DummyBidirectionalStreamStream
grpcbin.GRPCBin.DummyClientStream
grpcbin.GRPCBin.DummyServerStream
grpcbin.GRPCBin.DummyUnary
grpcbin.GRPCBin.Empty
grpcbin.GRPCBin.HeadersUnary
grpcbin.GRPCBin.Index
grpcbin.GRPCBin.NoResponseUnary
grpcbin.GRPCBin.RandomError
grpcbin.GRPCBin.SpecificError
➜ ~ grpcurl -plaintext grpcb.in:9000 grpcbin.GRPCBin/Empty
{}
➜ ~ grpcurl -plaintext -d '{}' grpcb.in:9000 grpcbin.GRPCBin/DummyUnary
{}
gRPC本质
本质上 gRPC 就是:
✅ 网络通信服务
用 HTTP/2 做底层传输,跨网络/不同语言之间调用
✅ 高性能序列化
用 Protobuf 把数据压缩成二进制流传过去(对比 JSON 快很多,也体积更小)
✅ 远程过程调用(RPC)
客户端像本地调用函数一样调用远程服务,gRPC 负责帮你打包、发送、等待返回
gRPC 就是让Go 调用 Python 函数 这么方便又快的工具!
比如:
- 你有个 Python 模型服务,Go 微服务要用
- 用 gRPC 定义接口
- 两边各自用对应语言生成代码
- 直接 stub.MyService.Method() 像本地函数一样调用,但是底层走网络传 Protobuf 消息
🧠 为什么大家喜欢 gRPC:
- 🏎 快 — 二进制流,HTTP/2 多路复用。
- 🧮 类型安全 — .proto 定义好了,生成各语言客户端。
- ⚖️ 通用 — Go/Python/Java/… 全部支持。
🎯 也就是:一份 .proto,多语言生成各自代码,这就是 gRPC 的核心
让不同语言像调用本地函数一样调用远程服务!