使用Protocol Buffers在ZeroMQ中实现RPC

时间:2017-12-30 22:43:36

标签: protocol-buffers zeromq

我有一个客户端和一个服务器的简单设置。客户端希望使用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 个答案:

答案 0 :(得分:4)

不要这样做。有个消息:

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。那样你' d自动执行参数验证,仅在ASN.1模式中定义.GPB中缺少值/大小限制是一个明显的遗漏。

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

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