flatbuffers support(3/3): Add flatbuffers protocol support for brpc#3197
flatbuffers support(3/3): Add flatbuffers protocol support for brpc#3197Q1ngbo wants to merge 1 commit intoapache:masterfrom
Conversation
Key components:
- Protocol Implementation
* Added flatbuffers_protocol.cpp/h for parsing, serialization and
request/response handling.
* Registered "fb_rpc" protocol in global.cpp
- Core Infrastructure Updates
* Channel: Added FBCallMethod and CallMethodInternal<bool is_pb>
template for dual pb/fb support.
* Controller: Added _fb_method, _fb_response fields and
is_use_flatbuffer() method for flatbuffers state tracking.
* Server: Added FlatBuffersMethodProperty/ServiceProperty structures
and AddService() overloads for flatbuffers::Service registration.
- Protocol Handler Refactoring
* Updated all protocol handlers (baidu_rpc, http, http2, redis, etc.)
to use generic void* pointers instead of google::protobuf types,
enabling protocol-agnostic message handling.
补充内容fb协议处理的简要说明Client应用会创建Stub,然后调用fbs中指定的method方法,之后会去调用channel->FBCallMethod。这些方法都是由flatbuffers自动生成的,而FBCallMethod是在brpc中定义的,此处是二者间的一个桥梁。由于FBCallMethod的实现与针对pb协议的CallMethod非常类似,所以我使用函数模板CallMethodInternal提取了二者中的公共部分,使用参数is_pb区分,CallMethod传入参数为true,FBCallMethod为false。发送路径上的序列化(SerializeFlatBuffersRequest)、Pack(PackFlatBuffersRequest)等操作已经被定义在了Protocol fb_protocol中。 序列化函数SerializeFlatBuffersRequest的执行逻辑非常简单,首先根据FBRpcRequestHeader大小来调整message前面预留的header buffer空间,然后零拷贝地将message中的SingleIOBuf append至目的IOBuf就结束了。值得注意的是,fb协议中header的各字段被硬编码了,不能像pb一样通过proto文件(baidu_rpc_meta.proto)调整。 函数PackFlatBuffersRequest的功能与baidu_std协议中的PackRpcRequest函数类似,只不过rpc header部分已经预先分配好。 Server应创建一个类,继承fb.h中生成的Service,并重载其virtual方法。在启动Server进程时,应将该类对象通过AddService将该service注册至brpc。接收到的请求会交由ProcessFlatBuffersRequest处理,它首先从msg->meta中提取出Header(这一步由SingleIOBuf::assign完成,可能会有拷贝);然后配置Controller,从msg->payload中解析出fb message(同样会调用SingleIOBuf::assign);交由应用响应。应用逻辑处理完成后,会通过SendFlatBuffersRpcResponse向Client发送response message,这里同样会将rpc header + message零拷贝地append到待发送IOBuf中。 性能测试我基于multi_threaded_echo_c++改造了benchmark程序,分别基于pb和fb协议实现,benchmark_fb的实现在#3196中。该程序基于bthread模型,共享同一个channel;每次发送时创建message,该message包含32B固定字段+ string组成的浮动字段(由request_size指定),proto文件定义如下;采用同步发送;输出指标包括延迟和QPS。 syntax="proto2";
option cc_generic_services = true;
package test;
message BenchmarkRequest {
required int32 opcode = 1;
required int32 echo_attachment = 2;
required int64 attachment_size = 3;
required int64 request_id = 4;
optional int64 reserved = 5;
optional string message = 4;
};
message BenchmarkResponse {
required int32 opcode = 1;
required int32 echo_attachment = 2;
required int64 attachment_size = 3;
required int64 request_id = 4;
optional int64 reserved = 5;
optional string message = 4;
};
service BenchmarkService {
rpc Test(BenchmarkRequest) returns (BenchmarkResponse);
};测试目的是为了说明fb的处理效率优于pb。为了避免网络影响,测试在同机上进行,分别为client和server绑定4个核。
下表所示为thread_num=64,即并发bthread数目为64的测试结果,可以看到即使message大小为8KB,fb的提升仍有20.4%。
另外测试发现即使携带attachment,仍能保持相近的提升百分比,因为attachment不会被序列化。 |
| return MakeParseError(PARSE_ERROR_TRY_OTHERS); | ||
| } | ||
| } else { | ||
| if (memcmp(header_buf, "BRPC", n) != 0) { |
| return MakeParseError(PARSE_ERROR_TRY_OTHERS); | ||
| } | ||
| } | ||
| if (n < sizeof(header_buf)) { |
| butil::IOBuf* request_buf, | ||
| Controller* cntl, | ||
| const google::protobuf::Message* request); | ||
| const void* request_obj); |
There was a problem hiding this comment.
这个改动影响太大了,我认为是不可接受的。不仅是brpc代码库中的所有protocol实现需要修改,而且其他用户自己实现的protocol也要修改(即不兼容升级)
我提一个思路你参考一下:你可以让brpc::flatbuffers::Message继承brpc::NonreflectableMessage,这样这个message就自动继承了google::protobuf::Message,这样就可以在不修改brpc框架接口的前提下扩展出flatbuffer协议。你可以参考brpc Redis/Memcached等协议的实现,这些协议实际上并不用到protobuf,但也保持了google::protobuf::Message的接口形式。
| namespace brpc { | ||
| namespace policy { | ||
|
|
||
| struct FBRpcRequestMeta { |
There was a problem hiding this comment.
有没有考虑过这个Meta也用flatbuffers格式呢?这样以后新增字段不会破坏兼容性
What problem does this PR solve?
Issue Number: #3062 #3196
Problem Summary:
Hi, 本提交添加了对flatbuffers协议的完整支持。我增加了与“baidu_std”并列的协议,暂时命名为“fb_rpc”,主要实现在文件flatbuffers_protocol.cpp/h中。我认为以下2点值得关注:
由于该提交依赖于#3196,且编译机器上未安装flatbuffers,所以本pr暂时无法直接编译。我计划根据评审老师的意见再进行修改并添加单测等完整实现。
Check List: