两者都是 compute → pageserver 的读路径,但实现方式不同:
对比
| 维度 | PageStream(libpq) | gRPC |
|---|---|---|
| 协议 | PostgreSQL 自定义协议(COPY 流) | gRPC/Protobuf |
| 连接 | TCP + libpq | HTTP/2 |
| 状态 | 长连接,整个查询生命周期复用 | 双向流,也是长连接 |
| 请求方式 | 每个 request 发一个命令字符串 | Protobuf 消息 |
| 版本 | 传统协议,v2/v3 | 新协议,实验性(EXPERIMENTAL) |
| 适用场景 | 当前生产默认 | 未来替代,已在开发中 |
PageStream 协议
compute 连接后发送:
pagestream_v3 <tenant_id> <timeline_id>
然后双方进入 COPY 模式,后续每个请求是二进制格式:
<tag: u8><reqid: i64><lsn: i64><not_modified_since: i64><payload...>
响应也是类似格式,通过 PQgetCopyData 读取。
核心 RPC:
- T_NeonGetPageRequest → 读页面
- T_NeonExistsRequest → 查关系是否存在
- T_NeonNblocksRequest → 查关系大小
- T_NeonDbSizeRequest → 查库大小
- T_NeonGetSlruSegmentRequest → 读 SLRU
gRPC 协议
proto 文件定义了 6 个 RPC:
rpc GetPages (stream GetPageRequest) returns (stream GetPageResponse); // 核心读路径
rpc GetRelSize (GetRelSizeRequest) returns (GetRelSizeResponse); // 查关系大小
rpc GetDbSize (GetDbSizeRequest) returns (GetDbSizeResponse); // 查库大小
rpc GetSlruSegment (GetSlruSegmentRequest) returns (GetSlruSegmentResponse); // 读 SLRU
rpc GetBaseBackup (GetBaseBackupRequest) returns (stream GetBaseBackupResponseChunk); // 拉备份
rpc LeaseLsn (LeaseLsnRequest) returns (LeaseLsnResponse); // LSN 租约(防 GC)
没有 GetPageAtLsn 这种单次 RPC——用双向流 GetPages 替代,避免每次 HTTP/2 流的开销。
主要区别
1. 性能:gRPC 用 HTTP/2 multiplexing,批处理更好;proto 注释说 streaming 比 unary "~doubles throughput"
2. 鉴权:gRPC 用 header(authorization: Bearer <JWT> + neon-tenant-id),pagestream 用 libpq password
3. Shard 路由:gRPC 通过 neon-shard-id header 指定,client_grpc/src/split.rs 自动拆分跨 shard 请求
4. 错误处理:gRPC 用 GetPageStatusCode 内嵌在消息里(避免终止 stream),pagestream 用独立错误消息
5. 成熟度:pagestream 是当前生产协议,gRPC 标记为 EXPERIMENTAL
简单说:gRPC 是 pagestream 的新一代替代方案,功能等价但用 Protobuf + HTTP/2 重做了,预期性能更好、更易维护。目前 compute 默认仍走
pagestream。
本文对比Neon数据库中compute节点与PageServer通信的两种读路径协议:PageStream(基于libpq COPY模式的二进制协议)和gRPC(基于Protobuf与HTTP/2的流式协议)。重点分析二者在性能(multiplexing与吞吐提升)、鉴权机制、分片路由、错误处理及成熟度等方面的差异,指出gRPC是面向未来优化的实验性替代方案,当前生产环境仍默认使用PageStream。
26

被折叠的 条评论
为什么被折叠?



