先上UserServer提供服务的函数要求proto文件内容:
syntax="proto3"; package fixbug; option cc_generic_services=true; message LoginRequest { bytes name=1; bytes pwd=2; } message LoginResponse { ResultCode result=1; bool sucess=2; } #调用远程服务的入口 service UserServiceRpc { rpc Login(LoginRequest)returns(LoginResponse); }
proto内容的解释:1.message类属性 2.service是一个抽象接口
接口类,也就是纯虚函数
Service:抽象接口由UserServiceRPC 和UserServiceRPC_Shub
这两个抽象类实现
UserServiceRPC:也就是Server端的服务的入口
UserServiceRPC_Shub:就是Client端请求服务的入口
下面直接源码:
class PROTOBUF_EXPORT Service { public: inline Service() {} virtual ~Service(); enum ChannelOwnership { STUB_OWNS_CHANNEL, STUB_DOESNT_OWN_CHANNEL }; //能够通过Service->GetDescriptor()得到派生类的ServerService的服务名和方法名 virtual const ServiceDescriptor* GetDescriptor() = 0; //这个函数是被调用的函数,method是被调用的方法描述符,method->GetMethodDescriptor() //能够拿到方法的名字以及method->service()拿到对应的服务 //Controller用于实现对于整个RPC的状态的控制,比如调用失败,就终止调用 // request即调用方法的参数,response即调用方法的返回值 //Clouser一个抽象的回调函数接口 virtual void CallMethod(const MethodDescriptor* method, RpcController* controller, const Message* request, Message* response, Closure* done) = 0; //通过基类指针拿到派生类的Request virtual const Message& GetRequestPrototype( const MethodDescriptor* method) const = 0; //通过基类指针拿到派生类的Response virtual const Message& GetResponsePrototype( const MethodDescriptor* method) const = 0; }
RpcController的代码,也是一个接口函数
class PROTOBUF_EXPORT RpcController { public: inline RpcController() {} virtual ~RpcController(); virtual void Reset() = 0; virtual bool Failed() const = 0; virtual std::string ErrorText() const = 0; virtual void StartCancel() = 0; virtual void SetFailed(const std::string& reason) = 0; virtual bool IsCanceled() const = 0; virtual void NotifyOnCancel(Closure* callback) = 0; }
RpcChannel,同样是一个接口,是用来调用远端服务的入口
class PROTOBUF_EXPORT RpcChannel { public: inline RpcChannel() {} virtual ~RpcChannel(); virtual void CallMethod(const MethodDescriptor* method, RpcController* controller, const Message* request, Message* response, Closure* done) = 0; private: GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(RpcChannel); };
比较重要的,需要通过这个来完成Client调用,即
上面的几个重要的接口类,介绍完,那我们回到我们要做的内容
UserServiceRPC 和UserServiceRPC_Shub
这两个类经过proto自己生成的类,根据规定rpc UserserviceRpc(request)returns{response}
class UserServiceRpc : public ::google::protobuf::Service { protected: inline UserServiceRpc() {}; public: virtual ~UserServiceRpc(); typedef UserServiceRpc_Stub Stub; static const ::google::protobuf::::ServiceDescriptor* descriptor(); virtual void Login(::google::protobuf::::RpcController* controller, const ::fixbug::LoginRequest* request, ::fixbug::LoginResponse* response, ::google::protobuf::Closure* done); // implements Service ---------------------------------------------- const ::google::protobuf::::ServiceDescriptor* GetDescriptor(); void CallMethod(const ::google::protobuf::MethodDescriptor* method, ::google::protobuf::RpcController* controller, const ::google::protobuf::Message* request, ::google::protobuf::Message* response, ::google::protobuf::Closure* done); const ::google::protobuf::Message& GetRequestPrototype( const ::google::protobuf::MethodDescriptor* method) const; const ::google::protobuf::Message& GetResponsePrototype( const ::google::protobuf::MethodDescriptor* method) const; private: GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(UserServiceRpc); }; class UserServiceRpc_Stub : public UserServiceRpc { public: //这个UserServiceRpc_Stub,通过RpcChannel对象进行构造,目的是在RpcChannel的派生类中 //直接调用派生类处理的函数 UserServiceRpc_Stub(::google::protobuf::RpcChannel* channel); UserServiceRpc_Stub(::google::protobuf::RpcChannel* channel, ::google::protobuf::Service::ChannelOwnership ownership); ~UserServiceRpc_Stub(); inline ::PROTOBUF_NAMESPACE_ID::RpcChannel* channel() { return channel_; } // implements UserServiceRpc ------------------------------------------ void Login(::google::protobuf::RpcController* controller, const ::fixbug::LoginRequest* request, ::fixbug::LoginResponse* response, ::google::protobuf::Closure* done); private: ::google::protobuf::RpcChannel* channel_; bool owns_channel_; GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(UserServiceRpc_Stub); };
上述重点看一下:login和callback,
login:就是我们定义的rcp service,
CallBack:就是Client调用函数后的内容
区别:通过上面两个类,我们可以很明显的发现,UserServiceRpc有回调函数,UserServiceRpcSthub明显没有一个CallBack的回调函数。因此,可以知道RPC服务的过程。
但是,我们请求RCP服务必定是要有回调的,Client发起请求同样RPC要给Client一个回调,Server执行login并执行回调,这个执行的回调函数,就是通过实现RpcChannel的派生类来调用的
总结:
Service、Controller、RpcChannle 我们可以简单的描述成下面的过程:
1.调用本地的login调用UserServiceRpc_Stub的login
2.new一个UserServiceRpc_Stub,并用SubRpcChannel初始化
3.执行回调函数,并序列化成规定的格式:比如:header_size+header_str(service_name、method_name)+args_size+args_str。然后,直接通过网络发送出去。
4.将header_size+header_str(service_name、method_name)+args_size+args_str规定的编解码格式解码成对应的service,method,agrs.
5.provider上述的service,method,agrs,然后通过提前将UserServiceRpc(继承Service)提前发布的方法,通过参数名直接找到对应的service,method,args
6.执行Userservice继承UserServiceRpc,实现提供的服务,并返回值
7.将派生类返回的值交给基类
8.将基类拿到的response序列化成二进制交给provider,并直接交给网络
9.将拿到的二进制,反序列化成response
10.执行RpcChannle的CallBack函数,将response返回给UserServiceRpc_Stub
11.UserServiceRpc_Stub执行Login函数
12.Client调用UserServiceRpc_Stub的函数