【问题标题】:Avro union: forward compatibility?Avro union:前向兼容性?
【发布时间】:2019-01-30 11:15:15
【问题描述】:

我们的系统由多个微服务组成,它们发出和使用以 avro 格式编码的事件(参见底部的架构)。一个特定的用例如下:服务 A 在主题 T1 上发出一个事件(类型为 InvoiceEvents),服务 B 和 C(不同的开发团队)正在从 T1 消费。例如。服务 B 属于税务团队,而服务 C 属于产品履行团队。

我期待以下是真的(但似乎不是):

  1. 通过添加新的联合类型(即为字段“有效负载”创建 InvoiceCreated),架构可以从版本 1 (v1) 演变为版本 2 (v2) - 查看底部的示例架构。
  2. 生产服务 A 升级到 v2(即生产遵循 v2 的事件)
  3. 一些消费服务(例如服务 C)仍然可以使用 v1,因为它们对新的事件类型(例如 InvoiceCreated)不感兴趣。在这种情况下,“有效负载”字段在反序列化时将使用默认(空)值。
  4. 最终且仅在出于业务原因需要时,服务 C 才能升级到使用 v2,如果需要对新事件类型(即 InvoiceCreated)做出反应。

但服务 C 无法反序列化 InvoiceCreated 类型的新事件。具体来说就是抛出:

org.apache.avro.AvroTypeException: Found com.elsevier.q2c.schema.avro.invoice.InvoiceCreated, expecting unionorg.apache.avro.AvroTypeException: Found com.elsevier.q2c.schema.avro.invoice.InvoiceCreated, expecting union at org.apache.avro.io.ResolvingDecoder.doAction(ResolvingDecoder.java:292) at 

avro 联合​​类型是否不向前兼容(如上所述)?它们是否仅像 Confluent Schema Registry tests 所暗示的那样向后兼容。避免微服务耦合的建议方法是什么?我猜无法使用 avro unions..

谢谢!!

没有明确答案的相关链接:Avro-union-compatibility-mode-enhancement-proposal


架构 v1:

[
   ...
   {
      "type":"record",
      "name":"InvoiceEvents",
      "namespace":"bla.bla.schema.avro.invoice",
      "fields":[
         {
            "name":"payload",
            "type":[
               "null",
               "bla.bla.schema.avro.invoice.InvoiceDrafted"
            ],
            "default":null
         }
      ]
   }
]

schema v2(添加了新的联合类型:InvoiceCreated):

[
   ...
   {
      "type":"record",
      "name":"InvoiceEvents",
      "namespace":"bla.bla.schema.avro.invoice",
      "fields":[
         {
            "name":"payload",
            "type":[
               "null",
               "bla.bla.schema.avro.invoice.InvoiceDrafted",
               "bla.bla.schema.avro.invoice.InvoiceCreated",
            ],
            "default":null
         }
      ]
   }
]

【问题讨论】:

  • Avro specification 表示如果所选作者的联合模式不是读者联合中的模式之一,则发出错误信号。
  • 确实在联合中添加新类型是不向前兼容的更改

标签: avro confluent-schema-registry


【解决方案1】:

经过一番思考,我们可能会选择选项 3,因为不跳过/丢失事件对项目来说比解耦更重要:

  1. 在自定义反序列化器和跳过事件中处理异常(可能会丢失有趣的事件 - 为了不丢失事件,所有消费服务必须在所有生产服务之前升级)
  2. 将所有自定义记录联合转换为单独的可选字段(可能会丢失有趣的事件,因为更改是前向兼容的,并且消费服务不会阻塞)
  3. 在所有使用新自定义记录类型架构的消费服务中接受反序列化错误/块消费和碰撞版本(这保证不会丢失任何有趣的事件)。

如果有更好的选择,请发表评论,我错过了!

更新: 似乎选项 (2) 现在可以以更简洁的方式实现,因为现在您可以拥有多种类型的主题 (https://github.com/confluentinc/schema-registry/pull/680)。这意味着一个主题可以有不同的值类型(例如 InvoiceCreated、InvoiceEdited 等),而无需使用 avro 联合​​,而每种不同的类型都有自己的演变路线!

【讨论】:

    猜你喜欢
    • 2021-08-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-12-11
    相关资源
    最近更新 更多