Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/147.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/visual-studio-2012/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 如何使用ZeroMQ为协议缓冲区编写自己的RPC实现_C++_Protocol Buffers_Zeromq_Rpc - Fatal编程技术网

C++ 如何使用ZeroMQ为协议缓冲区编写自己的RPC实现

C++ 如何使用ZeroMQ为协议缓冲区编写自己的RPC实现,c++,protocol-buffers,zeromq,rpc,C++,Protocol Buffers,Zeromq,Rpc,根据谷歌协议缓冲区文档,他们说 也可以在自己的RPC实现中使用协议缓冲区 据我所知,协议缓冲区并不以本机方式实现RPC。相反,它们提供了一系列必须由用户(那就是我!)实现的抽象接口。所以我想利用ZeroMQ实现这些抽象接口,用于网络通信 我正在尝试使用ZeroMQ创建RPC实现,因为我正在处理的项目已经实现了用于基本消息传递的ZeroMQ(因此,我没有按照文档建议使用gRPC) 在彻底阅读了proto文档之后,我发现我必须实现抽象接口和我自己的实现 我已经用我的RPC实现构建了一个我目前所处位置

根据谷歌协议缓冲区文档,他们说

也可以在自己的RPC实现中使用协议缓冲区

据我所知,协议缓冲区并不以本机方式实现RPC。相反,它们提供了一系列必须由用户(那就是我!)实现的抽象接口。所以我想利用ZeroMQ实现这些抽象接口,用于网络通信

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

在彻底阅读了proto文档之后,我发现我必须实现抽象接口和我自己的实现

我已经用我的RPC实现构建了一个我目前所处位置的最小化示例

.proto文件:为了简洁起见,省略了SearchRequest和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_;
};
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;
};
MyRPCController.cpp-基于

MyRpcChannel.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_;
};
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,因为在我看到的示例中(参见第三个代码块),它们传递一个字符串,该字符串具有要绑定的端口(即
      MyRpcChannel通道(“rpc:hostname:1234/myservice”);
  • 我关心我的RPCController实现,它似乎太简单了。这里应该有更多吗
  • 如何实现RPCChannel,它似乎与SearchServiceImpl非常相似。这些类中的1虚函数具有非常相似的方法签名,只是它是泛型的
下面是我遇到的一些其他堆栈溢出问题,这些问题提供了有关该主题的一些有用信息:

  • -这就是我找到RPCController实现示例的地方
  • -这个答案很有趣,因为在最上面的答案中,他们似乎建议不要在.proto文件中使用Protobufs内置的RPC格式。
    • 我在文件中也注意到了同样的概念,在一个名为的存储库中,这似乎是一个很好的源代码示例
  • 我是否可以/应该使用现有的实现,例如
  • 谢谢你的帮助。我希望我提供了足够的信息,并且清楚地知道我在寻找什么。请让我知道,如果有什么是不清楚或缺乏信息。我很乐意相应地编辑这个问题。

    • ZeroMQ基于可以包含任何数据的消息为网络通信提供了一个低级API
    • ProtoBuffers是一个库,它将结构化数据编码为压缩二进制数据并对这些数据进行解码
    • gRPC是一个RPC框架,它为基于网络通信的RPC服务生成代码,这些服务的函数将数据交换为ProtoBuffers数据
    ZeroMQ和gRPC都提供对网络通信的支持,但方式不同。您必须选择ZeroMQ或gRPC进行网络通信。 如果选择ZeroMQ,则可以使用交换二进制结构化数据的ProtoBuffers对消息进行编码

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

    因此,选择是:

  • 将ZeroMQ与发送和接收原语以及ProtoBuffers一起使用,这些原语和ProtoBuffers编码的变体消息可以包含各种子消息,如
  • 使用gRPC生成具有如下功能的服务
  • (这里可以使用多种组合)

  • 只使用单一功能的gRPC服务,如
  • 这一选择可能取决于

    • 客户端的首选目标:ZeroMQ或基于gRPC的客户端
    • 比较ZeroMQ与基于gRPC的服务的性能原因
    • 特定功能,如ZeroMQ与基于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的不同,在运行时必须检查参数的数量和类型。

    Hi Flaviu,感谢您抽出时间写出所有这些。这里有很多好信息。我一直坚持使用ZeroMQ和协议缓冲区,而不是gRPC,因为我们的项目已经使用了ZeroMQ,他们不想实现另一个网络。因此,我一直在尝试探索如何正确地集成协议缓冲区提供的RPC抽象接口,以及如何使用ZeroMQ.Hi和welcome实现它们。因此,您希望在ZeroMQ之上有一个RPC服务。为此,必须定义两个协议,一个用于指定RPC内容(函数id、参数编号、可能发生的错误),另一个用于指定RPC函数交换的消息(参数)。请看一下XML-RPC()和JSON-RPC()。基于这样的RPC定义,您可以编写一个包含RPC和消息的.proto文件——我想这是最困难的部分。然后生成ProtoBuffers代码,然后将其集成到ZeroMQ项目中。感谢您的回复。据我所知,我不使用Xml RPC或Json RPC,而是认为我可以利用Protobufs实现同样的功能。通读他们的
    service MyService 
    {
      rpc function1(MessageType1) returns (Response);
      rpc function2(MessageType2) returns (Response);
      rpc function3(MessageType3) returns (Response);
    
      rpc functionN(MessageType3) returns (MessageType5);
    }
    
    service MyService 
    {
        rpc function(Request) returns (Response);
    }
    
    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;
    }