-
Notifications
You must be signed in to change notification settings - Fork 4.1k
flatbuffers support(3/3): Add flatbuffers protocol support for brpc #3197
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: master
Are you sure you want to change the base?
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) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
BRPC这个名字改一下,比如FRPC?
| return MakeParseError(PARSE_ERROR_TRY_OTHERS); | ||
| } | ||
| } | ||
| if (n < sizeof(header_buf)) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
适当加一些空行,代码看上去太挤了
| butil::IOBuf* request_buf, | ||
| Controller* cntl, | ||
| const google::protobuf::Message* request); | ||
| const void* request_obj); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
这个改动影响太大了,我认为是不可接受的。不仅是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.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
有没有考虑过这个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: