0 序言
protobuf在rpc方面,仅仅提供了一个简单的框架和数据序列化手段,构建client与server之间的连接、通信、存储、线程处理等多方面问题需要用户自己实现。下面,将简单介绍使用protobuf和boost.asio来构建一个简单的rpc。该rpc只是简单阐述protobuf的rpc框架,耦合度较高,具体实现需要根据业务场景来实施。
1 定义.proto文件
protobuf提供了专门的关键字来定义rpc,下面是.proto的文件内容。
// echo.proto
package echo;
cc_generic_services = true; // 指示生成rpc
message RpcRequest { // 存储rpc请求的数据
required string msg = 1;
};
message RpcResponse { // 存储rpc反馈的数据
required string msg = 1;
}
service EchoService { // 定义rpc的接口
rpc Echo(RpcRequest) returns (RpcResponse);
rpc Send(RpcRequest) returns (RpcResponse);
}
上面.proto文件,经过下面的protoc编译,生成echo.pb.h和echo.pb.cc两个文件。
$ protoc --proto_path=./ --cpp_out=./ echo.proto
下面是生成文件中包含的4个类,client和server都知道下面四个类的存在。他们的意义分别是:
- RpcRequest: 存储客户端发送的请求。
- RpcResponse: 存储server端发送的响应。
- EchoService: 在服务器端提供服务。
- EchoService_Stub:在client端作为EchoService的代表提供服务。
class RpcRequest : public google::protobuf::Message;
class RpcRequest : public google::protobuf::Message;
class EchoService : public google::protobuf::Service;
class EchoService_Stub : public EchoService;
需要注意,EchoService运行在服务端,EchoService_Stub代表EchoService,运行在客户端,为EchoService在客户端上的代理——客户端通过EchoService_Stub来提供服务。
此思想与插座相同。用户通过插座获得电能,插座为stub,而实际由远端的电厂来供电。
2 远程调用原理
rpc(远程调用)实际上是cl