多彩编程 多彩编程MZPH · CODE BLOG
ARTICLE DETAIL

文章详情

深耕前端与后端开发技术的一线实战笔记与踩坑复盘。

brpc 对接 Thrift 协议:编译配置、客户端/服务端接入与性能实测指南

brpc 对接 Thrift 协议:编译配置、客户端/服务端接入与性能实测指南 【免费下载链接】brpcbrpc is an Industrial-grade RPC framework using C Language, which is often used in high performance system such as Search, Storage, Machine learning, Advertisement, Recommendation etc. brpc means better RPC.项目地址https://gitcode.com/gh_mirrors/brpc3/brpc点击查看免费下载本文是 brpc 直接支持 Thrift 协议thrift NonBlocking 模式的 framed transport的完整技术指南覆盖从 Thrift 库安装、brpc 开启--with-thrift编译到用brpc::ThriftStub访问既有 Thrift 服务、用brpc::ThriftService处理 Thrift 请求再到多线程、异步与代理转发等进阶用法。读完本文你将掌握如何在不重写业务代码的前提下让既有 Thrift 服务接入 brpc 的线程安全、负载均衡、超时重试与内置监控能力并看到仓库提供的基准测试数据作为选型参考。为什么用 brpc 对接 Thrift 协议Thrift 最初由 Facebook 开发、后被 Apache 基金会接管是一个在多种环境中被广泛使用的 RPC 框架。brpc 直接支持 Thrift 在NonBlocking 模式即 framed transport下使用的 thrift 协议从而让 brpc 客户端可以访问既有 Thrift 服务也让 brpc 服务端可以处理 Thrift 请求。相比官方 thrift 方案brpc 的接入方式带来一系列直接收益见 docs/en/thrift.md线程安全brpc::Channel与brpc::ThriftStub都是线程安全的无需像官方实现那样为每个线程单独建立一套 client 对象访问方式丰富支持同步、异步、批量同步、批量异步等调用方式组合 Channel如ParallelChannel并行访问多组服务同样适用连接与治理能力支持 short短连接、连接池等多种连接类型并完整继承 brpc 的超时、backup request备份请求、取消、tracing 与内置服务等能力性能更好仓库内提供了与原生 thrift 的实测对比数据见下文。编译支持如何开启 thrift 特性brpc默认不开启thrift 支持也不默认依赖 thrift 库同时brpc 复用了部分 thrift 工具生成的代码因此需要先安装 thrift 开发库。若需启用编译 brpc 时额外传入--with-thriftconfigure 脚本或-DWITH_THRIFTONCMake即可。在 Linux 下安装 thrift参考 Thrift 官方安装文档安装依赖库与工具后从官方站点下载 thrift 源码包并编译安装。仓库文档给出的可复现命令如下以 thrift 0.18.1 为例wget https://downloads.apache.org/thrift/0.18.1/thrift-0.18.1.tar.gz tar -xf thrift-0.18.1.tar.gz cd thrift-0.18.1/ ./bootstrap.sh ./configure --prefix/usr --with-rubyno --with-pythonno --with-javano --with-gono --with-perlno --with-phpno --with-csharpno --with-erlangno --with-luano --with-nodejsno --with-rsno --with-py3no CXXFLAGS-Wno-error make CPPFLAGS-DFORCE_BOOST_SMART_PTR -j 4 -s sudo make install需要说明的是--prefix/usr将库安装到系统路径便于后续链接--with-*系列参数只保留 C 语言绑定可显著缩短编译时间CPPFLAGS-DFORCE_BOOST_SMART_PTR与CXXFLAGS-Wno-error用于规避较老编译器对 thrift 源码的告警。实际使用中请根据你的发行版与 thrift 版本灵活调整。配置 brpc 并编译# Ubuntu sh config_brpc.sh --headers/usr/include --libs/usr/lib --with-thrift # Fedora/CentOS sh config_brpc.sh --headers/usr/include --libs/usr/lib64 --with-thrift # 或者使用 cmake mkdir build cd build cmake ../ -DWITH_THRIFTON编译完成后libbrpc.a中即包含 thrift 扩展代码可像其他 brpc 项目一样正常链接。更多编译选项参见 Getting Started。示例工程的 Makefile 展示了链接方式的关键差异——需要额外链接-lthrift原生 thrift 对比程序还需-lthriftnb -levent且通过thrift --gen cpp echo.thrift生成原生代码并打包为libechothrift.a后参与编译链接。客户端访问 Thrift 服务端按以下三步即可发起调用创建brpc::Channel将options.protocol设置为brpc::PROTOCOL_THRIFT基于该 Channel 创建brpc::ThriftStub直接使用 thrift 生成的原生 request/response 类型发起 RPC。核心代码完整示例见 example/thrift_extension_c/client.cpp#include brpc/channel.h #include brpc/thrift_message.h // 定义 ThriftStub ... DEFINE_string(server, 0.0.0.0:8019, IP Address of thrift server); DEFINE_string(load_balancer, , The algorithm for load balancing); ... brpc::ChannelOptions options; options.protocol brpc::PROTOCOL_THRIFT; brpc::Channel thrift_channel; if (thrift_channel.Init(FLAGS_server.c_str(), FLAGS_load_balancer.c_str(), options) ! 0) { LOG(ERROR) Fail to initialize thrift channel; return -1; } brpc::ThriftStub stub(thrift_channel); ... // example::EchoRequest / EchoResponse 是 thrift 生成的原生类型 example::EchoRequest req; example::EchoResponse res; req.data hello; stub.CallMethod(Echo, cntl, req, res, NULL); if (cntl.Failed()) { LOG(ERROR) Fail to send thrift request, cntl.ErrorText(); return -1; }几个关键点方法名以字符串传入CallMethod的第一个参数是 Thrift 方法名如Echo由 brpc 序列化进协议头服务端据此分发无需像 protobuf 服务那样携带方法描述符Channel与Stub均可跨线程共享示例中的brpc::ThriftStub stub(thrift_channel)在 client2.cpp 里被 50 个线程共同持有并各自CallMethod这正是文档强调的线程安全收益同步/异步由最后一个参数控制done NULL时同步阻塞等待传入google::protobuf::Closure回调则异步执行。客户端底层ThriftStub 如何复用原生消息ThriftStub定义在 src/brpc/thrift_message.h。模板版CallMethod(method_name, cntl, raw_request, raw_response, done)的实现思路是把用户传入的原生请求对象包装成details::ThriftMessageWrapperREQUEST再装入统一的ThriftFramedMessage一个继承自google::protobuf::Message的适配层最终落到_channel-CallMethod上。异步场景下模板会分配details::ThriftDoneWrapperRESPONSE让done回调持有响应对象并在Run()后自动释放见 src/brpc/thrift_message.h#L170-L239——同步调用则把响应放在栈上以避免堆分配。这种“原生消息 通用适配层”的设计正是 brpc 能在不改动 thrift 生成代码的前提下接入其协议栈的关键。服务端处理 Thrift 请求服务端需要继承brpc::ThriftService并实现ProcessThriftFramedRequest。在该方法中你可以直接调用 thrift 生成的原生 handler 复用既有入口也可以像 protobuf 服务一样直接读取请求、设置响应。class EchoServiceImpl : public brpc::ThriftService { public: void ProcessThriftFramedRequest(brpc::Controller* cntl, brpc::ThriftFramedMessage* req, brpc::ThriftFramedMessage* res, google::protobuf::Closure* done) override { // 按方法名分发到不同处理函数 if (cntl-thrift_method_name() Echo) { return Echo(cntl, req-Castexample::EchoRequest(), res-Castexample::EchoResponse(), done); } else { cntl-SetFailed(brpc::ENOMETHOD, Fail to find method%s, cntl-thrift_method_name().c_str()); done-Run(); } } void Echo(brpc::Controller* cntl, const example::EchoRequest* req, example::EchoResponse* res, google::protobuf::Closure* done) { // ClosureGuard 以 RAII 方式保证 done-Run() 被调用 // 若需异步处理请求请改为 done_guard.release()。 brpc::ClosureGuard done_guard(done); res-data req-data (processed); } };将实现类挂到ServerOptions.thrift_service后启动服务brpc::Server server; brpc::ServerOptions options; options.thrift_service new EchoServiceImpl; options.idle_timeout_sec FLAGS_idle_timeout_s; options.max_concurrency FLAGS_max_concurrency; if (server.Start(FLAGS_port, options) ! 0) { LOG(ERROR) Fail to start EchoServer; return -1; }服务端底层方法分发与延迟解析ThriftService的抽象接口见 src/brpc/thrift_service.h它同时持有MethodStatus状态统计与AdaptiveMaxConcurrency自适应并发控制使 thrift 服务也能获得 brpc 内置服务的监控与限流能力cntl-thrift_method_name()返回协议头中解析出的方法名定义于 src/brpc/controller.h#L598未匹配到方法时用ENOMETHOD置失败req-CastT()是惰性解析首次调用时才把ThriftFramedMessage::body中的二进制结构体解析为原生类型T解析完成后缓存实例后续Cast直接复用见 src/brpc/thrift_message.h#L189-L209。正因如此服务端在只做代理转发时完全可以不Cast直接把req/res原样转发见下节thrift 结构化数据要求 request/response 分别挂在协议字段 1 与 0 上这对应源码中的THRIFT_REQUEST_FID 1与THRIFT_RESPONSE_FID 0常量src/brpc/thrift_message.h#L44-L45。进阶用法多线程压测与代理转发示例目录中还有两个进阶程序client2.cpp多线程压测客户端。它支持--thread_num默认 50、--use_bthread用 bthread 替代 pthread 发压、--connection_typesingle/pooled/short、--request_size、--timeout_ms、--max_retry等 gflags 参数并可用bvar::LatencyRecorder实时统计 qps 与延迟。所有线程共享同一个Channel直观验证了线程安全特性server2.cpp代理转发服务端。EchoServiceImpl内部再初始化一个PROTOCOL_THRIFT的Channel对Echo请求直接stub.CallMethod(RealEcho, cntl, req, res, NULL)原样转发——注意此处req/res 不 Cast以ThriftFramedMessage形式透传演示了 brpc 的 thrift 实现可串联成代理链。对应服务的 thrift 定义见 echo.thriftEchoRequest/EchoResponse/EchoService.Echo原生实现对照见 native_client.cpp 与 native_server.cpp可用于原生与 brpc 两种实现的对比验证。该目录的 README.md 明确说明目前仅支持 thrift framed transport即只适用于 thrift NonBlocking 模式。协议实现原理brpc 如何解析 Thrift 帧thrift 协议的解析位于 src/brpc/policy/thrift_protocol.cpp。其核心是通过ReadThriftMessageBegin手工解析消息头不依赖 thrift 库的解析函数以获得更快的速度Version Message type Length Method Sequence Id | | | | | 3 1 4 0 4前 4 字节的高位是版本号THRIFT_HEAD_VERSION_1 0x80010000低 8 位为消息类型TMessageType随后 4 字节是方法名长度、方法名字符串、4 字节序列号方法名长度上限为MAX_THRIFT_METHOD_NAME_LENGTH 256超长直接判为非法请求src/brpc/policy/thrift_protocol.cpp#L63请求在服务端入口被还原出thrift_method_name用于分发同时支持写入 tracing span 名ResetServerSpanName因此 Thrift 请求同样能在内置监控与 tracing 体系中定位。此外PROTOCOL_THRIFT协议枚举值定义于 src/brpc/options.proto#L45作为ChannelOptions.protocol的合法取值。与原生 thrift 的性能对比仓库文档在 48 核 2.30GHz 环境下进行了三组对比测试客户端与服务器端分别基于原生 thrift 与 brpc thrift 实现场景一服务端原样返回客户端发来的字符串 helloFrameworkThreads NumQPSAvg latencyCPUnative thrift606.9w0.9ms2.8%brpc thrift6030w0.2ms18%场景二服务端返回 hello * 1000FrameworkThreads NumQPSAvg latencyCPUnative thrift605.2w1.1ms4.5%brpc thrift6019.5w0.3ms22%场景三服务端做较复杂的数学运算后返回 hello * 1000FrameworkThreads NumQPSAvg latencyCPUnative thrift601.7w3.5ms76%brpc thrift602.1w2.9ms93%解读在轻负载场景一、二下 brpc 的 QPS 提升约 3.7~4.3 倍、延迟下降明显代价是 CPU 占用更高协议栈本身更积极地利旧 CPU在业务本身成为瓶颈的场景三中两者差距缩小但仍有一定提升。这些数据是文档作者在特定硬件与版本下的实测结果仅供同类型场景的选型参考实际收益需结合自身业务的运算比重、网络环境与 brpc/thrift 版本自行压测验证。你可以直接运行示例目录下的echo_client/echo_client2与原生native_client复现对比。小结接入路径可概括为三步装 thrift 库并开启--with-thrift编译 brpc → 客户端用ThriftStub直接调原生类型 → 服务端继承ThriftService实现方法分发。核心接入代码集中在 thrift_message.h、thrift_service.h 与 thrift_protocol.cpp完整可运行示例在 example/thrift_extension_c 目录下。若需在既有 Thrift 集群中引入线程安全、负载均衡、超时重试、备份请求与内置监控这是成本最低的接入方式之一。赞分享【免费下载链接】brpcbrpc is an Industrial-grade RPC framework using C Language, which is often used in high performance system such as Search, Storage, Machine learning, Advertisement, Recommendation etc. brpc means better RPC.项目地址https://gitcode.com/gh_mirrors/brpc3/brpc点击查看免费下载相关推荐brpc 集成 Thrift 协议从编译配置到客户端/服务端接入的完整实战指南brpc 集成 Thrift 协议从编译配置到客户端/服务端接入的完整实战指南 brpc 直接支持 Thrift 在 NonBlocking 模式下使用的 FRPC框架后端微服务网络通信brpc 的 Thrift 协议支持编译接入、Client/Server 编程模型与性能对比实战brpc 的 Thrift 协议支持编译接入、Client/Server 编程模型与性能对比实战 brpc 原生实现了 Apache Thrift 在 NonRPC框架后端微服务网络通信使用 tonic-web 为 tonic 服务直接接入 gRPC-Web 客户端协议翻译、CORS 配置与实战指南使用 tonic web 为 tonic 服务直接接入 gRPC Web 客户端协议翻译、CORS 配置与实战指南 导读 tonic web 是 grpc r后端RPC框架上一篇Midway 构建产物测试实践用 8 个测试文件为 validation-* 包把守 CJS/ESM 发布质量下一篇WindowResizer终极指南3分钟学会强制调整任意Windows窗口大小创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表