一文带你搞懂RPC到底是个啥( 二 )


我们一直在说生成代码,到底有什么用呢?图中可以得知,生成代码是衔接用户调用接口和框架代码的桥梁,这里以一个最简单的protobuf自定义协议为例:example.proto
syntax = "proto3";message EchoRequest{string message = 1;};message EchoResponse{string message = 1;};service Example{rpc Echo(EchoRequest) returns (EchoResponse);};我们定义好了请求、回复、远程服务的函数名,通过以下命令就可以生成出接口代码example.srpc.h:
protoc example.proto --cpp_out=./ --proto_path=./srpc_generator protobuf ./example.proto ./我们一窥究竟,看看生成代码到底可以实现什么功能:
// SERVER代码class Service : public srpc::RPCService{public:// 用户需要自行派生实现这个函数,与刚才pb生成的是对应的virtual void Echo(EchoRequest *request, EchoResponse *response,srpc::RPCContext *ctx) = 0;};// CLIENT代码using EchoDone = std::function<void (echoresponse *, srpc::rpccontext *)>;class SRPCClient : public srpc::SRPCClient {public:// 异步接口void Echo(const EchoRequest *req, EchoDone done);// 同步接口void Echo(const EchoRequest *req, EchoResponse *resp, srpc::RPCSyncContext *sync_ctx);// 半同步接口WFFuture<std::pair<echoresponse, srpc::rpcsynccontext>> async_Echo(const EchoRequest *req);};作为一个高性能RPC框架,SRPC生成的client代码中包括了:同步、半同步、异步接口,文章开头展示的是一个同步接口的做法 。
而server的接口就更简单了,作为一个服务端,我们要做的就是收到请求->处理逻辑->返回回复,而这个时候,框架已经把刚才提到的网络收发、解压缩、反序列化等都给做好了,然后通过生成代码调用到用户实现的派生service类的函数逻辑中 。
由于一种协议定义了一种client/server,因此其实我们同样可以得到的server类型有第二部分提到过的若干种:

  • SRPCServer
  • SRPCHttpServer
  • BRPCServer
  • TRPCServer
  • ThriftServer
  • ...
4. 一个完整的server例子最后我们用一个完整的 server 例子,来看一下用户调用接口的使用方式,以及如何跨协议使用HTTP作为client进行调用 。刚才提到,srpc_generator 在生成接口的同时,也会自动生成空的用户代码,我们这里打开 server.pb_skeleton.cc 直接改两行,即可 run 起来:
#include "example.srpc.h"#include "workflow/WFFacilities.h"using namespace srpc;static WFFacilities::WaitGroup wait_group(1);void sig_handler(int signo){wait_group.done();}class ExampleServiceImpl : public Example::Service{public:void Echo(EchoRequest *request, EchoResponse *response, srpc::RPCContext *ctx) override{response->set_message("OK"); // 具体逻辑在这里添加,我们简单地回复一个OK}};int main(){unsigned short port = 80; // 因为要启动Http服务SRPCHttpServer server; // 我们需要构造一个SRPCHttpServerExampleServiceImpl example_impl;server.add_service(&example_impl);server.start(port);wait_group.wait();server.stop();return 0;}只要安装了srpc,linux下即可通过以下命令编译出可执行文件:
g++ -o server server.pb_skeleton.cc example.pb.cc -std=c++11 -lsrpc接下来是激动人心的时刻了,我们用人手一个的curl来发起一个HTTP请求:
$ curl -i 127.0.0.1:80/Example/Echo -H 'Content-Type: application/json' -d '{message:"Hello World"}'HTTP/1.1 200 OKSRPC-Status: 1SRPC-Error: 0Content-Type: application/jsonContent-Encoding: identityContent-Length: 16Connection: Keep-Alive{"message":"OK"}5. 总结今天我们基于 C++ 实现的开源项目 SRPC 深入分析了 RPC 的基本原理 。SRPC 整体代码风格简洁、架构层次精巧,整体约1万行代码,如果你使用 C++,那可能非常适合你用来学习 RPC 架构 。
通过这篇文章,相信我们可以清晰地了解到 RPC 是什么,接口长什么样,也可以通过与HTTP协议互通来理解协议层次,更重要的是可以知道具体纵向的每个层次,及横向对比我们常见的每种使用模式都有哪些 。如果小伙伴对更多功能感兴趣,也可以通过阅读 SRPC 源码进行进一步了解 。




推荐阅读