根据“Defining Services”下的Google Protocol Buffer 文档,他们说,



据我了解, Protocol Buffer 并不是本地实现RPC的。相反,它们提供了必须由用户实现的一系列抽象接口(interface)(多数民众赞成!)。因此,我想利用ZeroMQ来实现这些抽象接口(interface)进行网络通信。

我正在尝试使用ZeroMQ创建RPC实现,因为我正在处理的项目已经为基本消息传递实现了ZeroMQ(因此,为什么我不按文档建议使用gRPC)。

彻底阅读了原始文档之后,我发现必须为自己的实现实现抽象接口(interface)RpcChannelRpcController

我已经构建了一个最小化示例,说明了我目前在RPC实现中所处的位置

.proto文件:为了简洁起见,省略了SearchRequest和SearchResponse模式

service SearchService {
    rpc Search (SearchRequest) returns (SearchResponse);
}

SearchServiceImpl.h :
class SearchServiceImpl : public SearchService {
 public:
  void Search(google::protobuf::RpcController *controller,
                    const SearchRequest *request,
                    SearchResponse *response,
                    google::protobuf::Closure *done) override {
    // Static function that processes the request and gets the result
    SearchResponse res = GetSearchResult(request);

    // Call the callback function
    if (done != NULL) {
    done->Run();
    }
    }
  }
};

MyRPCController.h :
class MyRPCController : public google::protobuf::RpcController {
 public:
    MyRPCController();

    void Reset() override;

    bool Failed() const override;

    std::string ErrorText() const override;

    void StartCancel() override;

    void SetFailed(const std::string &reason) override;

    bool IsCanceled() const override;

    void NotifyOnCancel(google::protobuf::Closure *callback) override;
 private:
  bool failed_;
  std::string message_;
};

MyRPCController.cpp -基于this
void MyRPCController::Reset() {  failed_ = false; }

bool MyRPCController::Failed() const { return failed_; }

std::string MyRPCController::ErrorText() const { return message_; }

void MyRPCController::StartCancel() { }

void MyRPCController::SetFailed(const std::string &reason) {
  failed_ = true;
  message_ = reason;
}

bool MyRPCController::IsCanceled() const { return false; }

void MyRPCController::NotifyOnCancel(google::protobuf::Closure *callback) { }

MyRPCController::ChiRpcController() : RpcController() { Reset(); }

MyRpcChannel.h :
class MyRPCChannel: public google::protobuf::RpcChannel {
 public:
    void CallMethod(const google::protobuf::MethodDescriptor *method, google::protobuf::RpcController *controller,
                    const google::protobuf::Message *request, google::protobuf::Message *response,
                    google::protobuf::Closure *done) override;
};

到目前为止,我对我的示例有疑问:
  • 我该在哪里适合ZeroMQ?
  • 似乎应该进入RPCChannel,因为在我看到的示例中(请参见第3个代码块here),它们传递了一个字符串,该字符串具有要绑定(bind)的端口(即MyRpcChannel channel("rpc:hostname:1234/myservice");)
  • 我担心我的RPCController实现,这似乎太简单了。应该再去这里吗?
  • 我如何实现RPCChannel,它看起来与SearchServiceImpl非常相似。这些类中的1虚拟函数具有通用的方法签名,非常相似。

  • 这是我遇到的其他一些Stack Overflow问题,其中包含有关该主题的一些有用信息:
  • Protobuf-Net: implementing server, rpc controller and rpc channel-这是我在其中找到RPCController实现的示例的地方。
  • Using Protocol Buffers for implementing RPC in ZeroMQ-这个答案很有趣,因为在最佳答案中,似乎建议他们不要使用.proto文件的RPC格式内置的Protobufs。
  • this存储库中的libpbrpc文件中,我也注意到了同样的想法,这对于例如
  • 代码来说似乎是一个很好的来源
  • 我可以/应该使用现有的实现(例如RPCZ)吗?

  • 感谢您的帮助。我希望我能提供足够的信息,并且清楚我要寻找的内容。如果有不清楚或缺乏信息的地方,请告诉我。我很乐意相应地编辑问题。

    最佳答案

  • ZeroMQ基于可包含任何数据的消息,提供了用于网络通信的低级API。
  • ProtoBuffers是一个库,用于将结构化数据编码为压缩的二进制数据,并对此类数据进行解码。
  • gRPC是一个RPC框架,可为基于网络通信的RPC服务生成代码,该服务具有将数据作为ProtoBuffers数据进行交换的功能。

  • ZeroMQ和gRPC均以不同方式为网络通信提供支持。您必须选择ZeroMQ或gRPC进行网络通信。
    如果选择ZeroMQ,则可以使用ProtoBuffers交换二进制结构化数据来对消息进行编码。

    要点是ProtoBuffers库允许对变体记录(类似于C/C++ union )进行编码和解码,这些变体记录可以完全模拟具有交换ProtoBuffers消息功能的RPC服务所提供的功能。

    因此,选项为:
  • 将ZeroMQ与发送和接收原语以及ProtoBuffers编码的变体消息一起使用,这些变体消息可以包含各种子消息,例如


  • 使用gRPC生成具有
  • 之类功能的服务



    (这里可以使用很多组合)
  • 仅使用单功能gRPC服务,例如



  • 该选项可能取决于

    客户端的
  • 首选目标:基于ZeroMQ或gRPC的客户端
  • 性能原因比较ZeroMQ与基于gRPC的服务
  • 特定功能,例如在ZeroMQ与基于gRPC的服务和客户端中如何使用/处理订阅(请参见How to design publish-subscribe pattern properly in grpc?)

  • 对于第一个选项,与第二个选项相比,您必须做很多事情。您必须将发送的消息类型与期望接收的消息类型进行匹配。

    如果其他人将开发客户端,则第二个选项将允许更轻松/更快地理解所提供服务的功能。

    为了在ZeroMQ的顶部开发RPC服务,我将定义.proto文件,以指定函数,参数(所有可能的输入和输出参数)和类似以下的错误:
    enum Function
    {
        F1 = 0;
        F2 = 1;
        F3 = 2;
    }
    
    enum Error
    {
        E1 = 0;
        E2 = 1;
        E3 = 2;
    }
    
    message Request
    {
        required Function function = 1;
        repeated Input data = 2;
    }
    
    message Response
    {
        required Function function = 1;
        required Error error = 2;
        repeated Output data = 3;
    }
    
    message Input
    {
        optional Input1 data1 = 1;
        optional Input2 data2 = 2;
        ...
        optional InputN dataN = n;
    }
    
    message Output
    {
        optional Output1 data1 = 1;
        optional Output2 data2 = 2;
        ...
        optional OutputN dataN = n;
    }
    
    message Message
    {
       repeated Request requests;
       repeated Response responses;
    }
    

    并根据功能ID,在运行时必须检查参数的数量和类型。

    关于c++ - 如何使用ZeroMQ为 Protocol Buffer 编写自己的RPC实现,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/59616929/

    10-13 03:33