介紹
依賴兩大技術
- 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 的核心
讓不同語言像調用本地函數一樣調用遠程服務!