【发布时间】:2019-01-24 22:56:35
【问题描述】:
我正在使用 Spring Boot 2.0.2.RELEASE 和 Spring for Apache Kafka(有效的 pom 显示 2.1.6.RELEASE 用于 spring-kafka 版本)。
我已经从使用普通的ByteArrayDeserializer 变成了使用 Confluent 的反序列化器
properties.put(ConsumerConfig.VALUE_DESERIALIZER_CLASS_CONFIG, io.confluent.kafka.serializers.KafkaAvroDeserializer.class);
因此,我不必获取字节然后将它们反序列化到有效负载等中。但它的副作用是一些旧消息 - 我无法再阅读,因为它们的架构在融合注册表。
所以当我启动应用程序时,我不断收到这条消息
2018-08-17 17:58:51.360 ERROR 18004 --- [ntainer#0-0-C-1] o.s.k.listener.BatchLoggingErrorHandler : Error while processing:
org.apache.kafka.common.errors.SerializationException: Error deserializing key/value for partition ri00-q-log-et-final-0 at offset 36833. If needed, please seek past the record to continue consumption.
Caused by: org.apache.kafka.common.errors.SerializationException: Error deserializing Avro message for id -1
Caused by: org.apache.kafka.common.errors.SerializationException: Unknown magic byte!
所以我决定我必须从主题的结尾开始收听,我检查了文档https://docs.spring.io/spring-kafka/reference/htmlsingle/#seek 建议实现 ConsumerSeekAware 及其子接口 ConsumerSeekAware.ConsumerSeekCallback
我更改了包含@KafkaListener 方法的@service 类 实现文档中提到的接口
@Service
public class MyAvroListener implements
ConsumerSeekAware.ConsumerSeekCallback,ConsumerSeekAware {
它有 @kafkalistener 注释的方法,我尝试过寻找分区的结尾
@KafkaListener(topics = "${topic}", containerFactory = "myAvroListenerFactory")
public void listen(final Acknowledgment ack, final List<ConsumerRecord<String, EclLogging>> messages) throws Exception {
this.seekCallBack.get().seekToEnd(topic,0);
try {
for (ConsumerRecord<String, EclLogging> kafkaRecord : messages) {
我也尝试过寻找特定的偏移量(因为我一直卡在 36833 偏移量消息)
@KafkaListener(topics = "${topic}", containerFactory = "myAvroListenerFactory")
public void listen(final Acknowledgment ack, final List<ConsumerRecord<String, EclLogging>> messages) throws Exception {
this.seekCallBack.get().seek(topic,0,36900);
try {
for (ConsumerRecord<String, EclLogging> kafkaRecord : messages) {
我已经实现了上述接口的方法
private final ThreadLocal<ConsumerSeekCallback> seekCallBack = new ThreadLocal<>();
@Override
public void registerSeekCallback(ConsumerSeekCallback consumerSeekCallback) {
this.seekCallBack.set(consumerSeekCallback);
}
@Override
public void onPartitionsAssigned(Map<TopicPartition, Long> map, ConsumerSeekCallback consumerSeekCallback) {
}
@Override
public void onIdleContainer(Map<TopicPartition, Long> map, ConsumerSeekCallback consumerSeekCallback) {
}
@Override
public void seek(String s, int i, long l) {
}
@Override
public void seekToBeginning(String s, int i) {
}
@Override
public void seekToEnd(String topic, int partition) {
System.out.println("seekToEnd is hit for topic s = " + topic + " and partition i=" + partition);
}
当应用程序启动时, registerSeekCallBack 方法确实被命中, 但是 seekToEnd 或 seek 方法没有被击中。
因此我不断收到此消息
2018-08-17 17:58:51.360 ERROR 18004 --- [ntainer#0-0-C-1] o.s.k.listener.BatchLoggingErrorHandler : Error while processing:
org.apache.kafka.common.errors.SerializationException: Error deserializing key/value for partition ri00-q-log-et-final-0 at offset 36833. If needed, please seek past the record to continue consumption.
Caused by: org.apache.kafka.common.errors.SerializationException: Error deserializing Avro message for id -1
Caused by: org.apache.kafka.common.errors.SerializationException: Unknown magic byte!
我正在使用这里的 sn-p Spring Kafka Template implementaion example for seek offset, acknowledgement
正如这里提到的What determines Kafka consumer offset?,我不能使用 auto.offset.reset 属性从主题末尾开始消费(除非我使用不同的 consumerGroupId - 在我的情况下这是不可能的)。我想知道是否可以使用现有的消费者组来解决这个问题。
【问题讨论】:
标签: spring spring-boot apache-kafka spring-kafka