A simple C++ based RPC framework.
PhxRPC是微信后台团队推出的一个非常简洁小巧的RPC框架,编译生成的库只有450K。
作者: Sifan Liu, Haochuan Cui 和 Duokai Huang
联系我们:[email protected]
想了解更多, 以及更详细的编译手册,请进入中文WIKI,和扫描右侧二维码关注我们的公众号
使用Sample目录下的Search RPC C/S进行Echo RPC调用的压测,相当于Worker空转情况。
CPU:24 x Intel(R) Xeon(R) CPU E5-2620 v3 @ 2.40GHz 内存:32 GB 网卡:千兆网卡 Client/Server机器之间PING值: 0.05ms 请求写入并发:1000个线程 业务数据大小:除去HTTP协议部分20b Worker线程数:20
PhxRPC必须依赖的第三方库只有Protobuf。在编译前,在third_party目录放置好protobuf目录,或者通过软链的形式。
PhxRPC在ServerIO以及Client并发连接管理上使用了ucontext,而boost的ucontext实现要比system默认的更为高效,推荐使用boost。如果需要使用boost的话需要在third_party目录放置好boost目录,或者通过软链的形式。
进入PhxRPC根目录。
make (默认是-O2编译,如需编译debug版,执行 make debug=y)
make boost (可选,编译PhxRPC的boost优化插件,编译之前先准备好boost库)
下面是sample目录下的proto文件样例。
…
(PhxRPC根目录)/codegen/phxrpc_pb2server -I (PhxRPC根目录) -I (Protobuf include目录) -f (proto文件路径) -d (生成代码放置路径)
# sample
../codegen/phxrpc_pb2server -I ../ -I ../third_party/protobuf/include -f search.proto -d .
../codegen/phxrpc_pb2server -I ../ -I ../third_party/protobuf/include -f search.proto -d . -u
两种生成模式,区别在于-u参数。
第一种生成默认的线程池worker模型。
第二种-u参数指定生成uthread worker模型,也就是工作线程池里面每个线程里面运行着多个协程。
调用完工具后,在生成代码放置目录下执行make,即可生成全部的RPC相关代码。
打开生成代码放置目录下的Makefile文件。
# choose to use boost for network
#LDFLAGS := $(PLUGIN_BOOST_LDFLAGS) $(LDFLAGS)
可以看到以上两行,取消注释掉第二行,重新make clean && make即可开启Boost对PhxRPC的优化。开启前记得编译好PhxRPC的Boost插件。
int SearchServiceImpl::PHXEcho(const google::protobuf::StringValue &req,
google::protobuf::StringValue *resp) {
resp->set_value(req.value());
return 0;
}
int SearchServiceImpl::Search(const search::SearchRequest &req,
search::SearchResult *resp) {
// 这里补充这个RPC调用的Server端代码
return -1;
}
int SearchServiceImpl::Notify(const google::protobuf::StringValue &req,
google::protobuf::Empty *resp) {
// 这里补充这个RPC调用的Server端代码
return -1;
}
…
…
…
uthread_begin, uthread_end, uthread_s, uthread_t这几个关键字是PhxRPC自定义的宏,分别表示协程的准备、结束,协程调度器以及协程的创建。
上面的代码实现了Google提出的 Backup Requests 模式。实现的功能是分别对两个Server同时发起Echo调用,当有一个Server响应的时候,则整个函数结束。在这段代码里面,我们提供了一种异步IO的同步写法,并给予了一些方便使用的宏定义。首先使用uthread_begin进行准备,然后使用uthread_t以lambda的形式创建一个协程,而在任意一个协程里面都可使用我们PhxRPC生成的Client API进行RPC调用,并可使用uthread_s随时结束所有RPC调用。最后的uthread_end真正通过协程调度发起这些lambda内的RPC调用,并等待结束。
当然你可以借用这4个宏定义,以同步代码的写法,进行更自定义的并发访问。
…
No open issues yet, or sync has not completed.