Avro Union:向前兼容吗?

时间:2019-01-30 11:15:16

标签: avro confluent-schema-registry

我们的系统由多个微服务组成,这些微服务发出和使用以avro格式编码的事件(请参阅底部的架构)。以下是一个特定的用例:服务A发出有关主题T1的事件(类型为InvoiceEvents),服务B和C(不同的开发团队)正在使用T1。例如。服务B是税务小组的一部分,而服务C是产品执行小组的一部分。

我期望以下是正确的(但似乎并非如此):

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

但是服务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联合。.

谢谢!

没有明确答案的相关链接: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
         }
      ]
   }
]

模式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
         }
      ]
   }
]

1 个答案:

答案 0 :(得分:0)

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

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

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