一、gRPC 是什么?
gRPC 是由 Google 最初设计并开源的一套「高性能、通用的远程过程调用(RPC)框架 」。
简单说:它是一种让「一个程序可以像调用本地函数一样去调用远端服务」的通信框架。
它有几个关键特征:
- 使用 HTTP/2 作为底层传输协议
- 使用 Protocol Buffers(Protobuf) 作为默认数据序列化格式
- 天生支持 多语言、多平台(C++、Java、Go、Python、Node.js、C#、Rust 等等)
- 内置支持 流式通信、双向流,非常适合微服务、实时通信等场景
你可以把 gRPC 理解为:
比传统 REST/JSON 更高效的一套「服务间通信协议 + 工具链」。
二、为什么会有 gRPC?它要解决什么问题?
在微服务和分布式系统流行之后,服务间通信有这些典型痛点:
-
HTTP + JSON 的性能开销较大
- JSON 文本冗长、解析成本高,网络带宽和 CPU 都会消耗更多
- 对于高 QPS 内网调用,代价明显
-
接口定义不够规范、一致
- API 经常只存在于文档和代码注释中,缺乏强类型约束
- 不同服务、不同语言的实现容易产生细微差异
-
手写客户端代码繁琐、易出错
- 要自己拼 URL、拼 JSON、解析响应、处理错误逻辑
- 一旦接口变更,所有调用方都得手动修改
-
流式通信支持差
- 正常 HTTP/1.1 的请求-响应是「一来一回」,不便于:
- 服务器主动推送
- 客户端持续发送数据
- 双向实时流
- 正常 HTTP/1.1 的请求-响应是「一来一回」,不便于:
gRPC 就是为了解决这些问题而生的:
- 用二进制高效编码(Protobuf)+ HTTP/2
- 用统一的
.proto文件定义接口 - 根据接口自动生成服务端和客户端代码
- 原生支持四种通信模式(包括流式)
三、gRPC 的核心组成
1. Protocol Buffers(Protobuf)
Protobuf 是一种由 Google 设计的 结构化数据序列化协议,特点是:
- 二进制格式,体积小、效率高
- 强类型定义(类似于一个简化版的 IDL:Interface Definition Language)
- 有成熟代码生成器,支持多种语言
在 gRPC 中,你通常要写一个 .proto 文件,里面包含:
- 消息结构(消息类型 Message)
- 服务定义(Service + RPC 方法)
例如:
proto
syntax = "proto3";
package helloworld;
// 定义消息结构
message HelloRequest {
string name = 1;
}
message HelloReply {
string message = 1;
}
// 定义服务及其 RPC 方法
service Greeter {
rpc SayHello (HelloRequest) returns (HelloReply);
}
这份 .proto 文件就是单一事实来源(Single Source of Truth) :
根据它,工具会为你自动生成服务端和客户端代码。
2. HTTP/2
gRPC 默认运行在 HTTP/2 之上,带来一些关键优势:
- 多路复用(Multiplexing):一个 TCP 连接上可以同时跑多个流,避免 HTTP/1.1 的队头阻塞
- 头部压缩(HPACK):减少重复请求头带来的开销
- 双向流:客户端和服务端可以在一个连接上同时发数据
- 用于 长连接 & 实时通信 更合理
这也是为什么 gRPC 在高并发内网环境里性能普遍优于传统 REST。
3. RPC 调用模型
gRPC 支持四种调用模式:
-
Unary RPC(单次请求-响应)
类似传统 HTTP 调用:
protorpc GetUser (GetUserRequest) returns (GetUserResponse); -
Server Streaming RPC(服务端流式)
客户端发一次请求,服务端持续推送多个响应:
protorpc ListUsers (ListUsersRequest) returns (stream User); -
Client Streaming RPC(客户端流式)
客户端连续发送多个请求消息,最后由服务端返回一个响应:
protorpc UploadLogs (stream LogItem) returns (UploadResult); -
Bidirectional Streaming RPC(双向流式)
双方都可以持续发送消息,类似 WebSocket:
protorpc Chat (stream ChatMessage) returns (stream ChatMessage);
这四类模式,基本覆盖了大部分分布式系统下的通信需求。
四、gRPC 的工作流程(从 0 到 1)
以最常用的 Unary RPC 为例,过程大致如下:
-
定义协议(.proto 文件)
- 定义消息结构(请求、响应)
- 定义服务和 RPC 方法
-
代码生成
- 使用
protoc(Protobuf 编译器)+ gRPC 插件 - 生成:
- 服务端接口(需要你来实现具体逻辑)
- 客户端 Stub(供调用方直接使用)
- 使用
-
实现服务端逻辑
- 在目标语言中实现生成的接口:
- 例如 Go 中实现
GreeterServer接口的SayHello方法
- 例如 Go 中实现
- 在目标语言中实现生成的接口:
-
启动 gRPC 服务
- 绑定端口(通常是 TCP 端口)
- 注册服务实现
- 开始监听请求
-
在客户端使用 Stub 调用
- 初始化 gRPC Channel(给定服务地址)
- new 一个客户端 Stub
- 像调用本地函数一样调用
SayHello(request)
通讯过程中的细节(序列化、反序列化、网络传输、错误码处理)大多由框架自动完成。
五、gRPC 相比 REST/HTTP 的优缺点
1. 优点
-
性能和资源利用率高
- Protobuf 二进制编码:小体积、低延迟
- HTTP/2:多路复用、长连接,减少握手和队头阻塞
-
接口强类型 + 自动生成代码
- 接口由
.proto严格定义 - 类型安全,编译期就能发现很多错误
- 自动生成客户端 SDK,大幅降低调用成本
- 接口由
-
优秀的多语言支持
- 官方 & 社区提供的语言支持非常广泛
- 不同语言之间通信统一透明
-
流式通信、一等公民
- Server/Client/Bi-directional Streaming
- 很适合日志流、音视频、实时推送、IoT 等
-
生态完备
- 拦截器、超时、重试、负载均衡、服务发现、TLS 加密等支持比较完善
- 对接 Service Mesh(如 Istio、Linkerd)也很常见
2. 缺点 / 使用门槛
-
对浏览器支持不友好
- 浏览器原生不直接支持 HTTP/2 的 gRPC 二进制协议
- 通常要用 gRPC-Web 或网关(如 Envoy、grpc-gateway)转换成 HTTP/JSON
-
调试不如 REST 直观
- Protobuf + HTTP/2 不像 JSON/HTTP,不能简单用浏览器直接看
- 需要专门工具(如 BloomRPC、Postman 支持 gRPC、grpcurl 等)
-
学习曲线稍高
- 需要了解 Protobuf、.proto、代码生成器等
- 与传统「写个 Controller 暴露 HTTP 接口」的方式不同
-
对网络环境有要求
- 在某些代理、负载均衡、网关不支持 HTTP/2 的环境下,要额外配置或降级(比如 gRPC-Web 或 REST 转换)
六、典型使用场景
-
微服务内部通信(Service-to-Service)
- 高 QPS、内部网络带宽宝贵的场景
- 强类型接口、自动生成多语言 SDK,利于大团队协作
-
移动端/桌面客户端 与 服务器
- 高性能、低延迟需求
- 如:音视频通信、IM、实时协作工具
-
流式数据 / 实时推送
- 实时日志、监控数据上报
- 股票行情、游戏状态同步
- IoT 设备上传传感器数据
-
跨语言平台系统集成
- 一部分服务是 Java,一部分是 Go,还有 Python、Node.js 等
- 使用统一的 gRPC 协议极大简化集成复杂度
-
搭配 API Gateway 对外提供 REST
- 内部服务用 gRPC,高效通信
- 通过 Gateway(如 Envoy+gRPC-JSON 转换)对外暴露 HTTP/JSON API
七、gRPC 的生态和扩展能力
常见配套能力有:
- 认证与授权
- 基于 TLS 的双向认证(mTLS)
- Token / OAuth2 / JWT 等
- 可观测性(Observability)
- 日志、Tracing(如 OpenTelemetry)、Metrics(Prometheus)
- 负载均衡和服务发现
- 和 Kubernetes、Consul、Etcd、Eureka 等结合
- 拦截器(Interceptor / Middleware)
- 统一处理日志、鉴权、限流、熔断等横切逻辑
在大型微服务体系里,gRPC 往往和 Service Mesh、API Gateway、CI/CD 等一起构成一整套基础设施。
八、什么时候适合用 gRPC,什么时候不适合?
更适合用 gRPC 的情况:
- 微服务内部调用,高并发、高性能要求
- 多语言服务互相调用,希望减少对接成本
- 需要 长连接 + 流式、双向通信
- 内网环境较稳定,能很好支持 HTTP/2
可能更适合 REST/HTTP 的情况:
- 面向 普通 Web 浏览器 的公开 API
- 纯 CRUD 型业务,性能压力不大
- 客户端环境不可控,可能只支持最基本的 HTTP/1.1
- 团队对 gRPC 和 Protobuf 完全陌生,当前需求也不急迫
很多成熟系统的实践是:
- 内部服务:gRPC
- 对外开放:REST/HTTP(由网关转换而来)
九、简要总结
- gRPC 本质是 一个高性能、多语言的 RPC 框架
- 底层用 HTTP/2 ,数据用 Protobuf,性能好、功能强
- 通过
.proto文件定义接口,既是文档,也是代码生成的基础 - 相比 REST/JSON:
- 优点:高效、强类型、自动生成 SDK、流式通信
- 缺点:调试略麻烦、浏览器原生支持不好、需要学习成本
- 特别适合:
- 微服务内部通信
- 高性能、实时、流式场景
- 多语言大型系统