如果字段顺序更改,Avro 架构不兼容

2024-01-06

设想 - 客户端使用 Avro Reflect Datum Writer 序列化 POJO 并将 GenericRecord 写入文件。 通过反射获得的模式是这样的(注意顺序A、B、D、C)-

{
"namespace": "storage.management.example.schema",

"type": "record",
"doc": "Example schema for testing",
"name": "Event",
"fields": [
     ....
     ....
    { "name": "A", "type":  "string"  },
    { "name": "B", "type":  "string"  },
    { "name": "D", "type": "string" },
    { "name": "C", "type":  "string"  },
     ....
     ....
]
} 

代理读取文件并使用默认模式(注意顺序 - A、B、C、D)来反序列化记录的子集(保证客户端拥有这些字段)

{
"namespace": "storage.management.example.schema",
"type": "record",
"doc": "Example schema for testing",
"name": "Event",
"fields": [
    { "name": "A", "type":  "string"  },
    { "name": "B", "type":  "string"  },
    { "name": "C", "type": "string" },
    { "name": "D", "type":  "string"  }
]
}

问题 : 使用上述子集模式的反序列化会导致以下异常 -

Caused by: java.io.IOException: Invalid int encoding
at org.apache.avro.io.BinaryDecoder.readInt(BinaryDecoder.java:145)
at org.apache.avro.io.BinaryDecoder.readString(BinaryDecoder.java:259)
at org.apache.avro.io.ResolvingDecoder.readString(ResolvingDecoder.java:201)
at org.apache.avro.generic.GenericDatumReader.readString(GenericDatumReader.java:430)
at org.apache.avro.generic.GenericDatumReader.readString(GenericDatumReader.java:422)
at org.apache.avro.generic.GenericDatumReader.readWithoutConversion(GenericDatumReader.java:180)
at org.apache.avro.generic.GenericDatumReader.read(GenericDatumReader.java:152)
at org.apache.avro.generic.GenericDatumReader.readField(GenericDatumReader.java:240)
at org.apache.avro.generic.GenericDatumReader.readRecord(GenericDatumReader.java:230)

但是,如果子集模式还按 A、B、D、C 的顺序指定字段,则反序列化会成功。(与客户端模式相同)

这种行为是预期的吗?我认为 Avro 仅依赖于字段名称来构建记录,而不依赖于排序。

有什么解决办法吗?不同的客户端可能有不同的顺序,我无法强制排序,因为模式是通过反射生成的。


这不一定是预期的行为。您可能会犯与我开始使用 Avro 时所犯的错误相同的错误。

Avro 能够拥有不同版本的模式(例如,用一个模式写入但读入另一个模式),但很容易错过的一件事(至少我自己)是您必须拥有尝试读取消息时写入消息的确切架构。

您阅读的有关 Avro 的文档和信息(至少在表面上)并没有非常清楚地说明这一点。通常他们关注它的“向后兼容”。公平地说,从某种意义上来说是这样,但通常当人们看到这个短语时,他们会认为它的含义有点不同。通常我们认为这意味着您可以使用新模式处理旧消息,而不是使用新模式处理旧消息和旧消息的架构。

作为示例,请参阅此伪代码

Schema myUnsortedSchema has C B A order
Schema myAlphabeticalSchema has A B C order

Writer writer uses myUnsortedSchema
Reader badReader uses myAlphabeticalSchema only

writer writes message
badReader reads message

错误!不确定错误消息到底会说什么,但问题是badReader不仅尝试阅读myAlphabeticalSchema还可以阅读该消息,就好像它是由myAlphabeticalSchema。解决方案是有一种方法可以为其提供两种模式,一种是写入消息的模式,另一种是要读取的模式(具体方式取决于语言)。

Reader goodReader reads messages written with myUnsortedSchema into myAlphabeticalSchema

goodReader reads message

没有错误!这是正确的用法。

如果您使用类似的方法goodReader那么这种行为是意外的,但是如果您使用类似的方法badReader那么该行为是预期的。


某些服务(例如架构注册表)可以通过将一些元数据附加到消息字节的前面来确定哪个架构写入了消息(当然,并在读取之前将其剥离)来帮助解决此问题。这超出了问题的范围,但可以帮助解决这样的问题。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

如果字段顺序更改,Avro 架构不兼容 的相关文章

  • SPNEGO 密码身份验证问题

    我已将我的应用程序配置为通过 SPNEGO 与 Websphere 使用 Kerberos 身份验证 这是详细信息 krb5 conf libdefaults default realm ABC MYCOMPANY COM default
  • 从文本文件中读取阿拉伯字符

    我完成了一个项目 在该项目中我读取了用记事本编写的文本文件 我的文本文件中的字符是阿拉伯语 文件编码类型是UTF 8 当在 Netbeans 7 0 1 中启动我的项目时 一切似乎都正常 但是当我将项目构建为 jar 文件时 字符以这种方式
  • 将 MouseListener 添加到面板

    我正在尝试将鼠标操作添加到我的面板中 这就是程序应该做的事情 编写一个程序 允许用户通过按三下鼠标来指定一个三角形 第一次按下鼠标后 画一个小点 第二次按下鼠标后 绘制一条连接前两个点的线 第三次按下鼠标后 绘制整个三角形 第四次按下鼠标会
  • 从 Spring MVC XML 文件转移到 javaconfig。我真的对我的数据库 XML 文件感到困惑

    我从 Spring MVC XML 文件转移到 javaconfig 我真的对我的数据库 XML 文件感到困惑 我不知道如何让 Hibernate4 工作以及我的 JBoss JNDI 数据源工作 有人可以告诉我如何使 javaconfig
  • Java 卡布局。多张卡中的一个组件

    一个组件 例如JLabel 在多张卡中使用CardLayout 目前看来该组件仅出现在它添加到的最后一张卡上 如果有办法做到这一点 我应该吗 这是不好的做法吗 或者有其他选择吗 你是对的 它只出现在 添加到的最后一张卡 中 但这与CardL
  • Spring中的ProxyFactoryBean

    有人可以解释一下吗代理工厂Bean http static springsource org spring docs current javadoc api org springframework aop framework ProxyFa
  • JavaFX使节点覆盖父节点边框颜色

    我有一个如下所示的节点 仅使用 css 我希望标签覆盖其父边框颜色 因此标签下方的边框颜色部分变得不可见 我用来制作这个边框的CSS代码 fx border color black fx border width 3 fx border r
  • 可访问数据的 Java 约定。 (公共访问器和 Getter/命名)

    通过 Java API 您会看到大量冲突的命名和实践 这让我感到非常困惑 例如 The String http grepcode com file repository grepcode com java root jdk openjdk
  • 生成 equals 和 hashcode 时忽略属性

    假设我有一个类 Customer public class Customer private String firstName private String lastName private String doNotAddMeToEqual
  • 用于层次结构树角色的 Spring Security / Java EE 解决方案

    我知道 Spring Security 非常适合标准角色和基于权限的授权 我不确定的是这种情况 系统中管理着 10 000 名员工 员工被组织成组织结构图 跨部门的谁向谁报告的树 其中一些员工是用户 这些用户仅被允许访问其职责范围内的员工
  • 正确签名的 JNLP 应用程序无法在 Java 7 中运行

    我有一个 JNLP 应用程序 由于证书过期需要更新 我有一个经过 CA 验证的新证书 我已将新证书导入到我的密钥库中 我已导入完整的证书链 我的构建文件对构建中的 jar 进行签名和时间戳
  • 在带有 Protocol Buffers 的项目中使用 Proguard 有什么特点?

    我有一个使用 Google Protocol Buffers 的项目 一旦我尝试用 ProGuard 对其进行混淆 似乎 protobuf 会导致问题 我将所有自己的类打包成mybuildedclasses jar 谷歌代码被打包成prot
  • JUNIT 测试 void 方法

    我有一个充满 void 方法的 java 类 我想进行一些单元测试以获得最大的代码覆盖率 例如我有这个方法 protected static void checkifValidElements int arg1 int arg2 metho
  • 如何从intellij项目视图中隐藏不必要的文件?

    给定一个示例 gradle 项目 其项目结构如下所示 正如你所看到的 有很多东西你实际上不需要在想法中看到 但你需要它们存在 我知道下面被忽略的文件 文件夹类型Editor File Types但这些正在影响库和项目 idea 会在各处忽略
  • 删除 JFX 中选项卡后面的灰色背景

    So is there any way to remove the gray area behind the tab s 我尝试过用 CSS 来做到这一点 但没有找到方法 要设置 tabpane 标题的背景颜色 请在 CSS 文件中写入 t
  • 如何使用Gson仅从Json反序列化某些特定字段?

    我有以下 JSON 字符串 channel bvmt initValues data value instrumentIds TN0007250012 TN0007500010 instruments mnemonic ADWYA marc
  • 使用 PC/SC 读卡器验证 Ultralight EV1

    我在尝试使用 Java 中的 PC SC 读卡器 特别是 ACR1222L 验证 Ultralight EV1 卡时遇到问题 我能够使用 ISO 14443 3 标签的相应 APDU 在不受保护的标签上进行写入和读取 但是 我找不到运行 P
  • 如何从 JavaFX 中的另一个控制器类访问 UI 元素?

    我有一个使用 NetBeans 8 编写的 JavaFX Java 8 应用程序 没有SceneBuilder 我的应用程序有一个主窗口 该窗口有自己的 FXML 文件 primary fxml 和自己的控制器类 FXMLPrimaryCo
  • 如何使用自定义 JDK 构建 Jenkins 项目?

    我有一个常规的 Jenkins 实例 运行一些多分支管道 该实例在 JDK 11 上运行 因为 Jenkins 并不真正支持更高版本 没关系 但不好的是 我的所有管道似乎也都受到 Java 11 的限制 Jenkins 仅使用它自己也使用的
  • 如何建立与 FileZilla Server 1.2.0 的 FTPS 数据连接

    使用 Apache commons net 的 Java FTPSClient 进行会话恢复是一个已知问题 会话恢复是 FTPS 服务器数据连接所需的一项安全功能 Apache FTPSClient 不支持会话恢复 并且 JDK API 使

随机推荐