基于UB协议OBMM共享内存Transport方案设计
- Dominant language
- C++
- Stars
- 17.6k
- Forks
- 4.1k
- Avg merge
- 2d 12h
- Merged PRs (30d)
- 69
Description
**Is your feature request related to a problem?**
基于 Transport 框架的最新进展(#3167)以及新协议技术路线的社区讨论共识(#3217),我们计划优先完善 UB 共享内存通信协议的扩展。具体实现上,将沿用现有Transport框架技术路线,通过 OBMM 接口进行封装集成,使 Transport 层支持共享内存语义通信。
方案设计思路整理如下,欢迎 @chenBright @wwbmmm 及各位大佬一起交流讨论。
---------------------------
# 1.背景概况
## 1.1 brpc现有传输层协议面临的问题
**TCP Transport的固有瓶颈:**
brpc的TCP实现虽通过bthread实现了高并发,但受限于TCP/IP协议栈架构:
* **内核态开销**:数据需经过内核网络栈、协议处理、数据拷贝,端到端延迟通常在10-50微秒量级。
* **CPU资源消耗**:高吞吐场景下,协议处理、校验和计算、拥塞控制逻辑占用大量CPU周期。
* **数据拷贝开销**:即使使用zero-copy技术,仍需在kernel space与user space之间多次拷贝数据。
**RDMA Transport的扩展性与语义限制:**
brpc的RDMA实现通过 verbs 接口(ibv_post_send/ibv_post_recv)实现零拷贝,但存在相应的局限:
* **连接状态爆炸**:基于Queue Pair (QP)的面向连接模型,在千级节点规模下QP数量达百万级,耗尽网卡片上内存。
* **硬件资源争用**:控制面操作(内存注册/注销)与数据面竞争网卡内部资源,导致性能抖动。
* **语义不匹配**:RDMA的Read/Write语义是"设备DMA"而非"处理器Load/Store",无法直接利用CPU缓存层次结构。
# 2.提案的动机
## 2.1 广告搜推场景实测与性能瓶颈拆解
为验证当前brpc传输层在线推理场景的真实表现,我们构建了生产级搜推集群(特征抽取→模型推理→CTR预估全链路)中进行了对比测试。该场景对延迟极度敏感:**一次广告请求需经过召回(百万级向量ANN检索)→粗排→精排→重排**,每个阶段涉及数十次RPC调用,端到端P99延迟要求<150ms,单节点QPS达最高可达30万。
### 2.1.1 测试场景设计
**业务模型:**
* **服务拓扑**:32台特征抽取服务(Leaf)→ 8台模型推理服务(Root),全互联通信.
* **请求特征**:平均请求包大小 2.3KB(Dense特征+SparseID序列),响应包 0.5KB(分数/Embedding)
* **负载特征**:高并发(单节点30万QPS)、长连接、小消息为主、突发流量(大促时QPS×3)
**测试环境:**
* 硬件:Intel Xeon 8480+,512GB DDR5,100Gbps RoCEv2网络(TCP组使用同网络但走Kernel栈)。
* 软件:brpc 1.6.0,bthread并发模式,RDMA组启用brpc原生rdma::Channel。
* 采集指标:P50/P99/P99.9延迟、CPU cycles/request、上下文切换次数、IPC(每周期指令数)
### 2.1.2 TCP vs RDMA性能实测数据
| 指标项 | brpc+TCP | brpc+RDMA | 差异分析 |
|---------|----------|---------|---------|
P50延迟 | 450μs | 12μs | RDMA降低37倍
P99延迟 | 2.8ms | 45μs | TCP长尾严重,RDMA降低62倍
P99.9延迟 | 15ms(抖动剧烈) | 68μs | TCP受内核调度影响出现尖刺
峰值QPS | 120K | 480K | RDMA受限于QP数量无法继续提升
CPU占用 | 85%(8核满载) | 35% | TCP内核栈消耗大量cycles
上下文切换 | 28万次/秒 | 0.8万次/秒 | TCP频繁进出内核态
**数据分析结果:**
- **TCP长尾陷阱**:在30万QPS压力下,TCP的P99达到2.8ms,其中1.2ms消耗在kernel协议栈(sk_buff分配、软中断处理、TCP拥塞控制),且随负载非线性增长,无法满足精排阶段<1ms的延迟SLA。
- **RDMA吞吐量瓶颈**:当单节点需与8个下游节点建立连接时,brpc RDMA的QP数量达256个(32线程×8节点),在480K QPS时遭遇网卡Cache Miss,延迟从12μs跳变至300μs,无法支撑更高并发。
### 2.1.3 延迟构成详细拆解
通过eBPF(bpftrace)和brpc内置tracing对一次典型RPC调用(2.3KB请求)进行微秒级拆解:
**TCP路径延迟分解**(总计2.8ms):
```
[应用层序列化] 45μs (1.6%)
↓
[系统调用] 120μs (4.3%) <-- write()陷入内核
[内核协议栈] 850μs (30.4%) <-- tcp_sendmsg, qdisc, IP层
[网卡DMA] 45μs (1.6%)
[网络传输] 8μs (0.3%) <-- 同机房光纤,物理层极快
[对端网卡中断] 180μs (6.4%) <-- 硬中断+软中断处理
[内核协议栈接收] 620μs (22.1%) <-- tcp_v4_rcv, 拷贝至user space
[系统调用返回] 95μs (3.4%)
↓
[应用层反序列化] 37μs (1.3%)
[排队/锁竞争] 800μs (28.6%) <-- bthread调度队列竞争、内核锁
```
**RDMA路径延迟分解**(总计45μs):
```
[应用层序列化] 45μs (100%) <-- 占比100%,其余硬件卸载
[构建WQE] 8μs (17.8%) <-- 内存注册、地址转换
[Doorbell通知] 2μs (4.4%) <-- 写PCIe寄存器
[网卡处理] 12μs (26.7%) <-- 切包、CRC、调度
[网络传输] 8μs (17.8%)
[对端网卡处理] 10μs (22.2%)
[CQE轮询] 5μs (11.1%) <-- 用户态轮询完成队列
[应用层反序列化] 37μs (82.2%) <-- 零拷贝直接读取
```
**瓶颈识别:**
1. **TCP的28.6%时间消耗在内核态竞争**:在CFS调度器下,软中断与业务线程争抢CPU,导致排队延迟不可控。
2. **RDMA的WQE构建开销**:虽然整体快,但8μs的WQE准备时间占17.8%,且随消息大小增加而增加(大特征包达25μs)。
3. **RDMA的QP缓存失效**:当连接数>200时,网卡片上SRAM不足,需从Host DDR加载QP状态,引入额外300-500ns延迟。
**当前方案在广告搜推场景面临双重困境:**
- **TCP的困境**:
内核协议栈深度过重。即使使用io_uring优化,系统调用和上下文切换仍不可避免,在百万级QPS下累计消耗超过30%的CPU资源,且长尾延迟无法根治。
- **RDMA的困境**:
异步编程模型与硬件资源限制。搜推服务需频繁进行细粒度特征查询(单次查询仅几百字节),RDMA的"准备WQE→Doorbell→轮询CQE"流程在此场景下显得笨重;同时QP数量限制阻碍了水平扩展(当集群规模扩大至64节点时,QP爆炸导致性能骤降)。
**OBMM的针对性优势**:
通过对比测试发现,若采用OBMM纯Load/Store方案:
1. **消除WQE构建开销**:直接通过mov指令写入远端内存,省去8-25μs的WQE准备时间,在2.3KB消息场景下延迟可降至0.8-1.2μs。
2. **零内核介入**:无需系统调用,用户态直接访问,消除TCP的800μs排队延迟和RDMA的Doorbell开销。
3. **扩展性无瓶颈**:单节点仅需维护O(N)个内存映射(N为对端节点数),而非RDMA的O(N×线程数)个QP,在64节点规模下仍保持亚微秒延迟稳定性。
实测数据预测(基于本地共享内存模拟): 在相同搜推负载下,OBMM方案的P99延迟预计为5μs(较RDMA再降9倍),CPU占用降至<5%(指令数减少90%),且在大规模集群(>64节点)下延迟无抖动。
4. **业界技术路线测试数据与引用**
性能基准对比:
|技术方案 | 访问方式 | 单跳延迟 | 编程模型 | 缓存一致性 | 适用边界|
|---------| --------- | ---------|---------| ---------| ---------|
TCP/IP | Socket API | ~50μs | 字节流 | 软件管理 | 广域网
RDMA | Verbs API (异步) | ~2-5μs | Read/Write/Send | 无(需软件同步) | 数据中心
URMA | Segment API (异步) | ~2-5μs | Read/Write | 可选硬件一致性 | 超节点
OBMM | Load/Store | ~几百ns | 直接内存访问 | 可选NC和CC两种 | 超节点
**Describe the solution you'd like**
# 3.设计目标
## 3.1 UB共享内存池管理(基于OBMM)
OBMM通过所有权管理实现跨节点物理内存共享,采用多读单写(MRSW)一致性模型:
* **内存导出(Export)**:服务端调用 obmm_export() 将物理内存段暴露为全局标识的 mem_id,返回授权凭证。
* **内存导入(Import)**:客户端调用 obmm_import(mem_id) 将远端内存映射到本地进程虚拟地址空间(VA)。
* **NUMA透明化**:导入的远端内存作为远程NUMA节点呈现,操作系统可识别并优化调度。
相关接口和工作原理可以访问官网内容:https://atomgit.com/openeuler/obmm
## 3.2 可靠性与流控管理
由于OBMM提供的是**原始共享内存语义**(无内置消息边界、无内置流控),brpc需在应用层构建可靠流控传输机制,不同于RDMA的PFC/ECN或URMA的Jetty流控,OBMM采用**应用层协同流控**。
图片待补充
* **信用量(Credit)**:接收方在共享内存中暴露可用缓冲区大小,发送方通过Load指令读取。
* **批量更新**:每处理N个消息后,原子操作(Atomic Sub)更新Credit,减少Cache Coherence流量。
* **背压(Back Pressure)**:当Credit为0时,发送方自旋等待或让出bthread,避免覆盖未消费数据
## 3.3 最终实现方案与交互模型
### 3.3.1 总体的类图
- **Socket**:属于brpc框架的Socket类,向上层应用提供socket服务,对接下层Transport接口进行数据传输。
- **Transport**:属于brpc的Transport层接口方法,定义了读写的数据传输流程。
- **TransportFactory**:Transport构造工厂类,根据socket_mode类型创建对应的Transport。
- **UBShmTransport**:基于OBMM实现的共享内存Transport类,主要基于共享内存UBRing结构实现通信,同时管理着UBRingListener进行监听建链事件。
- **UBShmListener**:基于OBMM实现的共享内存Listener类,主要用于server端监听建链信息并交换建链信息数据。
- **UBRing**:基于OBMM实现的共享内存UBRing类,是主要的数据交换通道buffer,采用了环形结构实现数据的交换,一般写方持有的是远端共享内存buffer,读方访问的是本地的共享内存buffer。
- **UBRingEpoll**:基于OBMM实现的共享内存UBRingEpoll类,主要监听本地EventQ消息,当有新的数据包写入时会产生对应的事件通知到下游读方。
### 3.3.2 数据交互模型流程
#### 3.3.4 UBRing交互流程图
**建链流程图**
### 3.3.5 与brpc集成关键点
1. **Socket抽象**:每个brpc Socket对应一个OBMM导入的内存段,包含发送UBRing和接收UBRing。
2. **IOBuf适配**:brpc的IOBuf::Data指向OBMM映射的内存地址,无需拷贝即可直接访问payload。
3. **bthread调度**:使用 butex 等待共享内存中的通知标志位,避免自旋消耗CPU;或配置为轮询模式(低延迟场景)。
4. **零序列化**:对于支持FlatBuffers/Protocol Buffers的零拷贝序列化,可直接在共享内存中构造消息对象,消除序列化开销,这个可以在应用层改造适配。
# 4.总结
OBMM路线(本提案):纯Load/Store共享内存,通过 obmm_import 映射后使用CPU指令直接访问,实现极致延迟和编程透明性。
## 4.1 核心价值
1. **极致延迟**:百ns级访问延迟,较RDMA/URMA提升4-10倍,满足AI推理PD分离场景需求。
2. **编程简化**:远端内存与本地内存统一编址,无需异步编程模型,降低brpc维护复杂度。
3. **硬件一致性**:所有权模型(MRSW)提供硬件级缓存一致性,消除软件同步开销。
4. **超大规模**:O(N)级资源消耗,支持万节点超节点架构,突破RDMA千节点瓶颈。
## 4.2 后续计划
1. **Phase 1**:实现基于OBMM的内存池管理和环形缓冲区协议并集成到Transport架构上。
2. **Phase 2**:调优优化brpc的Socket Transport抽象和bthread调度机制。
**Describe alternatives you've considered**
**Additional context/screenshots**
Contributor guide
Research direction
Start by reading the existing Transport and Socket abstractions, including TransportFactory, then review the linked work in #3167 and discussion in #3217. The proposal names UBShmTransport, UBShmListener, UBRing, and UBRingEpoll as the planned components; done would require a settled Phase 1 design for OBMM memory management, ring-buffer communication, flow control, and Transport integration.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- cpp
- Domain
- backend-api-design, distributed-systems
- Issue type
- Feature
- Difficulty
- 5/5
- Estimated time
- Over a week
- Activity status
- Quiet
- Clarity
- Needs clarification
- Newbie friendliness
- 25/100