当前位置:   article > 正文

基于Protobuf的RPC

基于Protobuf的RPC

先上UserServer提供服务的函数要求proto文件内容:

  1. syntax="proto3";
  2. package fixbug;
  3. option cc_generic_services=true;
  4. message LoginRequest
  5. {
  6. bytes name=1;
  7. bytes pwd=2;
  8. }
  9. message LoginResponse
  10. {
  11. ResultCode result=1;
  12. bool sucess=2;
  13. }
  14. #调用远程服务的入口
  15. service UserServiceRpc
  16. {
  17. rpc Login(LoginRequest)returns(LoginResponse);
  18. }

proto内容的解释:1.message类属性 2.service是一个抽象接口

接口类,也就是纯虚函数

Service:抽象接口由UserServiceRPC 和UserServiceRPC_Shub

这两个抽象类实现

UserServiceRPC:也就是Server端的服务的入口

UserServiceRPC_Shub:就是Client端请求服务的入口

下面直接源码:

  1. class PROTOBUF_EXPORT Service {
  2. public:
  3. inline Service() {}
  4. virtual ~Service();
  5. enum ChannelOwnership { STUB_OWNS_CHANNEL, STUB_DOESNT_OWN_CHANNEL };
  6. //能够通过Service->GetDescriptor()得到派生类的ServerService的服务名和方法名
  7. virtual const ServiceDescriptor* GetDescriptor() = 0;
  8. //这个函数是被调用的函数,method是被调用的方法描述符,method->GetMethodDescriptor()
  9. //能够拿到方法的名字以及method->service()拿到对应的服务
  10. //Controller用于实现对于整个RPC的状态的控制,比如调用失败,就终止调用
  11. // request即调用方法的参数,response即调用方法的返回值
  12. //Clouser一个抽象的回调函数接口
  13. virtual void CallMethod(const MethodDescriptor* method,
  14. RpcController* controller, const Message* request,
  15. Message* response, Closure* done) = 0;
  16. //通过基类指针拿到派生类的Request
  17. virtual const Message& GetRequestPrototype(
  18. const MethodDescriptor* method) const = 0;
  19. //通过基类指针拿到派生类的Response
  20. virtual const Message& GetResponsePrototype(
  21. const MethodDescriptor* method) const = 0;
  22. }

RpcController的代码,也是一个接口函数

  1. class PROTOBUF_EXPORT RpcController {
  2. public:
  3. inline RpcController() {}
  4. virtual ~RpcController();
  5. virtual void Reset() = 0;
  6. virtual bool Failed() const = 0;
  7. virtual std::string ErrorText() const = 0;
  8. virtual void StartCancel() = 0;
  9. virtual void SetFailed(const std::string& reason) = 0;
  10. virtual bool IsCanceled() const = 0;
  11. virtual void NotifyOnCancel(Closure* callback) = 0;
  12. }

RpcChannel,同样是一个接口,是用来调用远端服务的入口

  1. class PROTOBUF_EXPORT RpcChannel {
  2. public:
  3. inline RpcChannel() {}
  4. virtual ~RpcChannel();
  5. virtual void CallMethod(const MethodDescriptor* method,
  6. RpcController* controller, const Message* request,
  7. Message* response, Closure* done) = 0;
  8. private:
  9. GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(RpcChannel);
  10. };

比较重要的,需要通过这个来完成Client调用,即

上面的几个重要的接口类,介绍完,那我们回到我们要做的内容 

UserServiceRPC 和UserServiceRPC_Shub 

这两个类经过proto自己生成的类,根据规定rpc UserserviceRpc(request)returns{response}

  1. class UserServiceRpc : public ::google::protobuf::Service {
  2. protected:
  3. inline UserServiceRpc() {};
  4. public:
  5. virtual ~UserServiceRpc();
  6. typedef UserServiceRpc_Stub Stub;
  7. static const ::google::protobuf::::ServiceDescriptor* descriptor();
  8. virtual void Login(::google::protobuf::::RpcController* controller,
  9. const ::fixbug::LoginRequest* request,
  10. ::fixbug::LoginResponse* response,
  11. ::google::protobuf::Closure* done);
  12. // implements Service ----------------------------------------------
  13. const ::google::protobuf::::ServiceDescriptor* GetDescriptor();
  14. void CallMethod(const ::google::protobuf::MethodDescriptor* method,
  15. ::google::protobuf::RpcController* controller,
  16. const ::google::protobuf::Message* request,
  17. ::google::protobuf::Message* response,
  18. ::google::protobuf::Closure* done);
  19. const ::google::protobuf::Message& GetRequestPrototype(
  20. const ::google::protobuf::MethodDescriptor* method) const;
  21. const ::google::protobuf::Message& GetResponsePrototype(
  22. const ::google::protobuf::MethodDescriptor* method) const;
  23. private:
  24. GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(UserServiceRpc);
  25. };
  26. class UserServiceRpc_Stub : public UserServiceRpc {
  27. public:
  28. //这个UserServiceRpc_Stub,通过RpcChannel对象进行构造,目的是在RpcChannel的派生类中
  29. //直接调用派生类处理的函数
  30. UserServiceRpc_Stub(::google::protobuf::RpcChannel* channel);
  31. UserServiceRpc_Stub(::google::protobuf::RpcChannel* channel,
  32. ::google::protobuf::Service::ChannelOwnership ownership);
  33. ~UserServiceRpc_Stub();
  34. inline ::PROTOBUF_NAMESPACE_ID::RpcChannel* channel() { return channel_; }
  35. // implements UserServiceRpc ------------------------------------------
  36. void Login(::google::protobuf::RpcController* controller,
  37. const ::fixbug::LoginRequest* request,
  38. ::fixbug::LoginResponse* response,
  39. ::google::protobuf::Closure* done);
  40. private:
  41. ::google::protobuf::RpcChannel* channel_;
  42. bool owns_channel_;
  43. GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(UserServiceRpc_Stub);
  44. };

上述重点看一下: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的函数

 

本文内容由网友自发贡献,转载请注明出处:https://www.wpsshop.cn/w/我家自动化/article/detail/943200
推荐阅读
相关标签
  

闽ICP备14008679号