简体   繁体   English

如何使用Avro克服Spring Kafka 1.3中无法反序列化的消息

[英]How to move past undeserializable messages in Spring Kafka 1.3 with Avro

I can't upgrade to Spring 5 so I'm stuck with spring-kafka 1.3 and its limited error handling. 我无法升级到Spring 5,因此无法使用spring-kafka 1.3及其有限的错误处理功能。 So I have no access to ConsumerAwareErrorHandler or SeekToCurrent error handlers from spring-kafka 2. 所以我无权从spring-kafka 2访问ConsumerAwareErrorHandler或SeekToCurrent错误处理程序。

I'm using a @KafkaListener -annotated method to listen to a topic, I've configured the io.confluent.kafka.serializers.KafkaAvroDeserializer as my value deserializer. 我正在使用@KafkaListener方法来侦听主题,我已经将io.confluent.kafka.serializers.KafkaAvroDeserializer配置为我的值反序列化器。

The problem is if I end up with a message in my topic that is not in Avro format the KafkaMessageListenerContainer poll loop gets stuck. 问题是,如果我最终在主题中收到的消息不是Avro格式,则KafkaMessageListenerContainer轮询循环会卡住。 The deserializer throws an exception on the message and the poll loop never seeks past it so the next time through the loop it tries deserializing the same message and keeps looping, dumping the same error thousands of time per second into my log. 反序列化器在消息上引发异常,而轮询循环再也找不到它了,因此下一次通过循环,它将尝试反序列化同一条消息并保持循环,每秒将同一个错误几千次转储到我的日志中。

There doesn't seem to be a way to get a NeverRetryPolicy or anything in edge-wise, but I can factory.getContainerProperties().setErrorHandler() . 似乎没有办法获得NeverRetryPolicy或其他任何方法,但是我可以factory.getContainerProperties().setErrorHandler() Unfortunately I'm not sure what I can do from there. 不幸的是,我不确定从那里可以做什么。

Is there something I can Autowire into my error handler that I can use to seek forward 1 offset on error? 是否可以自动连线到错误处理程序中,以便在错误时向前寻找1个偏移量? Not sure what that is, the docs don't talk much about what you can actually DO with the ErrorHandler and most examples I can find are for spring-kafka 2.X. 不知道那是什么,文档并没有过多地讨论您可以使用ErrorHandler实际执行的操作,而我能找到的大多数示例都是针对spring-kafka 2.X的。 Like, it won't deserialize, there's NOTHING I can do with the message, it will NEVER work, I want to avoid retrying it ever again and it seems most Stackoverflow questions are about doing the opposite. 就像,它不会反序列化,没有什么我可以处理的消息,它将永远无法工作,我想避免再试一次,而且似乎大多数Stackoverflow问题都在做相反的事情。

I've also seen some folks just wrap the Deserializer from Avro with their own class that eats the exception and returns null. 我还看到有些人只是将Avro的Deserializer包装到自己的类中,该类吃掉异常并返回null。 Is that a better plan? 那是一个更好的计划吗?

The problem is the deserialization fails well before Spring gets the data - the problem is in Kafka itself. 问题是反序列化在Spring获取数据之前就失败了-问题出在Kafka本身。

In 2.2, we added the ErrorHandlingDeserializer2 which wraps the real deserializer and sends a signal to the listener container so the error can be sent to the error handler. 在2.2中,我们添加了ErrorHandlingDeserializer2 ,它包装了实际的反序列化器,并将信号发送到侦听器容器,以便可以将错误发送到错误处理程序。

In older versions, you would need to write your own deserializer wrapper - however, there is no code in the container to deal with the situation so your catch block would need to return a real Object that is a signal to your listener that the deserialization failed. 在较旧的版本中,您需要编写自己的反序列化程序包装器-但是,容器中没有代码来处理这种情况,因此您的catch块将需要返回一个真实的对象,该对象向侦听器发出信号,表明反序列化失败。

Let's say your listener receives Invoice . 假设您的听众收到Invoice Your catch block could create a subclass, say BadInvoice which you can then detect in your listener and discard it. 您的catch块可以创建一个子类,例如BadInvoice ,然后您可以在侦听器中检测该子类BadInvoice其丢弃。

I've also seen some folks just wrap the Deserializer from Avro with their own class that eats the exception and returns null. 我还看到有些人只是将Avro的Deserializer包装到自己的类中,该类吃掉异常并返回null。 Is that a better plan? 那是一个更好的计划吗?

You can return null if you never get real null records, but you would have to add @Payload(required = false) to the method parameter. 如果您从未获得真正的空记录,则可以返回null ,但@Payload(required = false)在方法参数中添加@Payload(required = false)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM