Kafka Avro反序列化报错:Found string, expecting union 问题咨询
背景信息
在Spring Java项目消费Kafka Topic时,遭遇io.confluent.kafka.serializers.KafkaAvroDeserializer抛出的反序列化错误。项目依赖版本如下:
<dependency> <groupId>org.apache.avro</groupId> <artifactId>avro</artifactId> <version>1.10.1</version> </dependency> <dependency> <groupId>io.confluent</groupId> <artifactId>kafka-avro-serializer</artifactId> <version>7.2.1</version> </dependency>
上述版本虽非最新,但在生产环境消费其他Topic时运行正常。
问题详情
报错信息:
Caused by: org.apache.avro.AvroTypeException: Found string, expecting union
at org.apache.avro.io.ResolvingDecoder.doAction(ResolvingDecoder.java:308)
at org.apache.avro.io.parsing.Parser.advance(Parser.java:86)
at org.apache.avro.io.ResolvingDecoder.readIndex(ResolvingDecoder.java:275)
at org.apache.avro.generic.GenericDatumReader.readWithoutConversion(GenericDatumReader.java:187)
发送到Topic的消息所有字段均为非空字符串,有同事建议给每个字段添加default:"",示例如下:
{ "name": "namespace_Fld1", "type": [ "string", "null" ], "default": "" },
但不确定该方案是否有效,因为消息中并无空字段。
经排查,Writer Schema与Reader Schema存在不匹配:
Writer Schema:
{"type":"record", "name":"myClassName", "namespace":"fr.laposte.bdl.bscc.myClassName", "fields": [ {"name":"namespace_Fld1", "type":["string","null"]}, {"name":"namespace_Fld2", "type":["string","null"]}, {"name":"namespace_Fld3", "type":["string","null"]}, {"name":"namespace_Fld4", "type":["string","null"]}, {"name":"namespace_Fld5", "type":["string","null"]}, {"name":"namespace_Fld6", "type":["string","null"]}, {"name":"namespace_Fld7", "type":["string","null"]}, {"name":"namespace_Fld8", "type":["string","null"]}, {"name":"namespace_Fld9", "type":["string","null"]} ], "default":null }
Reader Schema:
"type": "record", "name": "myClassName", "namespace": "fr.laposte.bdl.bscc.myClassName", "fields": [ { "name": "namespace_Fld4", "type": [ "string", "null" ] }, { "name": "namespace_Fld5", "type": [ "string", "null" ] }, { "name": "namespace_Fld7", "type": [ "int", "null" ] }, { "name": "namespace_Fld8", "type": [ "string", "null" ] } ] }
Reader Schema字段顺序与Writer不同,且发送方曾发布并删除过该Schema的旧版本。
问题解答
1. 是否需要调整我的Reader Schema?
必须调整。核心问题出在namespace_Fld7的类型不匹配:Writer Schema中该字段是["string", "null"],但Reader Schema里定义成了["int", "null"]。这直接导致反序列化时,读取到字符串类型的值,却期望是包含int的联合类型,触发了报错。字段顺序不是问题,Avro是按字段名进行映射匹配的,和顺序无关。
2. 是否可能存在Avro缓存问题?
有可能。如果发送方曾删除过旧版本Schema,Schema Registry或消费端本地可能存在旧Schema的缓存,导致消费端拉取到错误的Schema进行反序列化;另外,本地项目生成的Avro类文件如果是基于旧Schema生成的,也可能引发缓存问题。不过优先解决Schema本身的类型错误,再排查缓存问题。
3. 需要对我的AVRO Reader Schema进行哪些操作?
- 修正类型错误:将
namespace_Fld7的类型改为和Writer Schema一致的["string", "null"],这是解决当前报错的关键。 - 可选添加默认值:给字段添加
default:""(字符串类型)或对应类型的默认值,虽然当前消息无空字段,但添加默认值能提升Schema的兼容性,后续如果出现字段为空的情况,不会触发反序列化错误。 - 无需调整字段顺序:Avro通过字段名匹配,字段顺序不影响反序列化结果。
- 排查缓存(若需要):如果修正Schema后仍报错,可重启消费服务,清理本地Avro类缓存;若使用Schema Registry,可确认Registry中存储的Writer Schema版本是否正确,必要时刷新Registry缓存。
内容的提问来源于stack exchange,提问作者Kris

