Doris 实战与架构

分析型数据库 / 源码阅读 / LESSON 13

RPC 通信框架

梳理 FE 与 BE 之间 Thrift、Brpc、Protobuf 等通信栈的职责边界。

阅读时间
30 分钟 | **前置阅读**: [doc-00](doc-00-architecture-overview.md) §2 (FE↔BE)
学习路径
Doris 实战与架构
内容来源
Doris 深度笔记

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


RPC 通信框架 图 01

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.thriftTFrontendServiceFE RPC 接口定义
gensrc/thrift/BackendService.thriftTBackendServiceBE RPC 接口定义
gensrc/thrift/AgentService.thriftTAgentServiceBE Agent 任务(Publish/Clone)
gensrc/proto/olap_file.protoSegmentFooter, PagePointerSegment 数据格式
gensrc/proto/internal_service.protoPTransmitDataParamsBE 间 Exchange
be/src/service/brpc_service.hBrpcServiceBE Brpc Server 入口
fe/fe-core/.../rpc/BackendServiceProxy.javaBackendServiceProxyJava Brpc Client(JNI 封装)

2. Thrift RPC——控制面的通信

IDL 定义

文件说明
gensrc/thrift/FrontendService.thriftFE 对外的 RPC (BE 调 FE)
gensrc/thrift/BackendService.thriftBE 对外的 RPC (FE 调 BE)
gensrc/thrift/AgentService.thriftBE Agent 任务 (Publish/Clone/DropTablet)
gensrc/thrift/HeartbeatService.thriftBE 心跳上报
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.protoSegmentFooter / PagePointer / ColumnMeta
gensrc/proto/internal_service.protoBE 间 Exchange 数据格式
gensrc/proto/data.protoRowBatch 格式
gensrc/proto/olap_common.protoTabletMeta / RowsetMeta

5. RPC 超时/重试机制

配置

参数说明影响
rpc_timeout_msRPC 超时时间过小→频繁失败; 过大→查询慢
max_retry_timesRPC 失败重试次数网络抖动时的鲁棒性
backup_request_ratioBackup 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, 零拷贝)。


RPC 通信栈: Thrift / Brpc / Protobuf

下一步