在某些情况下,我有几个关于spring-kafka行为的问题。任何答案或指针都会很棒。
背景:我正在建立一个与外部apis交谈的kafka消费者并发回确认。我的配置看起来像这样:
@Bean
public Map<String, Object> consumerConfigs() {
Map<String, Object> props = new HashMap<>();
props.put(ConsumerConfig.BOOTSTRAP_SERVERS_CONFIG, brokerServers());
props.put(ConsumerConfig.KEY_DESERIALIZER_CLASS_CONFIG, StringDeserializer.class);
props.put(ConsumerConfig.VALUE_DESERIALIZER_CLASS_CONFIG, JsonDeserializer.class);
props.put(ConsumerConfig.GROUP_ID_CONFIG, this.configuration.getString("kafka-generic.consumer.group.id"));
props.put(ConsumerConfig.AUTO_OFFSET_RESET_CONFIG, "earliest");
props.put(ConsumerConfig.SESSION_TIMEOUT_MS_CONFIG, "5000000");
props.put(ConsumerConfig.REQUEST_TIMEOUT_MS_CONFIG, "6000000");
return props;
}
@Bean
public RetryTemplate retryTemplate() {
final ExponentialRandomBackOffPolicy backOffPolicy = new ExponentialRandomBackOffPolicy();
backOffPolicy.setInitialInterval(this.configuration.getLong("retry-exp-backoff-init-interval"));
final SimpleRetryPolicy retryPolicy = new SimpleRetryPolicy();
retryPolicy.setMaxAttempts(this.configuration.getInt("retry-max-attempts"));
final RetryTemplate retryTemplate = new RetryTemplate();
retryTemplate.setBackOffPolicy(backOffPolicy);
retryTemplate.setRetryPolicy(retryPolicy);
return retryTemplate;
}
@Bean
public ConcurrentKafkaListenerContainerFactory<String, Event> retryKafkaListenerContainerFactory() {
ConcurrentKafkaListenerContainerFactory<String, Event> factory =
new ConcurrentKafkaListenerContainerFactory<>();
factory.setConsumerFactory(consumerFactory());
factory.setConcurrency(this.configuration.getInt("kafka-concurrency"));
factory.setRetryTemplate(retryTemplate());
factory.getContainerProperties().setIdleEventInterval(this.configuration.getLong("kafka-rtm-idle-time"));
//factory.getContainerProperties().setAckOnError(false);
factory.getContainerProperties().setErrorHandler(kafkaConsumerErrorHandler);
factory.getContainerProperties().setAckMode(AbstractMessageListenerContainer.AckMode.MANUAL_IMMEDIATE);
return factory;
}
让我们说我的分区是4.我的分区分配是针对KafkaListener的:
@KafkaListener(topicPartitions = @TopicPartition(topic = "topic", partitions = {"0", "1"}),
containerFactory = "retryKafkaListenerContainerFactory")
public void receive(Event event, Acknowledgment acknowledgment) throws Exception {
serviceInvoker.callService(event);
acknowledgment.acknowledge();
}
@KafkaListener(topicPartitions = @TopicPartition(topic = "topic", partitions = {"2", "3"}),
containerFactory = "retryKafkaListenerContainerFactory")
public void receive1(Event event, Acknowledgment acknowledgment) throws Exception {
serviceInvoker.callService(event);
acknowledgment.acknowledge();
}
现在我的问题是:
假设我有2台机器,我部署了这段代码(具有相同的消费者群组ID)。如果我理解得当,如果我得到一个分区的事件,其中一台机器&#39; kafkalistener用于相应的分区,并将听其他机器&#39; kafkalistener不会听这个活动。是吗?
我的错误处理程序是:
@Named public class KafkaConsumerErrorHandler implements ErrorHandler { @Inject private KafkaListenerEndpointRegistry kafkaListenerEndpointRegistry; @Override public void handle(Exception e, ConsumerRecord<?, ?> consumerRecord) { System.out.println("Shutting down all the containers"); kafkaListenerEndpointRegistry.stop(); } }
让我们谈谈消费者和消费者的情况。调用kafkalistener,它调用serviceInvoker.callService(event);
,但服务已关闭,然后根据retryKafkaListenerContainerFactory
重试3次然后失败,然后调用errorhandler,从而停止kafkaListenerEndpointRegistry。这会关闭所有其他消费者或具有相同消费者群体的机器,还是只关闭此消费者或机器?
让我们谈谈2中的场景。是否有任何配置我们需要改变让kafka知道在那么长时间内推迟确认?
我的kafka制作人每隔10分钟制作一次信息。我是否需要在我的消费者代码中的任何位置配置10分钟,或者它是否与此无关?
在我的KafkaListener注释中,我硬编码了主题名称和分区。我可以在运行时更改它吗?
非常感谢任何帮助。提前致谢。 :)
答案 0 :(得分:3)
ackOnError=false
,因此无法提交抵消。${...}
或Spel Expressions #{...}
在应用程序初始化期间进行设置。