-
Notifications
You must be signed in to change notification settings - Fork 4.1k
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%) <-- 零拷贝直接读取
瓶颈识别:
- TCP的28.6%时间消耗在内核态竞争:在CFS调度器下,软中断与业务线程争抢CPU,导致排队延迟不可控。
- RDMA的WQE构建开销:虽然整体快,但8μs的WQE准备时间占17.8%,且随消息大小增加而增加(大特征包达25μs)。
- 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方案:
- 消除WQE构建开销:直接通过mov指令写入远端内存,省去8-25μs的WQE准备时间,在2.3KB消息场景下延迟可降至0.8-1.2μs。
- 零内核介入:无需系统调用,用户态直接访问,消除TCP的800μs排队延迟和RDMA的Doorbell开销。
- 扩展性无瓶颈:单节点仅需维护O(N)个内存映射(N为对端节点数),而非RDMA的O(N×线程数)个QP,在64节点规模下仍保持亚微秒延迟稳定性。
实测数据预测(基于本地共享内存模拟): 在相同搜推负载下,OBMM方案的P99延迟预计为5μs(较RDMA再降9倍),CPU占用降至<5%(指令数减少90%),且在大规模集群(>64节点)下延迟无抖动。 - 业界技术路线测试数据与引用
性能基准对比:
| 技术方案 | 访问方式 | 单跳延迟 | 编程模型 | 缓存一致性 | 适用边界 |
|---|---|---|---|---|---|
| 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集成关键点
- Socket抽象:每个brpc Socket对应一个OBMM导入的内存段,包含发送UBRing和接收UBRing。
- IOBuf适配:brpc的IOBuf::Data指向OBMM映射的内存地址,无需拷贝即可直接访问payload。
- bthread调度:使用 butex 等待共享内存中的通知标志位,避免自旋消耗CPU;或配置为轮询模式(低延迟场景)。
- 零序列化:对于支持FlatBuffers/Protocol Buffers的零拷贝序列化,可直接在共享内存中构造消息对象,消除序列化开销,这个可以在应用层改造适配。
4.总结
OBMM路线(本提案):纯Load/Store共享内存,通过 obmm_import 映射后使用CPU指令直接访问,实现极致延迟和编程透明性。
4.1 核心价值
- 极致延迟:百ns级访问延迟,较RDMA/URMA提升4-10倍,满足AI推理PD分离场景需求。
- 编程简化:远端内存与本地内存统一编址,无需异步编程模型,降低brpc维护复杂度。
- 硬件一致性:所有权模型(MRSW)提供硬件级缓存一致性,消除软件同步开销。
- 超大规模:O(N)级资源消耗,支持万节点超节点架构,突破RDMA千节点瓶颈。
4.2 后续计划
- Phase 1:实现基于OBMM的内存池管理和环形缓冲区协议并集成到Transport架构上。
- Phase 2:调优优化brpc的Socket Transport抽象和bthread调度机制。
Describe alternatives you've considered
Additional context/screenshots