gRPC 与 RPC
问题
什么是 RPC?gRPC 有什么优势?在什么场景下使用?
答案
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 特性