私は現在、Spring Integration Kafka=を使用してリアルタイム統計を作成しています。ただし、グループ名はKafkaリスナーが読み取っていなかった以前のすべての値を検索します。
@Value("${kafka.consumer.group.id}")
private String consumerGroupId;
@Bean
public ConsumerFactory<String, String> consumerFactory() {
return new DefaultKafkaConsumerFactory<>(getDefaultProperties());
}
public Map<String, Object> getDefaultProperties() {
Map<String, Object> properties = new HashMap<>();
properties.put(ConsumerConfig.BOOTSTRAP_SERVERS_CONFIG, bootstrapServers);
properties.put(ConsumerConfig.GROUP_ID_CONFIG, consumerGroupId);
properties.put(ConsumerConfig.KEY_DESERIALIZER_CLASS_CONFIG, StringDeserializer.class);
properties.put(ConsumerConfig.VALUE_DESERIALIZER_CLASS_CONFIG, ByteArrayDeserializer.class);
return properties;
}
@Bean
public ConcurrentKafkaListenerContainerFactory<String, String> kafkaListenerContainerFactory() {
ConcurrentKafkaListenerContainerFactory<String, String> factory = new ConcurrentKafkaListenerContainerFactory<>();
factory.setConsumerFactory(consumerFactory());
return factory;
}
@Bean
public KafkaMessageListener listener() {
return new KafkaMessageListener();
}
私は最新のオフセットから始めて、古い値に悩まされないようにしたいと思います。グループのオフセットをリセットする可能性はありますか?
この例は見なかったので、ここでどのようにしたかを説明します。
あなたのクラス@KafkaListener
はConsumerSeekAware
クラスを実装する必要があります。これにより、パーティションが割り当てられている場合にリスナーがオフセットシークを制御できるようになります。 (ソース: https://docs.spring.io/spring-kafka/reference/htmlsingle/#seek )
public class KafkaMessageListener implements ConsumerSeekAware {
@KafkaListener(topics = "your.topic")
public void listen(byte[] payload) {
// ...
}
@Override
public void registerSeekCallback(ConsumerSeekCallback callback) {
}
@Override
public void onPartitionsAssigned(Map<TopicPartition, Long> assignments, ConsumerSeekCallback callback) {
assignments.forEach((t, o) -> callback.seekToEnd(t.topic(), t.partition()));
}
@Override
public void onIdleContainer(Map<TopicPartition, Long> assignments, ConsumerSeekCallback callback) {
}
}
ここでは、リバランス時に、指定されたすべてのトピックの最後のオフセットを探すために、指定されたコールバックを使用します。 Artem Bilan( https://stackoverflow.com/users/2756547/artem-bilan )に回答してくれてありがとう。
まあ、それはあなたが消費者のauto.offset.reset
。しかし、とにかくそれがデフォルトでlatest
であると私を混乱させているのは:
auto.offset.reset What to do when there is no initial offset in Kafka or if the current offset does not exist any more on the server (e.g. because that data has been deleted):
earliest: automatically reset the offset to the earliest offset
latest: automatically reset the offset to the latest offset
none: throw exception to the consumer if no previous offset is found for the consumer's group
anything else: throw exception to the consumer.
string latest [latest, earliest, none] medium
いくつかのトピックにサブスクライブするときに、kafkaコンシューマにConsumerRebalanceListener
を設定できます。このトピックでは、KafkaConsumer.endOffsets()
メソッドによって各パーティションの最新のオフセットを取得できます、これをKafkaConsumer.seek()
メソッドでコンシューマに設定します。
kafkaConsumer.subscribe(Collections.singletonList(topics),
new ConsumerRebalanceListener() {
@Override
public void onPartitionsRevoked(Collection<TopicPartition> partitions) {
//do nothing
}
@Override
public void onPartitionsAssigned(Collection<TopicPartition> partitions) {
//get and set the lastest offset for each partiton
kafkaConsumer.endOffsets(partitions)
.forEach((partition, offset) -> kafkaConsumer.seek(partition, offset));
}
}
);
次のように、partitionOffsetsアノテーションを使用して、正確なオフセットで開始できます。
@KafkaListener(id = "bar", topicPartitions =
{ @TopicPartition(topic = "topic1", partitions = { "0", "1" }),
@TopicPartition(topic = "topic2", partitions = "0",
partitionOffsets = @PartitionOffset(partition = "1", initialOffset = "100"))
})public void listen(ConsumerRecord<?, ?> record) {
}
それを行う最も簡単な方法は、CONSUMER_GROUP_ID
:
properties.put(ConsumerConfig.GROUP_ID_CONFIG, "new-consumer-group-id");
properties.put(ConsumerConfig.AUTO_OFFSET_RESET_CONFIG, "latest");
それを行う余裕がない場合は、初期化中に目的のオフセットを探す必要があります。