← 返回题目列表

gRPC 和 REST 有什么区别?微服务间通信该怎么选?

中等 第 20 / 24 题 更新于 2026/07/28
gRPCRESTProtobuf服务通信

简化版

**REST 和 gRPC 是微服务间通信的两种主流方式,核心区别在「协议、数据格式、性能、契约」:**REST 基于 HTTP/1.1 + JSON(文本、人类可读、通用),gRPC 基于 HTTP/2 + Protobuf(Protocol Buffers,二进制)gRPC 的优势① 性能高——Protobuf 是二进制、体积小、序列化快,HTTP/2 支持多路复用(一个连接并发多请求)、头部压缩;② 强契约——用 .proto 文件定义接口和消息结构,编译生成各语言的客户端/服务端代码(强类型、跨语言一致);③ 支持流式——双向流、客户端流、服务端流(REST 传统请求-响应做不到)。REST 的优势① 通用简单——基于 HTTP + JSON,浏览器/任何 HTTP 客户端都能调,调试方便(curl/Postman);② 生态成熟——工具、文档、缓存、网关全套支持。怎么选对外开放的 API(给前端/第三方)用 REST(通用、易调试);微服务内部之间的高频调用用 gRPC(性能、强契约、流式);很多公司「外部 REST + 内部 gRPC」混用。

详细版

gRPC vs REST 对比

维度RESTgRPC
协议HTTP/1.1(通常)HTTP/2
数据格式JSON(文本)Protobuf(二进制)
性能一般(文本大、解析慢)高(二进制小、快)
契约弱(靠文档/OpenAPI)强(.proto 生成代码)
流式不支持(请求-响应)支持(双向流/客户端流/服务端流)
可读性好(人能读 JSON)差(二进制)
浏览器直接调不能直接(需 grpc-web)
跨语言通用通用(proto 生成各语言代码)
调试方便(curl/Postman)需专门工具(grpcurl)
// gRPC 用 .proto 定义接口和消息(强契约)
syntax = "proto3";

message UserRequest { int64 id = 1; }
message UserResponse { int64 id = 1; string name = 2; int32 age = 3; }

service UserService {
    rpc GetUser(UserRequest) returns (UserResponse);        // 一元调用
    rpc ListUsers(UserRequest) returns (stream UserResponse); // 服务端流
    rpc Chat(stream Message) returns (stream Message);       // 双向流
}
// → 编译后生成 Java/Go/Python 等的客户端和服务端桩代码
REST:GET /users/123  →  { "id": 123, "name": "Tom", "age": 18 }(JSON)
gRPC:userService.getUser(request)  →  强类型的 UserResponse 对象(Protobuf 二进制传输)

⚠️ gRPC 和 REST 不是「谁取代谁」,而是「各有适用场景」,很多架构是「对外 REST + 对内 gRPC」混用对外的 API(给浏览器前端、给第三方开发者)优先 REST——因为它基于通用的 HTTP + JSON,任何客户端都能调、浏览器能直接用、调试方便(Postman/curl)、生态成熟(缓存、网关、文档工具全套),而 gRPC 的二进制、HTTP/2、需要 proto 文件对外部使用者不友好(浏览器还不能直接调 gRPC,要靠 grpc-web 代理)。微服务内部之间的高频调用优先 gRPC——因为内部调用追求性能(Protobuf 二进制小而快、HTTP/2 多路复用)、强类型契约(proto 生成代码,服务间接口一致、编译期检查)、且能用流式(如实时数据推送)。所以答案往往不是二选一,而是「看是对外还是对内」。

完整版教学

一、REST:基于 HTTP + JSON

先理解 REST 的特点:

REST(Representational State Transfer):
  基于 HTTP,用 URL 表示资源、HTTP 方法表示操作、JSON 传数据
  GET /users/123      查询用户 123
  POST /users         创建用户
  PUT /users/123      更新
  DELETE /users/123   删除
  → 资源导向、HTTP 语义、JSON 数据

特点:
  ① 通用——基于标准 HTTP,任何 HTTP 客户端都能调
  ② 人类可读——JSON 是文本,能直接看懂、调试方便
  ③ 无强契约——接口靠文档约定(或 OpenAPI/Swagger 描述)
     没有编译期检查,字段拼错、类型不对运行时才发现
  ④ 生态成熟——网关、缓存、认证、监控工具全套支持

缺点(相比 gRPC):
  ① 性能——JSON 文本冗余(字段名重复)、解析慢
  ② HTTP/1.1——每个请求要占用连接(虽有 keep-alive,但无多路复用)
  ③ 不支持流式(传统请求-响应模型)
  ④ 弱契约——接口变更容易出错(客户端不知道服务端改了字段)

REST 基于 HTTP + JSON——URL 表示资源、HTTP 方法表示操作、JSON 传数据(GET /users/123)。特点:通用(任何 HTTP 客户端能调)、人类可读(JSON 文本、调试方便)、无强契约(靠文档/OpenAPI 约定、无编译期检查、字段拼错运行时才发现)、生态成熟。缺点:性能一般(JSON 冗余解析慢)、HTTP/1.1 无多路复用、不支持流式、弱契约。理解「REST 基于 HTTP+JSON(资源导向)、通用+人类可读+生态成熟、但无强契约(靠文档运行时才发现错)+性能一般+不支持流式」,就掌握了 REST 的特点。

二、gRPC:基于 HTTP/2 + Protobuf

再理解 gRPC 的特点:

gRPC(Google Remote Procedure Call):
  基于 HTTP/2,用 Protobuf 序列化,用 .proto 定义接口
  调用像"调本地方法":userService.getUser(request)
  → RPC 风格(远程过程调用),不是资源导向

三个核心技术:
  ① HTTP/2:
     - 多路复用(一个连接并发多个请求,不用等前一个)
     - 头部压缩、二进制帧
     - 支持流式(双向流)
  ② Protobuf(Protocol Buffers):
     - 二进制序列化(不是文本 JSON)
     - 体积小(不传字段名,用字段编号)、序列化/反序列化快
     - 强类型(proto 定义了每个字段的类型)
  ③ .proto 文件(接口定义 IDL):
     - 定义 service(方法)和 message(数据结构)
     - 编译生成各语言的客户端/服务端代码(强契约、跨语言一致)

优势:
  高性能(二进制 + HTTP/2)、强契约(proto 生成代码)、支持流式
缺点:
  二进制不可读、浏览器不能直接调、调试需专门工具、学习成本

gRPC 基于 HTTP/2 + Protobuf——用 .proto 定义接口、调用像调本地方法(RPC 风格)。三个核心技术:① HTTP/2(多路复用一个连接并发多请求、头部压缩、支持流式);② Protobuf(二进制序列化、体积小(不传字段名用编号)、快、强类型);.proto 文件(IDL 定义 service 和 message、编译生成各语言代码、强契约跨语言一致)。优势:高性能、强契约、支持流式。缺点:二进制不可读、浏览器不能直接调、调试需专门工具。理解「gRPC 基于 HTTP/2+Protobuf(RPC 风格)、三核心:HTTP/2(多路复用/流式)+Protobuf(二进制小而快强类型)+.proto(生成各语言代码强契约)、优势高性能强契约流式、缺点不可读浏览器不能直接调」,就掌握了 gRPC 的特点。

三、性能差异:为什么 gRPC 更快

深入理解 gRPC 性能更好的原因:

① 数据格式:Protobuf(二进制)vs JSON(文本)
  JSON:{"userId": 123, "userName": "Tom"}
    → 字段名"userId""userName"重复传输、文本冗余、要解析字符串
  Protobuf:二进制,字段用编号(1, 2)代替字段名、紧凑编码
    → 体积小(可能只有 JSON 的 1/3~1/10)、解析快(直接读二进制)

② 传输协议:HTTP/2 vs HTTP/1.1
  HTTP/1.1:一个连接同一时间只能处理一个请求(队头阻塞)
    → 并发要开多个连接
  HTTP/2:多路复用——一个连接上并发多个请求(互不阻塞)
    → 连接复用、并发高、头部压缩

③ 综合效果:
  Protobuf 小而快 + HTTP/2 多路复用
  → gRPC 的吞吐、延迟通常明显优于 REST(尤其高频、小消息场景)

量化感受(大致):
  同样的数据,Protobuf 序列化后可能是 JSON 的 1/3 大小、快几倍
  高并发下 HTTP/2 的连接效率也远高于 HTTP/1.1

所以内部微服务高频调用,gRPC 的性能优势很实在

gRPC 更快的原因:① 数据格式 Protobuf(二进制)vs JSON(文本)——JSON 字段名重复、文本冗余、解析慢;Protobuf 二进制、字段用编号、紧凑(可能只有 JSON 的 1/3~1/10)、解析快;② 传输协议 HTTP/2 vs HTTP/1.1——HTTP/1.1 一个连接同时一个请求(队头阻塞),HTTP/2 多路复用(一个连接并发多请求、头部压缩)。综合 Protobuf 小而快 + HTTP/2 多路复用,gRPC 吞吐/延迟明显优于 REST(尤其高频小消息)。理解「gRPC 快因:Protobuf 二进制(小而快,字段用编号)vs JSON 文本冗余、HTTP/2 多路复用(一连接并发多请求)vs HTTP/1.1 队头阻塞、综合吞吐延迟明显优于 REST」,就理解了性能差异的原因。

四、契约与流式

gRPC 的另外两个优势:强契约和流式:

强契约(.proto 生成代码):
  .proto 文件定义了接口和消息结构(强类型)
  → 编译生成客户端和服务端的桩代码(各语言一致)
  → 好处:
    ① 客户端和服务端用同一份契约(proto),接口一致
    ② 强类型——字段类型编译期检查,不像 JSON 拼错运行时才发现
    ③ 跨语言——Java 服务端、Go 客户端,用同一份 proto 生成,无缝对接
    ④ 契约先行——先定义 proto,再各自实现

  对比 REST 的弱契约:
    REST 接口靠文档(或 OpenAPI)约定,没有强制
    服务端改了字段,客户端不知道 → 运行时才出错

流式(HTTP/2 支持):
  gRPC 支持四种调用模式:
    ① 一元(Unary):一次请求一次响应(像普通 RPC)
    ② 服务端流:一次请求,服务端返回一个流(多个响应)
       → 如实时推送、大结果集分批返回
    ③ 客户端流:客户端发一个流,服务端一次响应
       → 如上传大文件分块
    ④ 双向流:客户端和服务端都是流
       → 如实时聊天、双向数据同步

  REST 传统请求-响应做不到流式(要靠 WebSocket/SSE 变通)

所以 gRPC 的强契约(proto)和流式是它相比 REST 的独特能力

gRPC 的另外两个优势:① 强契约.proto 定义接口和消息、编译生成各语言桩代码——客户端服务端用同一份契约、强类型编译期检查、跨语言无缝、契约先行;对比 REST 弱契约靠文档、改字段客户端不知道运行时才出错);② 流式(HTTP/2 支持四种模式:一元、服务端流(实时推送/大结果集分批)、客户端流(上传大文件分块)、双向流(实时聊天);REST 传统请求-响应做不到流式要靠 WebSocket/SSE 变通)。理解「gRPC 强契约(.proto 生成各语言代码、强类型编译期检查、跨语言、契约先行,对比 REST 弱契约靠文档)、流式(四模式:一元/服务端流/客户端流/双向流,REST 做不到要 WebSocket)」,就掌握了 gRPC 的另外两个优势。

五、REST 的优势与适用

REST 也有 gRPC 比不了的优势:

REST 的优势:
  ① 通用简单——基于标准 HTTP + JSON
     任何 HTTP 客户端(浏览器、curl、任何语言的 HTTP 库)都能调
     不用生成代码、不用特殊协议
  ② 人类可读——JSON 文本,调试方便
     浏览器直接打开、Postman/curl 一键测、日志能直接看内容
  ③ 生态成熟——HTTP 生态全套支持
     缓存(HTTP 缓存)、网关、负载均衡、认证、监控、API 文档(Swagger)
  ④ 浏览器友好——浏览器能直接调(gRPC 不能,要 grpc-web 代理)
  ⑤ 松耦合——客户端和服务端不用共享 proto,独立演进

适用 REST:
  - 对外开放的 API(给前端、给第三方开发者)
  - 需要浏览器直接调用的
  - 需要方便调试、人类可读的
  - 简单的、非高频的调用
  - 需要利用 HTTP 缓存的

所以 REST 在"通用性、易用性、生态"上强,
  对外 API、浏览器交互、调试友好的场景是它的主场

REST 的优势:① 通用简单(标准 HTTP+JSON,任何客户端能调、不用生成代码);② 人类可读(JSON 文本、浏览器/Postman/curl 调试方便);③ 生态成熟(HTTP 缓存、网关、认证、Swagger 文档全套);④ 浏览器友好(gRPC 浏览器不能直接调要 grpc-web);⑤ 松耦合(不用共享 proto、独立演进)。适用:对外开放 API、需浏览器调用、需方便调试、简单非高频调用、需 HTTP 缓存。理解「REST 优势:通用简单(任何客户端能调)、人类可读(调试方便)、生态成熟(缓存/网关/Swagger)、浏览器友好、松耦合;适用对外 API/浏览器交互/调试友好/简单调用」,就掌握了 REST 的优势和适用。

六、怎么选:对外 REST + 对内 gRPC

综合对比,给出选择建议:

选择原则(不是二选一,看场景):

对外的 API(给前端、第三方)→ REST:
  - 通用、浏览器能调、调试方便、生态成熟
  - 外部使用者不想装 gRPC 工具、不想处理 proto

微服务内部之间的调用 → gRPC(高频/性能敏感时):
  - 性能高(Protobuf + HTTP/2)
  - 强契约(proto,服务间接口一致、编译期检查)
  - 支持流式
  - 内部可控(大家都用 gRPC,不用考虑通用性)

典型架构(混用):
  浏览器/App ──REST──> API 网关 ──gRPC──> 内部微服务集群
                                    微服务间也用 gRPC
  → 对外 REST(通用友好),对内 gRPC(高性能强契约)

其他考量:
  - 团队熟悉度、现有技术栈
  - 是否需要流式(要就 gRPC)
  - 是否强调调试友好、人类可读(要就 REST)
  - 消息大小/调用频率(大量高频小消息 gRPC 优势大)

结论:
  没有绝对好坏,对外通用用 REST、对内高性能用 gRPC,混用是常态

选择原则(看场景,不是二选一):对外 API(前端/第三方)用 REST(通用、浏览器能调、调试方便、生态成熟);微服务内部高频/性能敏感调用用 gRPC(性能高、强契约、流式、内部可控)。典型架构混用:浏览器/App ──REST──> API 网关 ──gRPC──> 内部微服务(对外 REST 友好、对内 gRPC 高性能)。其他考量:团队熟悉度、是否需流式(gRPC)、是否需调试友好(REST)、消息大小频率(高频小消息 gRPC 优势大)。理解「选择看场景:对外 API 用 REST(通用友好)、内部高频用 gRPC(高性能强契约流式);典型混用对外 REST 对内 gRPC;考量团队/流式/调试/消息频率」,就掌握了选择建议。

记忆钩子:「REST(HTTP/1.1+JSON)vs gRPC(HTTP/2+Protobuf);gRPC 优势:①性能高(Protobuf 二进制小而快、字段用编号 vs JSON 文本冗余;HTTP/2 多路复用一连接并发多请求 vs HTTP/1.1 队头阻塞)②强契约(.proto 定义接口生成各语言代码、强类型编译期检查、跨语言,vs REST 弱契约靠文档运行时才出错)③支持流式(一元/服务端流/客户端流/双向流,REST 做不到);REST 优势:通用简单(任何客户端能调)、人类可读(调试方便)、生态成熟(缓存/网关/Swagger)、浏览器友好;★选择看场景不是二选一:对外 API(前端/第三方)用 REST、微服务内部高频用 gRPC,典型混用对外 REST 对内 gRPC」

七、常见误区与追问

  • 误区:gRPC 一定比 REST 好、要全用 gRPC。 各有适用场景——gRPC 性能高、强契约、支持流式,适合微服务内部高频调用;REST 通用、浏览器能调、调试方便、生态成熟,适合对外 API;很多架构「对外 REST + 对内 gRPC」混用,不是二选一。
  • 误区:gRPC 就是「用 HTTP 传 Protobuf」。 gRPC 是基于 HTTP/2(不是 HTTP/1.1)+ Protobuf + .proto 契约的完整 RPC 框架——HTTP/2 提供多路复用和流式、Protobuf 提供高效二进制序列化、.proto 生成各语言代码提供强契约;三者结合才是 gRPC,不只是数据格式的差异。
  • 误区:REST 只能用 JSON。 REST 是一种架构风格(资源导向 + HTTP 语义),数据格式通常是 JSON 但也可以是 XML 等;只是实践中 REST + JSON 是最常见组合;gRPC 则固定用 Protobuf。
  • 误区:浏览器可以直接调 gRPC。 浏览器不能直接调原生 gRPC(基于 HTTP/2 的二进制帧、浏览器 API 不支持)——需要 grpc-web(一个代理层,把浏览器的请求转成 gRPC);这也是对外 API 更适合用 REST 的原因之一(浏览器能直接调 REST)。
  • 追问:gRPC 为什么比 REST 性能好? 两方面:① 数据格式——Protobuf 是二进制、体积小(字段用编号不传字段名、可能只有 JSON 的 1/3~1/10)、序列化/反序列化快;而 JSON 是文本、字段名重复冗余、解析慢;② 传输协议——gRPC 用 HTTP/2(多路复用,一个连接并发多个请求、不队头阻塞、头部压缩),REST 通常用 HTTP/1.1(一个连接同时一个请求);综合起来 gRPC 吞吐更高、延迟更低。
  • 追问:gRPC 的强契约相比 REST 有什么好处? gRPC 用 .proto 文件定义接口和消息结构(强类型),编译生成客户端/服务端各语言的代码——客户端和服务端用同一份契约、接口天然一致、字段类型编译期检查(不像 REST 的 JSON 字段拼错、类型不对要运行时才发现)、跨语言无缝对接(Java 服务端 + Go 客户端用同一 proto);REST 的接口靠文档/OpenAPI 约定,没有强制,服务端改了字段客户端不知道就会出错。
  • 追问:什么场景该用 REST,什么场景该用 gRPC? 对外开放的 API(给浏览器前端、第三方开发者)用 REST——通用、浏览器能直接调、调试方便、生态成熟;微服务内部之间的高频/性能敏感调用用 gRPC——性能高、强契约、支持流式、内部可控;需要流式(实时推送、双向通信)用 gRPC;需要人类可读、方便调试、利用 HTTP 缓存用 REST;很多架构对外 REST、对内 gRPC 混用。

八、加强记忆

REST 和 gRPC 是微服务通信的两种主流方式:REST 基于 HTTP/1.1 + JSON(文本),gRPC 基于 HTTP/2 + Protobuf(二进制)+ .proto 契约gRPC 的优势① 性能高——Protobuf 二进制、体积小(字段用编号、可能只有 JSON 的 1/3~1/10)、解析快,HTTP/2 多路复用(一个连接并发多请求、不队头阻塞)+ 头部压缩;② 强契约——.proto 定义接口和消息、编译生成各语言代码(客户端服务端契约一致、强类型编译期检查、跨语言无缝,对比 REST 弱契约靠文档、改字段运行时才出错);③ 支持流式——四种模式(一元/服务端流/客户端流/双向流,REST 请求-响应做不到)。REST 的优势通用简单(任何 HTTP 客户端能调、不用生成代码)、人类可读(JSON 文本、Postman/curl 调试方便)、生态成熟(HTTP 缓存/网关/Swagger)、浏览器友好(gRPC 浏览器不能直接调要 grpc-web)。怎么选(看场景,不是二选一)对外 API(前端/第三方)用 REST(通用友好),微服务内部高频/性能敏感调用用 gRPC(高性能强契约流式),典型架构「对外 REST + 对内 gRPC」混用。一句话「REST(HTTP+JSON,通用/人类可读/生态成熟/浏览器友好)vs gRPC(HTTP/2+Protobuf,性能高/强契约 proto 生成代码/支持流式);gRPC 快因 Protobuf 二进制小+HTTP/2 多路复用;选择看场景:对外 API 用 REST、内部高频用 gRPC,混用是常态」。