在 ZeroMQ 中使用协议缓冲区实现 RPC

Posted

技术标签:

【中文标题】在 ZeroMQ 中使用协议缓冲区实现 RPC【英文标题】:Using Protocol Buffers for implementing RPC in ZeroMQ 【发布时间】:2017-12-30 22:43:35 【问题描述】:

我有一个客户端和一个服务器的简单设置。客户端希望使用 ZeroMQ 在服务器中执行一个方法进行通信。我将使用 REQ 和 REP 套接字,因为它们适用于这个用例。不过,我对 protobuf 的定义有疑问。我认为这两个选项可以用来实现目标:

message ControlService
    string control = 1;
    int32 serverId = 2;
    bool block = 3;
    double temperature = 4;

其中“控制”包含要远程执行的方法的名称。另一种选择是:

message InputParameters
    int32 serverId = 1;
    bool block = 2;
    double temperature = 3;

message Empty


service ControlService
    rpc control (InputParameters) returns (Empty);

最好的方法是什么?或者至少使用一种方法而不是另一种方法的权衡是什么?

【问题讨论】:

【参考方案1】:

不要那样做。留言:

message InputParameters
    req oneof
    
        InputParametersA a = 1;
        InputParametersB b = 2;
    

message InputParametersA

    bool block = 1;
    float temperature = 2;

message InputParametersB

    <more fields>

这样你只发送 InputParameters 消息。调用的方法取决于 InputParameters.req 是否包含 InputParametersA(暗示应该调用方法 A)或 InputParmetersB(对于方法 B)。

这避免了解析字符串以确定方法名称(极易出错),而是为您提供了一个枚举以打开(req 字段的可能内容)。根据您使用的 GPB 的实现(C++ 等),如果您的 switch 语句没有充分覆盖该枚举的所有值,您甚至可能会收到编译时警告。

这也意味着在确定应该将哪些字段传递给方法时没有问题;您将 InputParameters.req.a 传递给方法 A 或 .b 传递给方法 B。无需将它们分解为方法的单独参数,只需将整个内容作为单个参数传递即可。

您可以以相同的方式定义不同的返回类型,通过单个oneof 将它们全部传回。

替代品

现在,如果您使用的是 ASN.1(在概念上与 GPB 类似),您可以对消息字段的值和/或大小设置限制(请参阅 here, Chapter 13 in this PDF。这样您就可以自动执行参数验证,仅在 ASN.1 模式中定义。GPB 中缺少值/大小约束是一个明显的遗漏。

看看here (overview)、here (free schema compiler for C/C++ that looks OK)和here (PDF, reference manual)。

ASN.1 在其有线格式中具有更强的键入能力(如果您使用 BER 编码)。可以询问有线比特流以找出它包含的消息类型。因此,无需像使用 GPB 那样将所有可能的消息包装到单个 oneof 中。

【讨论】:

以上是关于在 ZeroMQ 中使用协议缓冲区实现 RPC的主要内容,如果未能解决你的问题,请参考以下文章

Windows 上的 Thrift / Google 协议缓冲区

《RPC 应用与原理概述》之入门介绍

使用命名管道承载gRPC

如何使用非平凡(POD)类的缓冲区协议实现 pybind11

.NET使用命名管道承载gRPC

RPC、套接字和性能注意事项