我正在使用spring-kafka-2.2.9.RELEASE
和kafka_2.12-2.3.0
。
我一直在尝试获取.DLT主题中的original payload
,但我得到的只是“空”。我确信可以使用ErrorHandlingDeserializer2
,SeekToCurrentErrorHandler
和DeadLetterPublishingRecoverer
来做到这一点,但是我不确定自己缺少什么。
生产者和消费者
Producer:
@Autowired
private ObjectMapper objectMapper;
@Bean
public ProducerFactory<Object, Object> producerFactory() {
Map<String, Object> props = new HashMap<>();
props.put(ProducerConfig.BOOTSTRAP_SERVERS_CONFIG, bootstrapServers);
props.put("acks","all");
return new DefaultKafkaProducerFactory<Object, Object>(props, new JsonSerializer<Object>(objectMapper), new JsonSerializer<>());
//return new DefaultKafkaProducerFactory<Object, Object>(props, new JsonSerializer<Object>(objectMapper), new JsonSerializer<Object>(objectMapper));
}
@Bean
public KafkaTemplate<Object, Object> kafkaTemplate() {
return new KafkaTemplate<Object, Object>(producerFactory());
}
Consumer:
@Autowired
private KafkaTemplate<Object, Object> kafkaTemplate;
@Autowired
private ObjectMapper objectMapper;
@Bean
public ConsumerFactory<Object, Object> consumerFactory() {
Map<String, Object> props = new HashMap<>();
props.put(ConsumerConfig.BOOTSTRAP_SERVERS_CONFIG, bootstrapServers);
props.put(ConsumerConfig.AUTO_OFFSET_RESET_CONFIG, "latest");
JsonDeserializer<Object> jsonDeserializer = new JsonDeserializer<>(objectMapper);
jsonDeserializer.addTrustedPackages("*");
ErrorHandlingDeserializer2<Object> errorHandlingDeserializerKey = new ErrorHandlingDeserializer2<>(jsonDeserializer);
ErrorHandlingDeserializer2<Object> errorHandlingDeserializerValue = new ErrorHandlingDeserializer2<>(jsonDeserializer);
return new DefaultKafkaConsumerFactory<>(props, errorHandlingDeserializerKey, errorHandlingDeserializerValue);
}
@Bean
public ConcurrentKafkaListenerContainerFactory<String, Object> kafkaListenerContainerFactory() {
ConcurrentKafkaListenerContainerFactory<String, Object> factory = new ConcurrentKafkaListenerContainerFactory<>();
factory.setConsumerFactory(consumerFactory());
factory.setErrorHandler(new SeekToCurrentErrorHandler(new DeadLetterPublishingRecoverer(kafkaTemplate), 3));
return factory;
}
我在主题中看到“空”。DLT:
kafka-console-consumer.bat --bootstrap-server localhost:9092 --topic topic.DLT --from-beginning
null
null
在此先感谢您的帮助。
答案 0 :(得分:1)
您目前无法使用2.2.x中带有@KafkaListener
的DLT记录(由于序列化异常而发布),因为容器检测到DeserializationException
标头,因此发送了DLT记录本身到错误处理程序。
我只有fixed this,它将在2.2.11中提供。
但是,如果您使用常规KafkaConsumer
,则可以使用此代码获取原始值...
Header exHeader = record.headers().lastHeader(ErrorHandlingDeserializer2.VALUE_DESERIALIZER_EXCEPTION_HEADER);
DeserializationException ex = (DeserializationException) new ObjectInputStream(
new ByteArrayInputStream(exHeader.value())).readObject();
System.out.println("DLT: " + new String(ex.getData()));
注意:如果您使用Artem建议的功能,那么记录将转到您的主侦听器,而不是错误处理程序,因此您必须在那里处理它。因此,您将需要某种包含原始有效负载的伪值。
如果可以升级到2.3.1,肯定会更容易。
答案 1 :(得分:0)
ErrorHandlingDeserializer2
中的逻辑类似:
private T recoverFromSupplier(String topic, Headers headers, byte[] data, Exception exception) {
if (this.failedDeserializationFunction != null) {
FailedDeserializationInfo failedDeserializationInfo =
new FailedDeserializationInfo(topic, headers, data, this.isForKey, exception);
return this.failedDeserializationFunction.apply(failedDeserializationInfo);
}
else {
return null;
}
}
因此,如果未提供failedDeserializationFunction
,则反序列化数据将作为null
返回。
有关更多信息,请参阅文档:https://docs.spring.io/spring-kafka/docs/2.3.1.RELEASE/reference/html/#error-handling-deserializer
如果委托未能反序列化记录内容,则
ErrorHandlingDeserializer2
将在包含原因和原始字节的标头中返回空值和DeserializationException
。