gRPC 与 RPC
问题
什么是 RPC?gRPC 有什么优势?在什么场景下使用?
面试速答版
gRPC 比 REST 强在哪?为什么微服务都用它? 核心优势是性能 + 类型安全 + 流式:
- 二进制 Protobuf:体积比 JSON 小 3-10 倍,解析快 5-10 倍。
- HTTP/2 多路复用:一个连接跑多个请求,无队头阻塞。
- 强类型契约:
.proto文件生成各语言代码,编译期就能查出字段错误。 - 四种通信模式:一元(Unary)、服务端流、客户端流、双向流——天然支持实时推送、大数据导出。
Protobuf 比 JSON 好在哪?
- 字段编号机制:用
field_number = 1做向后兼容,加字段不影响老客户端。 - 类型严格:
int32、string、repeated、oneof等,避免 JSON 的弱类型坑。 - 二进制紧凑:不传字段名,只传字段号 + 值,节省带宽。
- 代码生成:
protoc一键生成 TypeScript/Go/Java/Python 的强类型 client/server。
什么场景适合 gRPC?前端能用吗?
- 适合:微服务内部通信、高性能场景、流式数据推送(如视频、实时日志)。
- 不适合:对外 API(浏览器原生不支持 HTTP/2 gRPC)、简单 CRUD(REST 更方便)、需要 HTTP 缓存。
- 浏览器调用:必须用
gRPC-Web,需要Envoy代理把 HTTP/1.1 翻译成 HTTP/2 gRPC,或者后端再开个 REST/GraphQL 网关。 Connect-RPC是更新方案,浏览器/Node.js 原生友好。
答案
RPC vs REST
| 维度 | REST | gRPC |
|---|---|---|
| 协议 | HTTP/1.1(通常) | HTTP/2 |
| 数据格式 | JSON(文本) | Protocol Buffers(二进制) |
| 性能 | 一般 | 高(体积小、解析快) |
| 类型安全 | 弱(依赖文档) | 强(.proto 文件生成代码) |
| 流式传输 | 不支持 | 支持(单向流、双向流) |
| 浏览器支持 | ✅ | 有限(需要 gRPC-Web) |
| 适用场景 | 对外 API | 内部服务间通信 |
Protocol Buffers
user.proto
syntax = "proto3";
package user;
service UserService {
rpc GetUser (GetUserRequest) returns (UserResponse);
rpc ListUsers (ListUsersRequest) returns (stream UserResponse); // 服务端流
rpc CreateUser (CreateUserRequest) returns (UserResponse);
}
message GetUserRequest {
string id = 1;
}
message CreateUserRequest {
string name = 1;
string email = 2;
}
message UserResponse {
string id = 1;
string name = 2;
string email = 3;
int64 created_at = 4;
}
message ListUsersRequest {
int32 page = 1;
int32 page_size = 2;
}
Node.js gRPC 实现
grpc-server.ts
import * as grpc from '@grpc/grpc-js';
import * as protoLoader from '@grpc/proto-loader';
const packageDefinition = protoLoader.loadSync('user.proto');
const proto = grpc.loadPackageDefinition(packageDefinition) as any;
// 实现服务
const server = new grpc.Server();
server.addService(proto.user.UserService.service, {
getUser: async (call: any, callback: any) => {
const user = await db.user.findById(call.request.id);
callback(null, user);
},
listUsers: async (call: any) => {
const users = await db.user.findMany();
for (const user of users) {
call.write(user); // 流式返回
}
call.end();
},
createUser: async (call: any, callback: any) => {
const user = await db.user.create(call.request);
callback(null, user);
},
});
server.bindAsync('0.0.0.0:50051', grpc.ServerCredentials.createInsecure(), () => {
console.log('gRPC server running on port 50051');
});
四种通信模式
常见面试问题
Q1: 什么时候用 gRPC?
答案:
- 微服务内部通信:性能好、类型安全
- 高性能场景:二进制序列化比 JSON 快 3-10 倍
- 需要流式传输:实时数据推送
不适合:对外 API(浏览器支持差)、简单 CRUD(REST 更方便)。
Q2: Protocol Buffers 比 JSON 好在哪?
答案:
- 体积小:二进制编码,比 JSON 小 3-10 倍
- 解析快:不需要文本解析
- 类型安全:.proto 生成类型代码
- 向后兼容:字段编号机制支持 Schema 演进
Q3: 前端能直接调用 gRPC 吗?
答案:
浏览器不直接支持 HTTP/2 的 gRPC。需要 gRPC-Web(需要 Envoy 代理转换),或者后端提供 REST/GraphQL 网关。
相关链接
- 微服务基础 - 服务间通信
- HTTP/2 与 HTTP/3 - HTTP/2 特性