我正在考虑使用Google Protobuffers进行增量消息传递。这意味着我只想发送我的域对象的更改值。
但这暴露了用于此目的的协议的问题。我可以轻松地省略未更改的属性,这将为我们提供紧凑的消息。
但是,将值从_something_
更改为null
的属性呢?无法在协议缓冲区中区分这两种方案。
其他人在这里做了什么?我正在寻找几种不同的解决方案:
-
向所有对象添加一个元属性,即 int 数组。如果任何属性应更改为 null,请在此数组中包含字段编号。如果没有属性更改,则只是省略 meta 属性,并且不会占用消息中的带宽。
-
添加一个位掩码的元属性,但工作原理类似于选项 1 中提到的数组。不过,这对客户来说可能更难理解。
-
使用我尚未找到的标准方式。
BR 周杰伦
Protobuf 3不太适合这个。但是在 protobuf 2 中,你可以有一个存在但值为 null 的字段。
因为protobuf 2不会很快消失,所以我建议将其用于这种目的。
我只是想就此发布后续文章并解释我所做的事情。
正如@jpa正确指出的那样,原型缓冲区不是为增量压缩而制造的。
所以我解决这个问题的方法是使用一些元属性并依赖该约定。我与使用数据的人有着密切的合作关系,因此可以就约定达成一致。
-
专门设置为 null 的值
我在消息中添加了一个 int 数组。此 int 数组大部分时间为空,对消息大小没有影响。当属性设置为 null 时,我会将属性标记添加到此数组中,并以这种方式指示它已在该消息更新中专门设置为 null。
-
清空的数组
其工作方式与 nulls 数组相同。我在消息中添加了一个 int 数组。此 int 数组大部分时间为空,对消息大小没有影响。当一个数组被清空时,我将向这个数组添加属性标签,并以这种方式指示它已被专门清空该消息更新。
-
已删除的对象
为了指示对象已被删除,我添加了一个布尔属性,指示该对象已被删除。删除对象时,我会将此值设置为 true,否则设置为 null,因此它不会占用消息中的空间。生成的消息是该对象的密钥标识符和指示该对象已删除的布尔值。
它要求客户端理解约定,但除此之外它工作得很好。