Schema Registry 中的向后兼容性问题和不确定性
Backward Comaptibility issue and uncertainity in Schema Registry
我有一个用例,我有一个 JSON,我想生成架构并从 JSON 中记录并发布一条记录。
我已经配置了值序列化器并且架构设置是向后兼容的。
第一个JSON
String json = "{\n" +
" \"id\": 1,\n" +
" \"name\": \"Headphones\",\n" +
" \"price\": 1250.0,\n" +
" \"tags\": [\"home\", \"green\"]\n" +
"}\n"
;
版本 1 架构已注册。
在 avro 控制台消费者中收到消息。
第二个JSON.
String json = "{\n" +
" \"id\": 1,\n" +
" \"price\": 1250.0,\n" +
" \"tags\": [\"home\", \"green\"]\n" +
"}\n"
;
注册架构成功。
已发送消息。
现在尝试发送 JSON 1 发送成功
架构 3:
String json = "{\n" +
" \"id\": 1,\n" +
" \"name\": \"Headphones\",\n" +
" \"tags\": [\"home\", \"green\"]\n" +
"}\n"
;
遇到这种情况的错误。
Caused by: io.confluent.kafka.schemaregistry.client.rest.exceptions.RestClientException: 正在注册的模式与早期模式不兼容;错误代码:409
How is that schema generated from 2nd JSON was registered and the
third one was rejected? Although I didn't have any Default key for the
deleted field? Is it that the Schema Registry always accepts the 1st
evolution? (2nd schema over 1st)
模式注册表中的模式
版本 1 架构
{
"fields": [
{
"doc": "Type inferred from '1'",
"name": "id",
"type": "int"
},
{
"doc": "Type inferred from '\"Headphones\"'",
"name": "name",
"type": "string"
},
{
"doc": "Type inferred from '1250.0'",
"name": "price",
"type": "double"
},
{
"doc": "Type inferred from '[\"home\",\"green\"]'",
"name": "tags",
"type": {
"items": "string",
"type": "array"
}
}
],
"name": "myschema",
"type": "record" }
版本 2:
{
"fields": [
{
"doc": "Type inferred from '1'",
"name": "id",
"type": "int"
},
{
"doc": "Type inferred from '1250.0'",
"name": "price",
"type": "double"
},
{
"doc": "Type inferred from '[\"home\",\"green\"]'",
"name": "tags",
"type": {
"items": "string",
"type": "array"
}
}
],
"name": "myschema",
"type": "record" }
让我们回顾一下向后兼容规则...https://docs.confluent.io/current/schema-registry/avro.html#compatibility-types
首先,默认值是不可传递的,因此版本 3 只会查看版本 2。
向后规则规定您可以删除字段或添加可选字段(具有默认值的字段)。我假设您的模式生成器工具不知道如何使用可选值,因此您只能删除,不能添加。
在版本 1 和版本 2 之间,您删除了有效的名称字段。
在版本 2 和即将到来的版本 3 之间,它认为您正在尝试 post 一个删除价格的新模式(这没关系},但添加了一个必需的名称字段,这是不允许的。
我有一个用例,我有一个 JSON,我想生成架构并从 JSON 中记录并发布一条记录。 我已经配置了值序列化器并且架构设置是向后兼容的。
第一个JSON
String json = "{\n" +
" \"id\": 1,\n" + " \"name\": \"Headphones\",\n" + " \"price\": 1250.0,\n" + " \"tags\": [\"home\", \"green\"]\n" + "}\n" ;
版本 1 架构已注册。
在 avro 控制台消费者中收到消息。
第二个JSON.
String json = "{\n" +
" \"id\": 1,\n" + " \"price\": 1250.0,\n" + " \"tags\": [\"home\", \"green\"]\n" + "}\n" ;
注册架构成功。 已发送消息。
现在尝试发送 JSON 1 发送成功
架构 3:
String json = "{\n" +
" \"id\": 1,\n" + " \"name\": \"Headphones\",\n" + " \"tags\": [\"home\", \"green\"]\n" + "}\n" ;
遇到这种情况的错误。 Caused by: io.confluent.kafka.schemaregistry.client.rest.exceptions.RestClientException: 正在注册的模式与早期模式不兼容;错误代码:409
How is that schema generated from 2nd JSON was registered and the third one was rejected? Although I didn't have any Default key for the deleted field? Is it that the Schema Registry always accepts the 1st evolution? (2nd schema over 1st)
模式注册表中的模式
版本 1 架构
{ "fields": [
{ "doc": "Type inferred from '1'", "name": "id", "type": "int" }, { "doc": "Type inferred from '\"Headphones\"'", "name": "name", "type": "string" }, { "doc": "Type inferred from '1250.0'", "name": "price", "type": "double" }, { "doc": "Type inferred from '[\"home\",\"green\"]'", "name": "tags", "type": { "items": "string", "type": "array" } } ], "name": "myschema", "type": "record" }
版本 2:
{ "fields": [
{ "doc": "Type inferred from '1'", "name": "id", "type": "int" }, { "doc": "Type inferred from '1250.0'", "name": "price", "type": "double" }, { "doc": "Type inferred from '[\"home\",\"green\"]'", "name": "tags", "type": { "items": "string", "type": "array" } } ], "name": "myschema", "type": "record" }
让我们回顾一下向后兼容规则...https://docs.confluent.io/current/schema-registry/avro.html#compatibility-types
首先,默认值是不可传递的,因此版本 3 只会查看版本 2。
向后规则规定您可以删除字段或添加可选字段(具有默认值的字段)。我假设您的模式生成器工具不知道如何使用可选值,因此您只能删除,不能添加。
在版本 1 和版本 2 之间,您删除了有效的名称字段。
在版本 2 和即将到来的版本 3 之间,它认为您正在尝试 post 一个删除价格的新模式(这没关系},但添加了一个必需的名称字段,这是不允许的。