1. gRPC 概述
gRPC 是 Google 开源的高性能远程过程调用(RPC)框架,基于 HTTP/2 协议和 Protocol Buffers(protobuf)序列化协议。它允许客户端应用像调用本地函数一样直接调用另一台机器上的服务端方法,屏蔽了网络通信、序列化、反序列化等底层细节。在微服务架构、跨语言服务通信和移动端-后端交互场景中,gRPC 已成为事实标准之一。
1.1 gRPC 与 REST 对比
REST 是资源导向的架构风格,而 gRPC 是动作导向的 RPC 框架。两者在协议、数据格式、性能、代码生成等方面存在显著差异。下表从关键维度进行对比:
| 对比维度 | gRPC | REST |
|---|---|---|
| 底层协议 | HTTP/2(多路复用、双向流、头部压缩) | HTTP/1.1(通常,也可用 HTTP/2) |
| 数据格式 | Protocol Buffers(二进制,紧凑高效) | JSON / XML(文本,可读性强但体积大) |
| 接口定义 | proto 文件(强类型,契约驱动) | OpenAPI / Swagger(文档驱动) |
| 代码生成 | 内置 protoc 编译器,自动生成客户端/服务端桩代码 | 需借助第三方工具(如 swagger-codegen) |
| 流式通信 | 原生支持:一元、服务端流、客户端流、双向流 | 需额外实现 WebSocket 或 SSE |
| 浏览器支持 | 需 gRPC-Web 代理,非原生 | 原生支持,浏览器可直接发起 fetch |
| 适用场景 | 微服务内部通信、低延迟高吞吐、实时流处理 | 面向外部的 Web API、资源管理、缓存友好 |
选型建议: 内部服务间通信优先选择 gRPC,利用其高性能和强契约特性;对外暴露的 API 或需要浏览器直接调用的场景,REST 仍是更通用的选择。
1.2 gRPC 核心概念
理解 gRPC 需要掌握三个核心抽象:Service、RPC 和 Message。它们共同构成了 gRPC 的契约体系。
- Service(服务):一组 RPC 方法的逻辑集合,在
.proto文件中通过service关键字定义。每个服务对应一个网络端点。 - RPC(远程过程调用):服务中的具体方法,定义了请求和响应的消息类型以及通信模式(一元、流式等)。
- Message(消息):结构化数据载体,使用 protobuf 定义字段类型和编号,是 RPC 方法的输入和输出。
以下是一个典型的 proto 契约示例:
syntax = "proto3";
package auth;
// 定义用户认证服务
service AuthService {
// 一元 RPC:登录
rpc Login (LoginRequest) returns (LoginResponse);
// 服务端流 RPC:获取用户操作日志
rpc GetAuditLogs (AuditLogRequest) returns (stream AuditLogEntry);
}
// 登录请求消息
message LoginRequest {
string username = 1;
string password = 2;
}
// 登录响应消息
message LoginResponse {
string token = 1;
int64 expires_at = 2;
}
// 审计日志条目消息
message AuditLogEntry {
string action = 1;
string timestamp = 2;
string detail = 3;
}
契约即文档: proto 文件是 gRPC 的唯一真相来源(Single Source of Truth)。服务端和客户端基于同一份 proto 生成代码,确保双方接口完全一致,避免因文档不同步导致的集成问题。
1.3 gRPC 应用场景
gRPC 在以下场景中展现出明显优势:
- 微服务间通信:低延迟、高吞吐,支持多种流式模式,适合服务网格(Service Mesh)架构。
- 多语言异构系统:protobuf 支持 C++、Go、Java、Python、Node.js 等十余种语言,跨语言调用无需额外适配。
- 实时数据流处理:如物联网设备数据上报、金融行情推送、日志实时采集等。
- 移动端-后端通信:二进制协议体积小,节省带宽和电量,配合 HTTP/2 多路复用减少连接数。
- 权限验证与审计:通过拦截器(Interceptor)在 RPC 调用链中注入认证、授权、日志等横切关注点,这正是本课程的核心主题。
下图展示了 gRPC 在微服务架构中的典型位置与通信模式:
注意: 虽然 gRPC 性能优异,但并非银弹。在浏览器直连、弱网络环境、需要人类可读调试的场景下,REST 或 GraphQL 可能更合适。选择技术栈时应结合团队能力和运维成本综合评估。