gRPC 与传统 REST API 的区别与实践详解
一、前言
在现代分布式系统和微服务架构中,服务间通信协议的选择极其关键。RESTful API 是 Web 时代的标准,而 gRPC 作为 Google 推出的高性能远程调用框架,近年来在高性能、微服务场景下日益流行。很多开发者在选型时都会有疑问:gRPC 和 REST 有什么区别?什么时候用哪个更好?
本文将从最基础的 RPC 概念讲起,对比 gRPC 与 REST 的核心区别、原理、工程用法、以及实际选型建议。
二、什么是 RPC?
1. 概念解释
RPC(Remote Procedure Call,远程过程调用) 是一种让开发者像调用本地函数一样,去调用远程服务器上的方法的技术。
- 本地调用
add(1, 2)
,在本机执行。 - 用 RPC 调用
add(1, 2)
,底层会自动发请求到远程服务器,服务器处理后返回结果,本地像用普通函数一样得到结果。
2. RPC 的本质
- 让网络调用变得像本地函数一样简单。
- 不需要关心网络传输、序列化、协议细节。
- 典型用途:微服务、分布式系统、服务化架构。
3. RPC 的发展
- 早期:Java RMI、XML-RPC、SOAP、CORBA
- 现代:gRPC(Google)、Thrift(Apache)、Dubbo(阿里巴巴)
三、REST API 基础回顾
REST(Representational State Transfer) 是一种面向资源的 Web API 设计风格。
- 每个 URL 代表一个资源,用 HTTP 动词(GET/POST/PUT/DELETE)进行操作。
- 以 JSON(或 XML)为主要数据格式,通用性好。
- 天然适配浏览器、HTTP 客户端,易于调试和测试。
例子:
bash
GET /users/123 # 获取用户
POST /users # 创建用户
PUT /users/123 # 修改用户
DELETE /users/123 # 删除用户
四、gRPC 原理与特性
1. 基本原理
- gRPC(Google Remote Procedure Call)是一种高性能、开源、支持多语言的 RPC 框架。
- 基于 HTTP/2 协议进行通信,数据使用 Protocol Buffers(Protobuf)二进制序列化,效率高。
- 接口定义用
.proto
文件,前后端根据接口定义自动生成代码。
2. gRPC 的主要特性
- 高性能:HTTP/2、多路复用、头部压缩、二进制数据
- 强类型:接口和数据结构由 .proto 文件约束,避免低级错误
- 多语言支持:官方支持 10+ 语言(Java、Go、Python、C#、Node.js、Dart 等)
- 流式通信:原生支持单向流、双向流(如实时推送、IM、音视频)
- 自动生成代码:接口定义一次,多端生成,开发效率高
接口定义示例(.proto 文件):
ini
syntax = "proto3";
service UserService {
rpc GetUser (UserRequest) returns (UserReply) {}
}
message UserRequest {
string user_id = 1;
}
message UserReply {
string user_id = 1;
string username = 2;
}
五、gRPC 和 REST API 的核心区别
方面 | gRPC | REST(HTTP API) |
---|---|---|
通信协议 | HTTP/2 | HTTP/1.1(主流) |
序列化格式 | Protobuf(二进制) | JSON(文本) |
调用方式 | 面向"方法/过程",强类型 | 面向"资源",松耦合 |
性能 | 高,低延迟,节省带宽 | 通用但体积大,延迟稍高 |
流式通信 | 原生支持双向/单向流 | 仅支持短连接/轮询/推送 |
浏览器支持 | 原生不支持,需 gRPC-Web 适配 | 天然支持 |
代码生成 | 支持多语言自动生成 | 一般用 Swagger/OpenAPI 生成文档 |
适用场景 | 微服务、服务间通信、实时场景 | Web/Mobile API,对外服务 |
1. 通信协议和性能
- gRPC 用 HTTP/2,支持连接复用、头压缩和流式,性能大幅领先 REST 的 HTTP/1.1。
- REST 一般用 HTTP/1.1,每个请求/响应独立,效率较低。
2. 数据格式
- gRPC 用 Protobuf,数据量小、序列化/反序列化快,但不易人读。
- REST 用 JSON,通用易读,带宽/解析开销更高。
3. 调用方式与开发体验
- gRPC :所有接口和数据结构在
.proto
中强类型定义,客户端像本地函数一样调用服务端(如userService.getUser(req)
),开发体验极好,易维护。 - REST:用 HTTP 动词+URL,请求体/响应体无类型约束,出错风险高,开发需手动拼装参数。
4. 浏览器支持
- REST:天然支持 Web/移动端各种客户端,前端调用无障碍。
- gRPC:原生不能直接被浏览器 JS 调用,但可以用 gRPC-Web 适配(中间件转译)。
5. 代码生成
- gRPC :后端和多端(Android/iOS/Go/Python 等)一套
.proto
,自动生成所有模型和调用代码,极大减少手写/同步工作。 - REST:只能用 Swagger/OpenAPI 生成接口文档和部分 SDK,类型安全性差,开发协同难度大。
六、代码对比示例
REST API 例子(Dart/Flutter 假代码)
ini
final response = await http.get(Uri.parse('https://api.example.com/users/123'));
final data = json.decode(response.body);
final user = UserModel.fromJson(data);
gRPC 例子(Dart/Flutter 假代码)
ini
final req = UserRequest(userId: '123');
final resp = await userServiceClient.getUser(req);
print(resp.username);
可以看到,gRPC 是强类型、面向对象的开发体验,更像直接调用本地方法。
七、实际选型建议
1. 推荐用 gRPC 的场景
- 微服务体系内部服务间通信
- 后端与后端、服务与服务之间的数据交互
- 实时通信、高性能、大流量场景(IM、音视频、推流、物联网等)
- 多端 SDK 自动生成,团队开发分工协作多
2. 推荐用 REST 的场景
- 对外开放的 API、Web/Mobile 客户端
- 快速原型开发、前后端协作以浏览器为主
- 需要易于调试、易于集成第三方服务时
3. 混合用法
-
很多大公司/中大型项目都采用"内部 gRPC、外部 REST"的双轨架构:
- 微服务内部高效通信用 gRPC
- 对外服务、前端调用仍暴露 RESTful API
八、常见问题
Q1: gRPC 为什么不能直接用于浏览器?
A1: 因为浏览器不直接支持 HTTP/2 的特性和 Protobuf 编解码,所以需要 gRPC-Web 适配。
Q2: gRPC 真的比 REST 快吗?
A2: 在高并发、流式通信和大数据量场景下,gRPC 性能明显优于 REST。但简单接口差距不大。
Q3: gRPC 支持哪些语言?
A3: Java、Go、C#、C++、Python、Dart、Kotlin、Swift、Node.js、Ruby 等,生态极其丰富。
Q4: REST 会被淘汰吗?
A4: 不会。REST 易于集成、调试、文档丰富,在公开 API 领域长期有生命力。
九、总结
- gRPC 和 REST 本质区别在于通信协议、数据格式和开发方式。
- gRPC 性能高、强类型、自动代码生成,适合服务间通信和高性能场景。
- REST 通用易用、无平台壁垒,适合公开 API、Web/Mobile 客户端。
- 实际开发中,按需选型/混合使用才是最优解。