预计阅读时间: 30 分钟 | 前置阅读: doc-00 §2 (FE↔BE) 下一次阅读: doc-14 (资源管理)

1. FE ↔ BE 通信层——Thrift vs Brpc
| 场景 | 协议 | 特征 |
|---|---|---|
| DDL / 心跳 / 控制命令 | Apache Thrift | 结构化, 类型安全, 跨语言 (Java↔C++) |
| 数据流 (Scan/Write/Exchange) | Brpc (百度RPC) | 高性能, TBuf 流控, 事件驱动 |
| BE 间数据交换 | Brpc | 支持 Pipeline Exchange |
| BE Agent (后台任务) | Thrift | 心跳, Clone, Publish |
源码导航
| 文件 | 关键类/方法 | 职责 |
|---|---|---|
gensrc/thrift/FrontendService.thrift | TFrontendService | FE RPC 接口定义 |
gensrc/thrift/BackendService.thrift | TBackendService | BE RPC 接口定义 |
gensrc/thrift/AgentService.thrift | TAgentService | BE Agent 任务(Publish/Clone) |
gensrc/proto/olap_file.proto | SegmentFooter, PagePointer | Segment 数据格式 |
gensrc/proto/internal_service.proto | PTransmitDataParams | BE 间 Exchange |
be/src/service/brpc_service.h | BrpcService | BE Brpc Server 入口 |
fe/fe-core/.../rpc/BackendServiceProxy.java | BackendServiceProxy | Java Brpc Client(JNI 封装) |
2. Thrift RPC——控制面的通信
IDL 定义
| 文件 | 说明 |
|---|---|
gensrc/thrift/FrontendService.thrift | FE 对外的 RPC (BE 调 FE) |
gensrc/thrift/BackendService.thrift | BE 对外的 RPC (FE 调 BE) |
gensrc/thrift/AgentService.thrift | BE Agent 任务 (Publish/Clone/DropTablet) |
gensrc/thrift/HeartbeatService.thrift | BE 心跳上报 |
gensrc/thrift/Data.thrift | 数据类型 (TScanRange, TRowBatch) |
gensrc/thrift/Exprs.thrift | 表达式定义 (TExpr) |
RPC 调用示例
FE → BE: PublishVersion RPC
1. FE 构造 TPublishVersionRequest (Thrift struct)
2. FE: BackendService.Client.publish_version(request)
3. Thrift 序列化 → TCP Socket → BE
4. BE: PublishVersionWorkerPool 反序列化 + 执行
5. BE 返回 TPublishVersionResult → FE
3. Brpc——数据面的通信
使用模式
// BE 端 Brpc Channel 创建 (be/src/service/)
brpc::Channel channel;
brpc::ChannelOptions options;
options.timeout_ms = 3000;
channel.Init(target_addr, &options);
// 调用 RPC
BackendService_Stub stub(&channel);
brpc::Controller cntl;
stub.send_data(&cntl, &request, &response, NULL/*done*/);
流控机制
Brpc 的 TBuf 缓冲区有最大限制。当发送端速度快于接收端时: TBuf 满 → Producer 被阻塞 → 反压到上游 Pipeline → Scan 停止生产数据。
Backup Request
Brpc 支持 Backup Request: 发送 RPC 到多个 BE (副本), 最先返回的结果被采用, 其他请求被取消。在 BE 上启用可减少长尾延迟 (P99 latency 降低 20-40%)。
4. Protobuf——数据格式
与 Thrift 的配合
Thrift: 用于 RPC 方法定义和参数传递
Protobuf: 用于复杂数据结构 (Segment Footer, Tablet Meta, File Cache)
└── 比 Thrift struct 更紧凑, 更适合持久化
主要的 Proto 文件
| 文件 | 说明 |
|---|---|
gensrc/proto/olap_file.proto | SegmentFooter / PagePointer / ColumnMeta |
gensrc/proto/internal_service.proto | BE 间 Exchange 数据格式 |
gensrc/proto/data.proto | RowBatch 格式 |
gensrc/proto/olap_common.proto | TabletMeta / RowsetMeta |
5. RPC 超时/重试机制
配置
| 参数 | 说明 | 影响 |
|---|---|---|
rpc_timeout_ms | RPC 超时时间 | 过小→频繁失败; 过大→查询慢 |
max_retry_times | RPC 失败重试次数 | 网络抖动时的鲁棒性 |
backup_request_ratio | Backup Request 比例 | 长尾优化 |
失败处理
RPC 失败:
1. Timeout → 重试? (取决于请求类型)
- 幂等操作 (Scan, Check) → 自动重试
- 非幂等 (Publish) → 不重试, 返回错误
2. Connection Refused → 标记 BE 不健康 → 通知 FE TabletChecker
3. Brpc Channel 自动切换副本 (channel 配置了多副本)
6. 常见问题 / 面试题
Q1: 为什么不用 gRPC? A: Brpc 对百度的内部基础设施有更好的支持, 且对 Backup Request/Streaming RPC/类协程(Bthread)的支持优于 gRPC。Doris 2019 年选择 Brpc 是成熟度决定的, 如果重来可能会在 Brpc 和 gRPC 之间重新评估。
Q2: Thrift 和 Brpc 的数据传输方式有何不同? A: Thrift: 完整的 RPC + 序列化框架, 适合低频控制面 (DDL/Heartbeat)。Brpc: 基于 Protobuf + 事件驱动的 RPC 框架, 擅长高吞吐数据流 (TBuf buffer, 零拷贝)。

下一步
- 资源管理: doc-14-resource-workload.md——RPC 的调用如何受到资源限制