一、前言:为什么需要 gRPC?
在微服务架构盛行的今天,系统间通信的效率与规范成为关键。
传统的 RESTful API 虽然简单直观,但在高并发、低延迟、强类型接口的场景下往往力不从心。
这时,gRPC(Google Remote Procedure Call) 成为更现代化的选择。它由 Google 开发,基于 HTTP/2 和 Protocol Buffers,实现了 高性能、跨语言、类型安全 的远程过程调用(RPC)框架。
💡 一句话概括:
gRPC 是一个让不同语言的服务之间,像本地函数调用一样进行通信的高性能协议。
二、gRPC 核心概念
1. RPC(远程过程调用)
RPC 的思想是让分布式系统中的某个服务,能够像本地函数一样被调用。
开发者无需关心底层网络通信,只需定义接口、序列化参数、执行调用。
sequenceDiagram
Client ->> Server: 调用 sayHello("Tom")
Server -->> Client: 返回 "Hello Tom"
2. Protocol Buffers(protobuf)
gRPC 使用 protobuf 作为接口描述语言(IDL)与序列化机制。
你只需定义 .proto 文件,gRPC 自动为多语言生成客户端与服务端代码。
示例:
syntax = "proto3";
service Greeter {
rpc SayHello (HelloRequest) returns (HelloReply);
}
message HelloRequest {
string name = 1;
}
message HelloReply {
string message = 1;
}
通过命令生成对应代码(例如 Node.js):
protoc --js_out=import_style=commonjs,binary:. \
--grpc_out=grpc_js:. \
helloworld.proto
三、gRPC 的通信模型
gRPC 基于 HTTP/2 协议,天然支持多路复用、头部压缩与双向流。
| 通信模式 | 描述 | 示例场景 |
|---|---|---|
| Unary RPC | 一次请求对应一次响应 | 普通接口调用 |
| Server Streaming | 客户端请求一次,服务端持续返回流式数据 | 实时日志流 |
| Client Streaming | 客户端持续上传数据,服务端最后响应一次 | 文件上传 |
| Bidirectional Streaming | 双向实时流通信 | 聊天系统、视频通话 |
示例:双向流(Node.js)
const call = client.chat();
call.on('data', msg => console.log('Server:', msg.text));
call.write({ text: 'Hi from client!' });
四、gRPC 与 REST 的对比
| 对比项 | REST | gRPC |
|---|---|---|
| 协议 | HTTP/1.1 | HTTP/2 |
| 数据格式 | JSON(文本) | Protobuf(二进制) |
| 性能 | 较低 | 高 |
| 类型检查 | 弱(依赖文档) | 强(自动生成代码) |
| 流式通信 | 不支持 | ✅ 支持双向流 |
| 生态兼容 | 浏览器友好 | 需 gRPC-Web 代理支持 |
| 适合场景 | Web API、轻量接口 | 微服务、内部通信、高频调用 |
五、gRPC 实战:Node.js 服务示例
1. 安装依赖
npm install @grpc/grpc-js @grpc/proto-loader
2. 服务端实现
// server.js
import grpc from '@grpc/grpc-js';
import protoLoader from '@grpc/proto-loader';
const packageDef = protoLoader.loadSync('helloworld.proto');
const proto = grpc.loadPackageDefinition(packageDef).Greeter;
const server = new grpc.Server();
server.addService(proto.service, {
SayHello: (call, callback) => {
callback(null, { message: `Hello ${call.request.name}` });
}
});
server.bindAsync('0.0.0.0:50051', grpc.ServerCredentials.createInsecure(), () => {
server.start();
console.log('gRPC server running on port 50051');
});
3. 客户端调用
// client.js
import grpc from '@grpc/grpc-js';
import protoLoader from '@grpc/proto-loader';
const packageDef = protoLoader.loadSync('helloworld.proto');
const proto = grpc.loadPackageDefinition(packageDef).Greeter;
const client = new proto('localhost:50051', grpc.credentials.createInsecure());
client.SayHello({ name: 'Alice' }, (err, res) => {
console.log(res.message);
});
输出:
Hello Alice
六、浏览器端:gRPC-Web 支持
gRPC 并非直接兼容浏览器,因为浏览器环境无法原生访问 HTTP/2 + Binary。
解决方案是 gRPC-Web + Envoy 代理:
Browser <==HTTP1==> Envoy <==HTTP2==> gRPC Server
安装 gRPC-Web 客户端:
npm install grpc-web
Envoy 代理配置示例:
listeners:
- name: listener_0
address:
socket_address: { address: 0.0.0.0, port_value: 8080 }
filter_chains:
- filters:
- name: envoy.filters.network.http_connection_manager
typed_config:
"@type": type.googleapis.com/envoy.extensions.filters.network.http_connection_manager.v3.HttpConnectionManager
codec_type: AUTO
route_config:
name: local_route
virtual_hosts:
- name: backend
domains: ["*"]
routes:
- match: { prefix: "/" }
route: { cluster: grpc_server }
http_filters:
- name: envoy.filters.http.router
clusters:
- name: grpc_server
connect_timeout: 0.25s
type: LOGICAL_DNS
lb_policy: ROUND_ROBIN
load_assignment:
cluster_name: grpc_server
endpoints:
- lb_endpoints:
- endpoint:
address:
socket_address: { address: localhost, port_value: 50051 }
七、性能与最佳实践
✅ 性能优化建议
- 使用 protobuf 流式传输大数据,避免 JSON 序列化成本。
- 连接池复用:避免频繁建立 gRPC channel。
- 启用压缩(gzip):减少网络带宽消耗。
- 合理设计 proto 文件结构:拆分模块,保持接口稳定。
- 监控与 tracing:结合 OpenTelemetry 监控请求延迟与错误。
⚠️ 常见问题
- 端口冲突:默认
50051,可修改。 - 跨语言兼容:确保使用相同版本的
.proto定义。 - 浏览器调用:需 gRPC-Web 或 REST 兼容层。
八、生态与工具链
| 工具 | 功能 |
|---|---|
protoc | 官方 protobuf 编译器 |
grpcurl | 命令行 gRPC 调试工具(类似 curl) |
buf.build | proto 版本管理与 CI/CD 集成 |
grpc-web | 浏览器端调用支持 |
grpc-gateway | 将 gRPC 自动转 REST API |
九、总结
gRPC 代表了服务通信的新范式:
- 高性能(HTTP/2 + 二进制序列化)
- 跨语言(多语言 SDK)
- 强类型(IDL 自动生成)
- 支持流式与实时通信
在微服务、IoT、AI 推理、音视频流等高性能场景中,gRPC 正逐渐成为事实标准。
✅ 一句话总结:
“REST 让系统之间能对话,而 gRPC 让它们像同一进程一样协作。”
文章评论