gRPC vs RPC 高频面试题
一、gRPC 最常见面试题
-
gRPC 是什么?它和传统 REST 有什么区别?
- 考察你是否理解 gRPC 的定义、通信协议(HTTP/2)、序列化方式(Protocol Buffers)以及与 REST 的性能、数据格式差异。
一、gRPC 是什么?
- 定义:gRPC 是 Google 开源的 高性能、跨语言的 RPC 框架,基于 HTTP/2 协议,使用 Protocol Buffers(Protobuf) 作为接口定义语言(IDL)和序列化协议。
- 核心目标:让不同语言的服务之间可以像调用本地方法一样进行远程调用,同时保证高性能和可扩展性。
- 跨语言支持:Java、Go、Python、C++、Node.js、C# 等。
二、gRPC 核心原理
-
接口定义
- 使用
.proto文件定义服务和消息结构。 - 通过
protoc编译器生成各语言的客户端和服务端代码。
- 使用
-
通信协议
- 基于 HTTP/2,支持多路复用、流式传输、头部压缩、双向通信。
-
序列化方式
- 使用 Protobuf,二进制格式,体积小、解析快。
-
调用流程
- 客户端调用 → 序列化请求 → HTTP/2 传输 → 服务端反序列化 → 执行方法 → 序列化响应 → 返回客户端。
三、gRPC 与传统 REST 的区别
| 对比维度 | gRPC | REST |
|---|---|---|
| 协议 | HTTP/2 | HTTP/1.1 |
| 数据格式 | Protobuf(二进制) | JSON(文本) |
| 性能 | 高性能,低延迟 | 相对较慢 |
| 通信模式 | 支持四种模式(Unary、Server streaming、Client streaming、Bidirectional streaming) | 单请求-单响应 |
| 类型安全 | 强类型(IDL 定义) | 弱类型(JSON) |
| 跨语言支持 | 自动生成多语言代码 | 需手动编写客户端 |
| 可读性 | 二进制不可读 | JSON 可读 |
| 适用场景 | 微服务内部高性能通信 | 对外 API、浏览器调用 |
四、使用场景分析
- 适合 gRPC 的场景:
- 微服务之间的高性能通信
- 多语言服务交互
- 需要流式数据传输(如实时聊天、视频流)
- 适合 REST 的场景:
- 对外开放 API
- 浏览器直接调用
- 需要人类可读的调试数据
五、面试高分答法
gRPC 是 Google 开源的高性能、跨语言 RPC 框架,基于 HTTP/2 协议,使用 Protobuf 进行序列化。它通过
.proto文件定义接口,自动生成多语言客户端和服务端代码,支持四种通信模式,包括双向流式通信。
与传统 REST 相比,gRPC 在性能、类型安全、跨语言支持和通信模式上更优,但可读性较差,适合微服务内部高性能通信;REST 则更适合对外 API 和浏览器调用。
六、示例:
需求场景
我们有一个 用户服务,需要提供一个接口:
根据用户 ID 获取用户信息(包含姓名、邮箱、年龄)。
1. REST 示例
接口定义(HTTP/1.1 + JSON):
GET /user/123
返回数据(JSON,可读性强):
{"id": 123,"name": "Alice","email": "alice@example.com","age": 25
}
调用方式:
- 浏览器直接访问
http://api.example.com/user/123 - 或者用
curl:
curl http://api.example.com/user/123
特点:
- 可读性强(JSON)
- 跨平台方便(浏览器、Postman 都能直接调)
- 性能一般(文本格式,体积大)
2. gRPC 示例
接口定义(.proto 文件):
syntax = "proto3";service UserService {rpc GetUser (UserRequest) returns (UserResponse);
}message UserRequest {int32 id = 1;
}message UserResponse {int32 id = 1;string name = 2;string email = 3;int32 age = 4;
}
调用方式:
- 客户端调用生成的
UserServiceStub:
UserRequest request = UserRequest.newBuilder().setId(123).build();
UserResponse response = userServiceStub.getUser(request);
System.out.println(response.getName());
返回数据(Protobuf 二进制,不可直接读):
- 在网络上传输的是压缩后的二进制数据,比 JSON 小很多。
特点:
- 性能高(二进制序列化,体积小)
- 强类型(编译时生成代码)
- 不适合直接用浏览器调试(需要客户端 Stub)
直观对比
| 维度 | REST | gRPC |
|---|---|---|
| 协议 | HTTP/1.1 | HTTP/2 |
| 数据格式 | JSON(可读) | Protobuf(二进制) |
| 调用方式 | URL + HTTP 方法 | 生成的客户端 Stub 调用 |
| 性能 | 较慢 | 高性能 |
| 调试 | 浏览器/工具直接调 | 需专用客户端 |
| 适用场景 | 对外 API | 微服务内部通信 |
💡 面试技巧:
当面试官问“gRPC 和 REST 有什么区别”时,你可以先用一句话总结理论,然后用这个用户服务的例子快速对比,这样既有深度又有落地感。
-
gRPC 的四种通信模式是什么?
- Unary(单次请求响应)
- Server streaming(服务端流式响应)
- Client streaming(客户端流式请求)
- Bidirectional streaming(双向流式通信)
一、gRPC 的四种通信模式
gRPC 基于 HTTP/2,支持四种通信模式:
- Unary RPC(单次请求-单次响应)
- Server Streaming RPC(服务端流式响应)
- Client Streaming RPC(客户端流式请求)
- Bidirectional Streaming RPC(双向流式通信)
二、详细讲解 + 示例
1. Unary RPC(单次请求-单次响应)
定义:客户端发送一次请求,服务端返回一次响应,类似传统 REST 调用。
示例 .proto:
service UserService {rpc GetUser (UserRequest) returns (UserResponse);
}
调用流程:
- 客户端构造
UserRequest(包含用户 ID)。 - 发送到服务端。
- 服务端处理请求,返回
UserResponse。 - 连接关闭。
特点:
- 最简单的模式
- 类似 HTTP GET/POST
- 适合一次性数据查询
2. Server Streaming RPC(服务端流式响应)
定义:客户端发送一次请求,服务端返回一个数据流,可以持续推送多条消息。
示例 .proto:
service OrderService {rpc ListOrders (OrderRequest) returns (stream OrderResponse);
}
调用流程:
- 客户端发送
OrderRequest(如用户 ID)。 - 服务端开始不断推送
OrderResponse(每条订单一条消息)。 - 客户端逐条接收,直到服务端结束流。
- 连接关闭。
特点:
- 适合批量数据返回(如订单列表、日志流)
- 客户端可以边接收边处理
- 减少多次请求的开销
3. Client Streaming RPC(客户端流式请求)
定义:客户端发送一个数据流给服务端,服务端在接收完所有数据后返回一次响应。
示例 .proto:
service UploadService {rpc UploadFile (stream FileChunk) returns (UploadStatus);
}
调用流程:
- 客户端不断发送
FileChunk(文件分片)。 - 服务端接收并处理每个分片。
- 当客户端发送完成,服务端返回
UploadStatus(如成功/失败)。 - 连接关闭。
特点:
- 适合大文件上传、批量数据提交
- 服务端在接收完全部数据后才返回结果
4. Bidirectional Streaming RPC(双向流式通信)
定义:客户端和服务端都可以同时发送数据流,互相独立,不必等待对方完成。
示例 .proto:
service ChatService {rpc Chat (stream ChatMessage) returns (stream ChatMessage);
}
调用流程:
- 客户端和服务端建立连接。
- 客户端发送
ChatMessage,服务端立即返回ChatMessage。 - 双方可以同时发送和接收消息。
- 连接在双方都结束流时关闭。
特点:
- 适合实时聊天、视频通话、实时数据推送
- 双方可以并行通信
- 需要处理并发和流控制
三、四种模式流程对比
| 模式 | 请求次数 | 响应次数 | 适用场景 |
|---|---|---|---|
| Unary | 1 | 1 | 查询单条数据 |
| Server Streaming | 1 | 多 | 批量数据返回 |
| Client Streaming | 多 | 1 | 大文件上传 |
| Bidirectional Streaming | 多 | 多 | 实时通信 |
四、面试高分答法
gRPC 基于 HTTP/2,支持四种通信模式:Unary(一次请求一次响应)、Server Streaming(一次请求多次响应)、Client Streaming(多次请求一次响应)、Bidirectional Streaming(多次请求多次响应)。
例如,查询用户信息用 Unary;获取订单列表用 Server Streaming;上传大文件用 Client Streaming;实时聊天用 Bidirectional Streaming。
这些模式让 gRPC 在微服务内部通信、实时数据传输等场景比 REST 更灵活高效。
-
gRPC 为什么使用 HTTP/2?有什么优势?
- 多路复用、头部压缩、双向流、低延迟等。
一、背景
- gRPC 是 Google 开源的高性能 RPC 框架,目标是 低延迟、高吞吐、跨语言。
- 传统 REST 大多基于 HTTP/1.1,但 HTTP/1.1 在性能和功能上有一些限制:
- 队头阻塞(同一连接一次只能处理一个请求)
- 连接复用效率低
- 头部冗余大(每次请求都要重复发送大量 HTTP 头)
- 不支持原生双向流
二、gRPC 为什么选择 HTTP/2
gRPC 需要:
- 多路复用(同时处理多个请求)
- 低延迟(减少等待时间)
- 双向流式通信(实时数据传输)
- 高效压缩(减少带宽占用)
- 更好的连接管理(长连接)
HTTP/2 正好满足这些需求。
三、HTTP/2 的优势
1. 多路复用(Multiplexing)
- 在一个 TCP 连接上同时发送多个请求和响应,互不阻塞。
- 解决了 HTTP/1.1 的队头阻塞问题。
- gRPC 利用场景:多个 RPC 方法可以并行执行,不需要为每个请求建立新连接。
2. 头部压缩(Header Compression)
- 使用 HPACK 压缩 HTTP 头部,减少冗余数据。
- gRPC 利用场景:Protobuf 本身数据很小,头部压缩进一步降低带宽占用。
3. 双向流(Bidirectional Streaming)
- 客户端和服务端可以在同一连接上同时发送数据。
- gRPC 利用场景:实现四种通信模式中的流式模式(Server Streaming、Client Streaming、Bidirectional Streaming)。
4. 长连接(Persistent Connection)
- 一个连接可以长期保持,减少频繁建立连接的开销。
- gRPC 利用场景:微服务之间的持续通信。
5. 更好的优先级控制
- HTTP/2 可以为不同的流设置优先级,优化资源分配。
- gRPC 利用场景:在高并发场景下优先处理关键请求。
四、面试高分答法
gRPC 选择 HTTP/2 是因为它提供了多路复用、头部压缩、双向流、长连接等特性,这些特性可以显著提升 RPC 调用的性能和灵活性。
例如,HTTP/2 的多路复用让多个 RPC 方法可以在同一连接上并行执行,双向流支持实时通信,头部压缩减少带宽占用,这些都是 HTTP/1.1 无法高效实现的。
-
gRPC 的序列化协议是什么?为什么选择它?
- Protocol Buffers(Protobuf),高效、跨语言、结构化。
一、gRPC 的序列化协议是什么?
- gRPC 默认使用 Protocol Buffers(简称 Protobuf) 作为 接口定义语言(IDL) 和 序列化协议。
- 作用:
- IDL:用
.proto文件定义服务接口和数据结构。 - 序列化协议:将数据结构转换为二进制格式进行传输,并在接收端反序列化为对象。
- IDL:用
二、为什么选择 Protobuf?
gRPC 的目标是 高性能、跨语言、可扩展,而 Protobuf 在这些方面表现优异:
-
高性能
- 二进制格式,体积小,解析速度快。
- 比 JSON、XML 更节省带宽和 CPU。
-
跨语言支持
- 官方支持 Java、Go、Python、C++、C#、Node.js 等多种语言。
.proto文件编译后自动生成各语言的客户端和服务端代码。
-
强类型 & 向后兼容
- 编译时生成类型安全的代码,避免运行时类型错误。
- 支持字段的新增、删除,不影响旧版本客户端(通过字段编号管理)。
-
结构清晰
.proto文件既是接口文档,也是代码生成的源文件。- 开发、维护、调试更方便。
-
与 HTTP/2 配合良好
- 二进制数据在 HTTP/2 的多路复用和头部压缩下传输效率更高。
三、Protobuf 与 JSON 对比
| 对比维度 | Protobuf | JSON |
|---|---|---|
| 格式 | 二进制 | 文本 |
| 体积 | 小 | 大 |
| 解析速度 | 快 | 慢 |
| 类型安全 | 强类型(编译生成代码) | 弱类型(运行时解析) |
| 可读性 | 不可直接读 | 可直接读 |
| 跨语言支持 | 自动生成代码 | 需手动解析 |
| 适用场景 | 微服务内部高性能通信 | 对外 API、调试友好 |
四、面试高分答法
gRPC 默认使用 Protocol Buffers 作为序列化协议,因为它是高性能、跨语言、强类型的二进制格式。
相比 JSON,Protobuf 体积更小、解析更快,并且通过.proto文件可以自动生成多语言客户端和服务端代码,保证类型安全和向后兼容,非常适合微服务内部的高性能通信。
二、RPC 最常见面试题
-
什么是 RPC?它的基本原理是什么?
- 考察你是否能解释 RPC 的概念:像调用本地方法一样调用远程服务,底层通过网络传输数据。
一、什么是 RPC?
- 定义:RPC(Remote Procedure Call,远程过程调用) 是一种像调用本地函数一样调用远程服务的技术。
- 核心目标:屏蔽网络通信的细节,让开发者像调用本地方法一样调用远程方法。
- 关键点:开发者不需要关心底层的网络协议、序列化方式、连接管理等。
二、核心思想
本地调用的体验 + 网络通信的能力
RPC 把远程调用封装成一个看起来像本地函数的接口,底层自动完成数据传输和结果返回。
三、RPC 的基本原理
RPC 的工作流程可以拆成 客户端 Stub → 网络传输 → 服务端 Stub → 执行方法 → 返回结果:
-
客户端调用 Stub 方法
- Stub 是由 RPC 框架生成的代理对象,方法签名和本地方法一样。
- 开发者调用时,就像调用本地函数。
-
序列化请求数据
- 将方法名、参数等信息序列化成二进制或其他格式(如 Protobuf、JSON)。
-
网络传输
- 通过 TCP、HTTP/2 等协议将序列化后的数据发送到远程服务端。
-
服务端反序列化
- 服务端 Stub 接收到数据后,反序列化成方法参数。
-
执行真实方法
- 服务端调用实际的业务逻辑方法,得到结果。
-
序列化响应数据
- 将结果序列化成二进制或其他格式。
-
返回给客户端
- 客户端 Stub 接收响应数据,反序列化成对象,并返回给调用方。
四、简单示例
假设我们有一个 获取用户信息 的方法:
客户端调用:
User user = userService.getUser(123);
System.out.println(user.getName());
底层实际发生的事情:
getUser(123)被 Stub 拦截。- 参数
123被序列化成二进制。 - 通过网络发送到服务端。
- 服务端反序列化成
123。 - 调用真实的
getUser方法,查询数据库。 - 将结果序列化成二进制。
- 发送回客户端并反序列化成
User对象。
五、面试高分答法
RPC(Remote Procedure Call)是一种让我们像调用本地方法一样调用远程服务的技术。它的原理是通过客户端 Stub 将方法调用序列化成数据,通过网络传输到服务端,服务端 Stub 反序列化后调用真实方法,并将结果序列化返回。这样开发者无需关心底层通信细节,只需像写本地代码一样调用远程方法。
-
RPC 调用的核心流程是什么?
- 客户端调用 → 序列化请求 → 网络传输 → 服务端反序列化 → 执行方法 → 序列化响应 → 返回客户端。
一、RPC 调用的核心流程
RPC 调用的核心流程可以分为 客户端发起调用 → 序列化 → 网络传输 → 服务端执行 → 返回结果 五大阶段:
1. 客户端发起调用
- 开发者调用的是 客户端 Stub(代理对象) 提供的方法,看起来就像调用本地函数。
- Stub 方法的签名与服务端方法一致,但内部会封装网络通信逻辑。
关键点:Stub 是本地调用的入口,它屏蔽了底层的网络细节。
2. 序列化请求数据
- 将方法名、参数等信息转换成可传输的格式(如 Protobuf、JSON、XML)。
- 序列化的目标是压缩数据体积和保证跨语言解析。
关键点:序列化协议决定了 RPC 的性能和跨语言能力。
3. 网络传输
- 通过 TCP、HTTP/2 等协议将序列化后的数据发送到服务端。
- 可能会经过负载均衡、服务发现等中间环节。
关键点:网络层负责数据的可靠传输,RPC 框架通常会内置连接管理和重试机制。
4. 服务端反序列化 & 执行方法
- 服务端 Stub 接收到数据后,反序列化成方法参数。
- 调用实际的业务逻辑方法(如查询数据库、计算结果)。
关键点:服务端 Stub 是远程调用的接收入口,它负责把网络数据还原成可执行的本地方法调用。
5. 序列化响应数据 & 返回
- 将方法执行结果序列化成可传输格式。
- 通过网络返回给客户端。
- 客户端 Stub 接收响应并反序列化成对象,返回给调用方。
关键点:响应过程与请求过程对称,同样依赖序列化和网络传输。
二、核心流程总结表
| 阶段 | 客户端 | 服务端 |
|---|---|---|
| 调用入口 | Stub 方法 | Stub 方法 |
| 序列化 | 请求参数 → 二进制 | 响应结果 → 二进制 |
| 网络传输 | 发送数据 | 返回数据 |
| 反序列化 | 响应结果 ← 二进制 | 请求参数 ← 二进制 |
| 执行方法 | - | 真实业务逻辑 |
三、面试高分答法
RPC 调用的核心流程是:客户端调用 Stub 方法 → 序列化请求数据 → 通过网络传输到服务端 → 服务端 Stub 反序列化并执行真实方法 → 序列化结果返回给客户端 → 客户端反序列化得到结果。
这样开发者就能像调用本地方法一样调用远程服务,而底层的序列化、网络传输、反序列化过程由 RPC 框架自动完成。
-
RPC 和 HTTP API 的区别是什么?
- 协议层、性能、数据格式、调用方式、适用场景的差异。
一、定义回顾
-
RPC(Remote Procedure Call)
像调用本地方法一样调用远程服务,底层自动完成序列化、网络传输、反序列化。
常见实现:gRPC、Dubbo、Thrift。 -
HTTP API(REST API)
基于 HTTP 协议,通过 URL + HTTP 方法(GET/POST/PUT/DELETE)访问资源,通常使用 JSON/XML 作为数据格式。
二、核心区别
| 对比维度 | RPC | HTTP API |
|---|---|---|
| 调用方式 | 像调用本地方法(函数名 + 参数) | 通过 URL 访问资源(路径 + HTTP 方法) |
| 协议层 | 可基于 TCP、HTTP/2 等 | 基于 HTTP/1.1 或 HTTP/2 |
| 数据格式 | 二进制(如 Protobuf、Thrift) | 文本(如 JSON、XML) |
| 性能 | 高性能(二进制体积小、解析快) | 相对较慢(文本解析开销大) |
| 类型安全 | 强类型(编译生成代码) | 弱类型(运行时解析) |
| 跨语言支持 | 依赖 IDL 自动生成多语言代码 | 语言无关,但需手动解析 JSON/XML |
| 可读性 | 不可直接读(需反序列化) | 可直接读(调试方便) |
| 适用场景 | 微服务内部高性能通信 | 对外开放 API、跨平台调用 |
三、场景对比
-
RPC 适合:
- 微服务内部调用(高性能、低延迟)
- 需要强类型和自动代码生成的场景
- 实时通信(双向流)
-
HTTP API 适合:
- 对外开放接口(易调试、易理解)
- 浏览器直接调用
- 第三方集成(跨语言、跨平台)
四、面试高分答法
RPC 和 HTTP API 的主要区别在于调用方式、协议层、数据格式和性能。
RPC 像调用本地方法一样调用远程服务,通常使用二进制序列化(如 Protobuf),性能高、类型安全,适合微服务内部通信;
HTTP API 基于 URL + HTTP 方法访问资源,通常使用 JSON/XML,易读易调试,适合对外开放接口。
简单来说,RPC 更偏向服务间高性能通信,HTTP API 更偏向对外资源访问。
-
常见的 RPC 框架有哪些?
- gRPC、Dubbo、Thrift、Hessian 等。
