2. gRPC 协议基础:Protocol Buffers 定义与四种通信模式
gRPC 是 Google 开源的高性能远程过程调用(RPC)框架,默认使用 Protocol Buffers(protobuf)作为接口定义语言(IDL)与序列化协议。在分布式事务压测场景中,理解 gRPC 的协议基础是构造精准、可复现的压测脚本的前提。本节将系统梳理 protobuf 定义语法与 gRPC 的四种通信模式,为后续压测场景库的构建奠定理论基础。
2.1 Protocol Buffers 定义
Protocol Buffers 是一种语言中立、平台中立的序列化结构化数据机制,通过 .proto 文件定义服务接口与消息结构。压测脚本中,所有请求/响应数据均需按 protobuf schema 进行编解码。
2.1.1 消息结构定义
一个典型的 .proto 文件包含消息类型(message)与字段定义。字段由类型、名称、编号组成,编号用于二进制编码标识,一旦发布不可修改。
syntax = "proto3";
package transaction.pressure;
// 订单请求消息
message OrderRequest {
string order_id = 1;
int64 user_id = 2;
double amount = 3;
repeated string product_ids = 4;
map<string, string> metadata = 5;
}
// 订单响应消息
message OrderResponse {
string order_id = 1;
bool success = 2;
int32 status_code = 3;
string error_message = 4;
}
压测要点:字段编号 1-15 占用 1 字节编码,16-2047 占用 2 字节。高频字段应分配小编号以降低序列化开销,提升压测吞吐。
2.1.2 服务接口定义
服务(service)定义声明 RPC 方法签名,包括方法名、输入消息类型、输出消息类型。压测场景中,每个 RPC 方法对应一个压测目标。
service OrderService {
// 创建订单(Unary)
rpc CreateOrder(OrderRequest) returns (OrderResponse);
// 批量查询订单状态(Server Streaming)
rpc BatchQueryStatus(OrderStatusRequest) returns (stream OrderStatusResponse);
// 批量上传订单(Client Streaming)
rpc BatchCreateOrder(stream OrderRequest) returns (BatchSummaryResponse);
// 实时订单对账(Bidirectional Streaming)
rpc ReconcileOrders(stream ReconcileRequest) returns (stream ReconcileResponse);
}
2.1.3 标量类型与特殊类型
| Protobuf 类型 | C# 映射 | Java 映射 | Go 映射 | 压测注意事项 |
|---|---|---|---|---|
| double | double | double | float64 | 金额字段建议使用 int64(分/厘)避免浮点精度 |
| int32 / int64 | int / long | int / long | int32 / int64 | 负数场景建议使用 sint32/sint64 节省编码 |
| string | string | String | string | 压测时控制长度,避免超大 payload 影响延迟 |
| bytes | ByteString | ByteString | []byte | 二进制数据,压测中常用于传递序列化对象 |
| repeated | RepeatedField | List | slice | 压测时需关注列表长度对序列化性能的影响 |
| map | MapField | Map | map | 键值对数量影响编码效率,压测场景建议限制 |
2.2 gRPC 四种通信模式
gRPC 基于 HTTP/2 流式传输,支持四种通信模式。压测场景库需要针对每种模式设计不同的并发模型与数据流策略。
2.2.1 Unary RPC(一元模式)
客户端发送单个请求,服务端返回单个响应。这是最基础的 RPC 模式,行为与传统的 HTTP REST 类似,但基于 HTTP/2 和 protobuf 获得更低的延迟与更高的吞吐。
- 压测特征:短连接场景下,每个请求独立建立 HTTP/2 流,并发数直接决定吞吐上限。
- 典型场景:创建订单、查询余额、提交支付。
- 压测关注点:请求/响应大小、序列化耗时、连接池复用效率。
2.2.2 Server Streaming RPC(服务端流模式)
客户端发送单个请求,服务端以流式方式返回多个响应。服务端可以持续推送数据,直到流结束。
- 压测特征:客户端需持续读取流数据,接收速率可能成为瓶颈。
- 典型场景:批量查询订单状态、日志推送、实时监控数据拉取。
- 压测关注点:流式接收缓冲区大小、消息到达间隔、流超时控制。
2.2.3 Client Streaming RPC(客户端流模式)
客户端以流式方式发送多个请求,服务端在接收完所有请求后返回单个响应。
- 压测特征:客户端需控制发送速率与批次大小,避免服务端内存溢出。
- 典型场景:批量上传订单、批量写入日志、文件分片上传。
- 压测关注点:发送间隔、流关闭时机、服务端聚合处理能力。
2.2.4 Bidirectional Streaming RPC(双向流模式)
客户端和服务端可以独立发送多个消息,形成全双工通信。双方可以按任意顺序读写,流独立控制。
- 压测特征:并发读写,需要精细控制读写协程/线程的调度。
- 典型场景:实时对账、聊天系统、协同编辑、分布式事务协调。
- 压测关注点:读写并发模型、消息顺序保证、背压(backpressure)处理。
2.3 四种模式压测对比矩阵
| 通信模式 | 请求数量 | 响应数量 | 连接复用 | 压测并发模型 | 典型压测指标 |
|---|---|---|---|---|---|
| Unary | 1 | 1 | 高(多流复用) | 请求-响应线程池 | QPS、P99 延迟 |
| Server Streaming | 1 | N | 中(长流占用) | 异步接收 + 流计数器 | 消息吞吐、流持续时间 |
| Client Streaming | N | 1 | 中(发送端控制) | 定时发送 + 流关闭 | 发送速率、聚合延迟 |
| Bidirectional | N | M | 低(全双工) | 独立读写协程 | 双向吞吐、消息乱序率 |
压测陷阱提示:在双向流压测中,如果客户端和服务端都使用同步阻塞读写,极易导致死锁。压测脚本必须使用异步读写或独立协程/线程分别处理发送与接收。
2.4 压测场景库中的协议适配策略
在分布式事务压测场景库中,每种通信模式需要适配不同的压测执行器。以下策略可作为场景库设计的参考:
- Unary 场景:使用连接池 + 请求-响应模型,每个虚拟用户独立发送请求,统计 QPS 与延迟分布。
- Server Streaming 场景:使用异步接收器,每个流启动一个接收协程,记录消息到达时间戳与间隔。
- Client Streaming 场景:使用定时发送器,按固定间隔或事件驱动发送请求,控制流关闭时机。
- Bidirectional 场景:使用双协程模型,发送协程与接收协程独立运行,通过 channel/queue 传递消息。