Apache bRPC 1.17.0:FlatBuffers 零拷贝、Redis 集群原生通道与 RDMA 扩展齐上阵

2026-06-01 23 预计阅读时间:1 分钟
来源:oschina.net AI 摘要 原文链接

免责声明:本文为 AI 摘要整理,建议结合原文阅读。摘要可能省略上下文、版本差异或边界条件,不作为官方说明。

预计阅读时间:9 分钟

bRPC 作为百度开源的高性能 C++ RPC 框架,已经在工业级微服务场景中打磨多年。1.17.0 版本不是小修小补——它带来了三个方向上的实质性能力跃迁:序列化零拷贝、协议传输层扩展、以及 RDMA 通信增强。如果你在用 bRPC 做高吞吐服务间调用,这版值得跟进。

SingleIOBuf:让 FlatBuffers 真正"零拷贝"

FlatBuffers 的设计初衷就是避免序列化时的中间缓冲区分配,但传统 bRPC 在处理 FlatBuffers 请求时,仍然需要将数据拷进 IOBuf 的链式缓冲区结构。1.17.0 引入的 SingleIOBuf 改变了这一点。

SingleIOBuf 是一块连续内存的单一缓冲区视图,不再像 IOBuf 那样由多个 Block 链式拼接。对于 FlatBuffers 这种本身就产出连续内存布局的序列化方案,SingleIOBuf 可以直接接管 FlatBuffer 的输出指针,省去拼接与拷贝开销。

实际效果:在 FlatBuffers 请求的序列化/反序列化路径上,内存分配次数从"每段一个 Block"降到一次,拷贝字节数趋近于零。对大消息体(比如推荐系统中的特征向量批量传输)场景,延迟和 CPU 占用改善明显。

下面是一个使用 SingleIOBuf 承载 FlatBuffer 请求的简化示例:

#include <brpc/channel.h>
#include <brpc/single_iobuf.h>
#include "flatbuffers/flatbuffers.h"

// 假设已有 FlatBuffer schema 生成的头文件
#include "example_generated.h"

int main() {
    // 1. 构建 FlatBuffer
    flatbuffers::FlatBufferBuilder builder(1024);
    auto name = builder.CreateString("bRPC-user");
    auto payload = example::CreateItem(builder, name, 42);
    builder.Finish(payload);

    // 2. 用 SingleIOBuf 直接接管 builder 的连续内存,零拷贝
    brpc::SingleIOBuf single_buf;
    single_buf.append(builder.GetBufferPointer(), builder.GetSize());

    // 3. 发送 RPC 请求
    brpc::Channel channel;
    brpc::ChannelOptions opts;
    opts.protocol = brpc::PROTOCOL_BAIDU_STD;  // 或自定义 FlatBuffer 协议
    if (channel.Init("127.0.0.1:8010", &opts) != 0) {
        LOG(ERROR) << "Channel init failed";
        return -1;
    }

    brpc::Controller cntl;
    cntl.request_attachment().append(single_buf);  // 附件直接挂载,无额外拷贝
    example::ExampleService_Stub stub(&channel);
    stub.GetItem(&cntl, NULL, NULL, NULL);
    if (cntl.Failed()) {
        LOG(ERROR) << "RPC failed: " << cntl.ErrorText();
    } else {
        LOG(INFO) << "Response size: " << cntl.response_attachment().size();
    }
    return 0;
}

关键点:SingleIOBuf::append 只记录指针和长度,不触发内存拷贝。构建完 FlatBuffer 后直接挂载到 RPC 附件上,整条路径只有 FlatBuffer Builder 内部的一次分配。

原生 Redis 集群通道:不再手动分片

此前 bRPC 的 Redis 通道只支持单节点连接,集群模式下要么依赖客户端侧的分片逻辑,要么在前面架代理。1.17.0 新增了原生 Redis Cluster Channel,框架内部自动处理 slot 映射和请求路由。

这意味着你可以在 bRPC 服务中直接访问 Redis 集群,不用引入额外中间件。对缓存密集型服务(比如特征读取、会话存储),链路更短、运维更简单。

#include <brpc/channel.h>
#include <brpc/redis.h>

int main() {
    brpc::Channel channel;
    brpc::ChannelOptions opts;
    opts.protocol = brpc::PROTOCOL_REDIS_CLUSTER;
    // 连接集群任意节点,框架会自动发现拓扑
    if (channel.Init("10.0.1.100:6379", &opts) != 0) {
        LOG(ERROR) << "Redis cluster channel init failed";
        return -1;
    }

    brpc::RedisRequest req;
    brpc::RedisResponse resp;
    brpc::Controller cntl;

    req.AddCommand("SET session:%s %s", "user_9527", "active");
    req.AddCommand("GET session:%s", "user_9527");

    channel.CallMethod(NULL, &cntl, &req, &resp, NULL);
    if (cntl.Failed()) {
        LOG(ERROR) << "Redis call failed: " << cntl.ErrorText();
    } else {
        LOG(INFO) << "SET reply: " << resp.reply(0).data();
        LOG(INFO) << "GET reply: " << resp.reply(1).data();
    }
    return 0;
}

注意 PROTOCOL_REDIS_CLUSTER 这个协议常量——它告诉 bRPC 按 Redis Cluster 规范处理 MOVED/ASK 重定向和 slot 映射。你只需要给一个种子节点地址,框架自动拉取集群拓扑。

协议扩展传输层与 RDMA ECE

这两个能力面向的是更底层的定制需求。

协议扩展传输层允许你在现有 bRPC 协议(如 baidu_std、hulu_pbrpc)的基础上,自定义传输层行为——比如加一层加密、压缩、或私有帧封装,而不需要从头写一个完整协议。这对需要在内网安全传输或对接遗留帧格式的团队很实用。

RDMA ECE(Extended Connection Establishment) 则是 RDMA 通道的增强。ECE 允许在 RDMA 连接建立阶段交换更多参数(比如协商队列深度、MTU、内存注册策略),避免运行时才发现配置不匹配导致的性能回退。如果你在用 bRPC 的 RDMA 通道做跨机房高速数据同步,ECE 能让连接建立更可靠、参数协商更充分。

稳定性加固与模糊测试

1.17.0 还在稳定性上做了系统性投入:扩展了模糊测试(fuzz testing)的覆盖面,对协议解析、HTTP 处理等入口做了更激进的畸形输入测试。这类投入不会出现在功能列表的头条,但它直接减少了生产环境中被异常请求打崩的概率。

如果你在暴露 bRPC 服务到公网(比如 HTTP+JSON 模式做 API 网关),这版 fuzz 加固值得关注。

升级建议与注意事项

场景 建议
使用 FlatBuffers 且消息体较大 优先升级,SingleIOBuf 的零拷贝收益直接
依赖 Redis 集群做缓存 升级后可去掉客户端分片层或 Redis 代理
RDMA 通道跨机房同步 ECE 参数协商减少连接失败率,建议跟进
服务暴露公网、HTTP 模式 fuzz 加固降低异常请求崩溃风险
纯 gRPC/protobuf 内网服务 收益较小,可按常规版本节奏升级

升级前注意:SingleIOBuf 与传统 IOBuf 的接口不完全兼容,如果你的代码中有对 IOBuf 链式结构的直接操作(比如逐 Block 遍历),需要确认是否受影响。Redis Cluster Channel 是新增协议,不影响已有单节点 Redis 通道的行为。

# 快速拉取 1.17.0 并编译
git clone -b 1.17.0 https://github.com/apache/brpc.git
cd brpc
mkdir build && cd build
cmake -DCMAKE_BUILD_TYPE=Release ..
make -j$(nproc)

# 运行自带示例验证
./example/echo_c++/echo_client --server=127.0.0.1:8010

bRPC 1.17.0 的核心价值不是某个单一功能,而是它在序列化效率、协议灵活性和传输可靠性三个维度同时向前推了一步。如果你的服务间通信正在触碰性能天花板或运维复杂度瓶颈,这版提供了几个具体的突破口。


相关推荐