不建议从零手写高性能RPC框架,核心难点在于“稳、快、可观测、可运维”,brpc/rest_rpc等已封装多路复用、连接池、协议栈、熔断与状态页;自研需攻克帧头设计、序列化绑定、异步模型三大协议层问题。

直接说结论:不建议从零手写高性能 RPC 框架,除非你明确要深入网络/并发/协议底层,或已有成熟团队支撑。真正生产可用的 C++ RPC 框架,核心难点不在“能通”,而在“稳、快、可观测、可运维”——这些能力靠 10 行 socket + protobuf 远远不够。
为什么 brpc / rest_rpc / muduo-based 框架更值得优先选型
brpc 和 rest_rpc 已经把最耗时、最易出错的模块封装好了:epoll/kqueue 多路复用层、连接池管理、HTTP/2 与 protobuf 协议栈共存、超时熔断、内置 /vars 和 /connections HTTP 状态页。你自己重写一遍,光是解决 TCP 粘包+拆包+心跳保活+连接复用这四件事,没两周调不完。
常见错误现象包括:
- 客户端发 3 个请求,服务端只收到 1 个大包(粘包)或半个包(拆包失败)
- 长连接空闲 60 秒后被中间防火墙静默断开,但你的代码还拿着失效 fd 继续
write() - 并发 5000 连接时,每个连接都 new 一个线程,
pthread_create开销压垮调度器
而 brpc 的 Channel 默认启用连接复用,rest_rpc 的 rpc_client 内置连接池 + co_await 超时 watchdog,这些不是“锦上添花”,是避免线上事故的底线能力。
立即学习“C++免费学习笔记(深入)”;
如果真要从零搭,必须立刻处理的三个协议层问题
绕不开的硬骨头就三个:帧头设计、序列化绑定、异步模型选型。别碰“自研压缩/加密”,先让 request_id 和 body_length 对得上。
帧头至少得含:
-
magic(如0x5250)用于快速过滤非法流量 -
message_type(0=Request, 1=Response)驱动分发逻辑 -
request_id(uint64_t,大端)保证请求-响应匹配,别用rand()或时间戳 -
body_length(uint32_t,大端)——这是解包唯一可信依据,别依赖recv()返回值
序列化必须和协议耦合:brpc 直接用 google::protobuf::Message 接口;rest_rpc 允许传入 std::function 自定义序列化函数,但要求输入输出都是 std::string_view。自己写的话,ParseFromArray() 前务必校验 body_length 是否超出缓冲区上限,否则 Segmentation fault 是常态。
协程 vs 线程池:C++20 co_await 不是银弹
rest_rpc 的协程模型依赖 asio::awaitable 和 io_context,它确实让 connect → send → recv 看起来像同步代码。但要注意:
- 所有阻塞系统调用(如
fopen、sleep、未包装的getaddrinfo)会卡死整个io_context线程,必须用asio::this_coro::executor切到线程池执行 -
co_await的 suspend/resume 开销约 20–50ns,比裸指针跳转高一个数量级,高频小包场景(如风控规则引擎)可能反不如libevent回调 - 调试困难:gdb 不支持跨
co_await断点,backtrace里看不到完整调用链
如果你的业务 RPC 调用平均耗时 >5ms(比如查 MySQL 或 Redis),协程收益明显;若大部分是 sub-ms 纯计算,muduo 的 EventLoopThreadPoll 可能更稳。
服务发现和负载均衡不能“后期加”
很多初学者先写单机 echo,跑通再想“怎么加 ZooKeeper”。但服务发现不是插件,它深度耦合在客户端初始化路径里。brpc 的 ChannelOptions 里 lb_policy(如 "rr" 或 "citus")必须在 Channel::Init() 时传入;rest_rpc 的 rpc_client 构造函数不接受地址列表,而是依赖启动时读取 config.json 中的 "servers" 数组。
这意味着:你第一版代码就必须决定——是静态地址列表(开发环境够用),还是集成 zookeeper watch + ephemeral znode(生产必需)。临时改会造成大量接口重构,比如原来 client.call("add", a, b) 得变成 client.call_with_discovery("add", a, b),破坏向后兼容。
真正容易被忽略的是健康检查粒度:brpc 按连接做 ping-pong 心跳;而基于 ZooKeeper 的框架通常按服务实例做 ephemeral node 存活判断——前者能发现网卡故障,后者只能发现进程崩溃。两者不等价,选型时就得明确你的 SLA 要求。



















