如何确认spring kafka中的当前偏移量以进行手动提交

时间:2017-11-22 06:13:02

标签: apache-kafka spring-kafka

我第一次使用Spring Kafka而且我无法在我的消费者代码中使用Acknowledgement.acknowledge()方法进行手动提交。如果我的消费者配置或监听器代码中缺少任何内容,请告诉我。或者是否有其他方法根据条件处理确认偏移。     在这里,我正在寻找解决方案,如果没有手动提交/确认偏移,它应该由消费者选择相同的消息/偏移。

import java.util.HashMap;
import java.util.Map;

import org.apache.kafka.clients.consumer.ConsumerConfig;
import org.apache.kafka.common.serialization.StringDeserializer;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.kafka.annotation.EnableKafka;
import org.springframework.kafka.config.ConcurrentKafkaListenerContainerFactory;
import org.springframework.kafka.core.DefaultKafkaConsumerFactory;
import org.springframework.kafka.listener.AbstractMessageListenerContainer.AckMode;

@EnableKafka
@Configuration
public class ConsumerConfig {

@Value(value = "${kafka.bootstrapAddress}")
private String bootstrapAddress;

@Value(value = "${kafka.groupId}")
private String groupId;

@Bean
public ConcurrentKafkaListenerContainerFactory<String, String> containerFactory() {
Map<String, Object> props = new HashMap<String, Object>();
props.put(ConsumerConfig.BOOTSTRAP_SERVERS_CONFIG, bootstrapAddress);
props.put(ConsumerConfig.GROUP_ID_CONFIG, groupId);
props.put(ConsumerConfig.ENABLE_AUTO_COMMIT_CONFIG, false);
props.put(ConsumerConfig.AUTO_COMMIT_INTERVAL_MS_CONFIG, 100);
props.put(ConsumerConfig.KEY_DESERIALIZER_CLASS_CONFIG,
        StringDeserializer.class);
props.put(ConsumerConfig.VALUE_DESERIALIZER_CLASS_CONFIG,
        StringDeserializer.class);
props.put(ConsumerConfig.AUTO_OFFSET_RESET_CONFIG, "latest");
ConcurrentKafkaListenerContainerFactory<String, String> factory = new ConcurrentKafkaListenerContainerFactory<String, String>();
factory.setConsumerFactory(new DefaultKafkaConsumerFactory<String, String>(
        props));
factory.getContainerProperties().setAckMode(AckMode.MANUAL_IMMEDIATE);
factory.getContainerProperties().setSyncCommits(true);
return factory;
}
}
------------------------

private static int value = 1;

@KafkaListener(id = "baz", topics = "${message.topic.name}", containerFactory = "containerFactory")
public void listenPEN_RE(@Payload String message,
@Header(KafkaHeaders.RECEIVED_PARTITION_ID) int partition,
@Header(KafkaHeaders.OFFSET) int offsets,
Acknowledgment acknowledgment) {
if (value%2==0){
        acknowledgment.acknowledge();
}
value++;
}

4 个答案:

答案 0 :(得分:7)

将enable-auto-commit属性设置为false:

  

propsMap.put(ConsumerConfig.ENABLE_AUTO_COMMIT_CONFIG,false);

将ack-mode设置为MANUAL_IMMEDIATE:

  

factory.getContainerProperties()setAckMode(AbstractMessageListenerContainer.AckMode.MANUAL_IMMEDIATE);

然后,在您的消费者/侦听器代码中,您可以手动提交偏移量,如下所示:

df3.columns = df1.columns + ("Amount",)

更新:我为此创建了一个小POC。查看here,可能对您有帮助。

答案 1 :(得分:6)

您需要执行以下操作

1)将enable-auto-commit属性设置为false

consumerConfigProperties.put(ConsumerConfig.ENABLE_AUTO_COMMIT_CONFIG, "false");

2)将ACK模式设置为MANUL_IMMEDIATE

factory.getContainerProperties().setAckMode(AckMode.MANUAL_IMMEDIATE);

3)对于已处理的记录,您需要调用acknowledgment.acknowledge();

4)对于失败的记录调用acknowledgment.nack(10); 注意:nack方法需要一个很长的参数,即睡眠时间,并且应小于max.poll.interval.ms

下面是示例代码

@KafkaListener(id = "baz", topics = "${message.topic.name}", containerFactory = "containerFactory")
public void listenPEN_RE(@Payload String message,
        @Header(KafkaHeaders.RECEIVED_PARTITION_ID) int partition,
        @Header(KafkaHeaders.OFFSET) int offsets,
        Acknowledgment acknowledgment) {

    if (value%2==0){
        acknowledgment.acknowledge();
    } else {
        acknowledgment.nack(10); //sleep time should be less than max.poll.interval.ms
    }
    value++;
}

答案 2 :(得分:0)

这在Apache Kafka中并没有这样做。

对于当前正在运行的消费者,我们可能永远不会担心提交抵消。我们需要它们只针对同一个消费者群体中的新消费者。当前的一个跟踪其在内存中的偏移量。我想在经纪人的某个地方。

如果您需要在同一个消费者中重新获取相同的消息,可能是下一轮投票,您应该考虑使用before(function() { // Stub, as you were before findStub = sinon.stub() // Require the module yourself to stub stubbedDep = require('google-geocoder') // Override the method with the extact code used in the source stubbedDep.GeoCoder.prototype.find = findStub // Pass the stubbed version into proxyquire test = proxyquire('./test.js', { 'google-geocoder': stubbedDep }); }); 功能:https://docs.spring.io/spring-kafka/docs/2.0.1.RELEASE/reference/html/_reference.html#seek

答案 3 :(得分:0)

您可以执行以下操作:
1.将当前记录的偏移量存储到文件或数据库中。
2.使用ConsumerAware实现您的kafka侦听器类。
3.如下所示调用registerSeekCallback:

(registerSeekCallback(ConsumerSeekCallback callback) 
      {
      callback.seek(topic, partition, offset)
}

因此,当使用者下降或分配了新使用者时,它将开始从存储在您的数据库中的偏移量开始读取。