我第一次使用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++;
}
答案 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)
}
因此,当使用者下降或分配了新使用者时,它将开始从存储在您的数据库中的偏移量开始读取。