muduo 使用网络库和 Protobuf 来构建 RPC 框架

通过阅读moduo中rpc的示例程序来分析,如何利用一个网络库和Protobuf来构建一个RPC框架

pb generated sources

分析pb生成了哪些源码,思考需要用网络库去实现哪部分来实现通信

sudoku.proto

package sudoku;
option cc_generic_services = true;
option java_generic_services = true;
option py_generic_services = true;

message SudokuRequest {
  required string checkerboard = 1;
}

message SudokuResponse {
  optional bool solved = 1 [default=false];
  optional string checkerboard = 2;
}

service SudokuService {
  rpc Solve (SudokuRequest) returns (SudokuResponse);
}

sudoku.proto.h & sudoku.proto.cc

SudokuService

class SudokuService : public ::PROTOBUF_NAMESPACE_ID::Service {
   
 protected:
  // This class should be treated as an abstract interface.
  inline SudokuService() {
   };
 public:
  virtual ~SudokuService();

  typedef SudokuService_Stub Stub;

  static const ::PROTOBUF_NAMESPACE_ID::ServiceDescriptor* descriptor();

  virtual void Solve(::PROTOBUF_NAMESPACE_ID::RpcController* controller,
                       const ::sudoku::SudokuRequest* request,
                       ::sudoku::SudokuResponse* response,
                       ::google::protobuf::Closure* done);

  // implements Service ----------------------------------------------

  const ::PROTOBUF_NAMESPACE_ID::ServiceDescriptor* GetDescriptor();
  void CallMethod(const ::PROTOBUF_NAMESPACE_ID::MethodDescriptor* method,
                  ::PROTOBUF_NAMESPACE_ID::RpcController* controller,
                  const ::PROTOBUF_NAMESPACE_ID::Message* request,
                  ::PROTOBUF_NAMESPACE_ID::Message* response,
                  ::google::protobuf::Closure* done);
  const ::PROTOBUF_NAMESPACE_ID::Message& GetRequestPrototype(
    const ::PROTOBUF_NAMESPACE_ID::MethodDescriptor* method) const;
  const ::PROTOBUF_NAMESPACE_ID::Message& GetResponsePrototype(
    const ::PROTOBUF_NAMESPACE_ID::MethodDescriptor* method) const;

 private:
  GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(SudokuService);
};

SudokuService override 了父类 Service的纯虚函数

// Abstract base interface for protocol-buffer-based RPC services.  Services
// themselves are abstract interfaces (implemented either by servers or as
// stubs), but they subclass this base interface.  The methods of this
// interface can be used to call the methods of the Service without knowing
// its exact type at compile time (analogous to Reflection).
class PROTOBUF_EXPORT Service {
   
 public:
  inline Service() {
   }
  virtual ~Service();
  ...

  // Get the ServiceDescriptor describing this service and its methods.
  virtual const ServiceDescriptor* GetDescriptor() = 0;

  virtual void CallMethod(const MethodDescriptor* method,
                          RpcController* controller, const Message* request,
                          Message* response, Closure* done) = 0;

  virtual const Message& GetRequestPrototype(
      const MethodDescriptor* method) const = 0;
  virtual const Message& GetResponsePrototype(
      const MethodDescriptor* method) const = 0;
...

};
descriptor

每一种具体的 Service 类(SudokuService)或 Method(Solve) 或 Message类 (SudokuRequest, SudokuResponse)类都会对应一个全局唯一ServiceDescriptor常量实例或MethodDescriptor常量实例或Descriptor常量实例,用来获取该 ConcreteType 的各种信息

ServiceDescriptor

通过GetDescriptor()这个接口,可以获取到指向SudokuService对应的全局唯一ServiceDescriptor常量实例的指针(const ServiceDescriptor*)

const ::PROTOBUF_NAMESPACE_ID::ServiceDescriptor* SudokuService::GetDescriptor() {
   
  return descriptor();
}

通过ServiceDescriptor就可以获取service name,以及指向service所包含的methods各自对应的一个全局唯一MethodDescriptor常量实例的指针(const MethodDescriptor*)

class PROTOBUF_EXPORT ServiceDescriptor {
   
 public:
  ...

  // The name of the service, not including its containing scope.
  const std::string& name() const;
  // The fully-qualified name of the service, scope delimited by periods.
  const std::string& full_name() const;
  ...

  // The number of methods this service defines.
  int method_count() const;
  // Gets a MethodDescriptor by index, where 0 <= index < method_count().
  // These are returned in the order they were defined in the .proto file.
  const MethodDescriptor* method(int index) const;

  // Look up a MethodDescriptor by name.
  const MethodDescriptor* FindMethodByName(ConstStringParam name) const;
  ...
};
MethodDescriptor

通过MethodDescriptor可以获取method name,指向该method所属的service所对应的全局唯一ServiceDescriptor常量实例的指针(const ServiceDescriptor*),以及指向该method的input message和output message各自所对应的全局唯一Descriptor常量实例指针(const Descriptor*)

class PROTOBUF_EXPORT MethodDescriptor {
   
 public:
  ...

  // Name of this method, not including containing scope.
  const std::string& name() const;
  // The fully-qualified name of the method, scope delimited by periods.
  const std::string& full_name() const;
  ...
  
  // Gets the service to which this method belongs.  Never nullptr.
  const ServiceDescriptor* service() const;

  // Gets the type of protocol message which this method accepts as input.
  const Descriptor* input_type() const;
  // Gets the type of protocol message which this message produces as output.
  const Descriptor* output_type() const;

  ...
};
Descriptor
method

SolveSudokuService中唯一的method,它是个虚函数,需要业务来继承SudokuService这个类并且 override Solve方法,来实现业务逻辑(接受 request,set response)。done->Run()Closure是个纯虚类,需要RPC框架来实现)的时候应该要能把response序列化后返回给client(返回RPC响应报文)。

class SudokuServiceImpl : public SudokuService
{
   
 public:
  void Solve(::google::protobuf::RpcController* controller,
                       const ::sudoku
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值