如何使必填的 thrift 字段可选?

How do I make a required thrift field optional?

在 thrift 中制作 required 字段 optional 的最佳过程是什么。例如,我有一个结构...

struct Message {
    1: required double userID;
    2: required string content;
    ...
} 

...但我想让 content 可选。

编辑:澄清一下,我已经有使用此结构的消费者,因此我需要在不破坏这些消费者的情况下更新它。分阶段升级很好(即 ​​- 添加新的 optional 字段,更新下游客户端,然后删除或停止使用旧的 required 字段)。

你不能,因为俗话说要的是永远。以下引自 Diwaker Gupta 的极力推荐"Missing Guide"。它几乎明确了为什么在使用 required:

之前应该(至少)三思而后行

Required Is Forever

You should be very careful about marking fields as required. If at some point you wish to stop writing or sending a required field, it will be problematic to change the field to an optional field — old readers will consider messages without this field to be incomplete and may reject or drop them unintentionally. You should consider writing application-specific custom validation routines for your buffers instead. Some have come the conclusion that using required does more harm than good; they prefer to use only optional. However, this view is not universal.

恐怕唯一的选择是弃用整个结构并创建一个新结构。

除此之外,其实还有三个需求度,其中只有两个有关键字:

  • required:读取时必须存在,写入时必须设置
  • optional:可以设置也可以不设置,完全可选
  • "default":读取时可能不存在,总是写入(除非它是 null 指针)

requiredoptional 均未指定时,将隐式应用 "default" 要求。

如果我们查看事物的兼容性站点,可以清楚地看到,required 的限制是相当严格的。即使向结构添加新的 required 字段也可能导致不兼容,例如如果新客户端正在从旧服务器读取数据(反之亦然),因为新的 required 字段不在旧 impl 写入的数据中,而是新 impl 所期望的。

如果您通过以下步骤控制该结构的所有读写器,就可以做到这一点:

  1. 将 thrift 架构中的字段从必需更改为可选。在引用或使用此结构的所有系统中同步此新模式。不要停止写这个字段。这是一个安全的更改,因为该字段将始终存在。
  2. 只有在使用该结构的所有系统中都部署了模式更改后,在某些情况下才能停止写入该字段。现在这样做是安全的,因为该字段在每个系统中都被标记为可选,没有其他答案中提到的“老读者”。