Kafka在消费者反序列化时出现问题

Kafka在消费者反序列化时出现问题

问题描述

今天在启动Kafka时,出现了一些问题。Kafka启动后,卡在了某一消费点,报

Missing exception handling for deserialization of key values,提示缺少对键值反序列的异常处理,并且系统一直重复反序列化该调记录,一直失败,陷入死循环。

上网查询解决办法发现这种现象是当生产者序列化程序和消费者反序列化程序不兼容时产生的一种毒丸场景。在以下场景可能会发生毒丸现象:

  • 生产者更改了键或值序列化器,并继续将数据生产到同一Kafka主题。这给该主题的所有消费者带来了反序列化问题。

  • 使用者配置了错误的key或值反序列化器。

  • 不同的生产者使用不同的键或值序列化程序,开始生产有关Kafka主题的记录。

在发生这种情况后如果不处理将会产生很大的影响:

  • 消费者应用程序正在使用Kafka主题。

  • 在某个时间点,应用程序无法对记录进行反序列化(遇到毒丸)。

  • 消费者不能处理毒丸。

  • 因为使用者偏移量没有向前移动,所以阻止了主题分区的使用。

  • 消费者将一次又一次地(非常迅速地)尝试反序列化记录,但是永远不会成功。因此,您的消费者应用程序将陷入一个无穷循环,尝试对失败的记录进行反序列化。

  • 对于每次失败,都会在您的日志文件中写入一行。

解决过程

Kafka提供了ErrorHandlingDeserializer用来解决上述问题。

 

在配置文件中配置

spring.kafka.consumer.key-deserializer=org.springframework.kafka.support.serializer.ErrorHandlingDeserializer spring.kafka.consumer.value-deserializer=org.springframework.kafka.support.serializer.ErrorHandlingDeserializer

(当反序列化失败时,.ErrorHandlingDeserializer会去调用ErrorHander去捕获异常,并把异常信息打印在控制台上)

以及

spring.kafka.consumer.properties.spring.deserializer.key.delegate.class=org.apache.kafka.common.serialization.StringDeserializer spring.kafka.consumer.properties.spring.deserializer.value.delegate.class=org.springframework.kafka.support.serializer.JsonDeserializer(消费者实际的反序列化配置)

配置了ErrorHandlingDeserializer后,系统将不会阻塞在反序列化异常的消费点上,而是将异常捕获打印后,继续运行程序。Kafka还提供了

ErrorHandlingDeserializer与DeadLetterPublishingRecoverer,SeekToCurrentErrorHandler组合使用将死信记录发布到死信主题上进行保存,方便后期排查问题。

在配置了ErrorHandlingDeserializer后,再次启动Kafka,发现问题变成了is not in the trusted packages: If you believe this class is safe to deserialize, please provide its name. If the serialization is only done by a trusted source, you can also enable trust all (*).提示要被反序列化的消息类不在被信任的包内。这个问题其实是因为自定义消息在默认情况下是被Kafka信任的,解决办法是在配置文件中添加需要被信任包的路径:spring.kafka.consumer.properties.spring.json.trusted.packages=xxx。其实这个问题以前就已经处理了,在一开始还没想明白为什么还会出这个问题,我就把信任路径直接设置为**,表示信任全部路径下的包。

再次运行后发现报错信息又变了,改为failed to deserialize; nested exception is org.springframework.messaging.converter.MessageConversionException: failed to resolve class name. Class not found

找不到要加载的类,仔细观察后,发现提示找不到该路径下对应的类。

然后突然想起来公司最近对这个Kafka进行了一次重构操作,新老版本没有去区分开,而是共用了一个Kafka,然而里面的消息类的路径又发生了一些改变,所以在运行新版本项目里的Kafka时,读取到了一些旧版本项目里的Kafka消息,消费者无法对消息进行正常的反序列化而导致的异常。找到问题后,进行处理,系统便能正常运行了。

问题总结

项目在运行时总会遇到一些奇怪的问题,而避免这些问题的最好方法应该是合理规范的开发,例如这次的问题就出在系统重构时,没有将两个项目的Kafka独立使用,而是共用一个Kafka导致出现问题。所以在开发中,解耦还是非常重要的,做到尽量不要将关联性不大的东西耦合在一起。

  • 1
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
要将Flink从Kafka消费的数据反序列化并存入Hive,可以按照以下步骤进行操作: 1. 配置Kafka消费者和Hive连接 首先需要配置Flink的Kafka消费者和Hive连接,可以使用Flink提供的Kafka连接器和Hive连接器来实现。具体的配置可以参考Flink官方文档进行设置。 2. 设计反序列化类 根据你从Kafka消费的数据格式,需要设计一个反序列化类来将数据转换为Flink中的对象。例如,如果你从Kafka消费的是JSON格式的数据,可以使用Flink提供的JSON反序列化类进行转换。 3. 定义Hive表结构 在Hive中创建一个表来存储反序列化后的数据。你需要定义表的结构,包括列名、列类型和分区等信息。 4. 编写Flink程序 编写一个Flink程序来消费Kafka中的数据,并将数据反序列化后存入Hive表中。具体的实现可以参考以下代码示例: ```java DataStream<String> dataStream = env.addSource(new FlinkKafkaConsumer<String>( "topic", new SimpleStringSchema(), properties)); DataStream<MyObject> myObjects = dataStream.map(new MapFunction<String, MyObject>() { @Override public MyObject map(String value) throws Exception { ObjectMapper mapper = new ObjectMapper(); return mapper.readValue(value, MyObject.class); } }); HiveCatalog hiveCatalog = new HiveCatalog("myHiveCatalog", "default", "/path/to/hive/conf"); TableSchema schema = new TableSchema( new String[] {"id", "name", "age"}, new TypeInformation<?>[] {Types.STRING, Types.STRING, Types.INT}); HiveTableSink hiveTableSink = new HiveTableSink( "myDatabase.myTable", schema, hiveCatalog, new Configuration(), "myPartition"); myObjects.addSink(hiveTableSink); ``` 其中,`MyObject`是你从Kafka消费的数据反序列化后的对象,`hiveCatalog`是Hive连接器的配置信息,`schema`是Hive表的列信息,`hiveTableSink`是Hive表的输出目的地。 5. 运行Flink程序 配置好Flink程序后,就可以运行程序了。程序会从Kafka消费数据,将数据反序列化后存入Hive表中。 以上就是将Flink从Kafka消费数据反序列化存入Hive的步骤和示例代码。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值