我正在使用Kafka 2.0版和Java消费者API来消费主题中的消息。我们使用的是单节点Kafka服务器,每个分区一个使用者。我观察到,消费者正在失去一些信息。 该方案是: 消费者调查主题。 我已经为每个线程创建了一个消费者。 获取消息并将其提供给处理程序以处理消息。 然后,它使用“至少一次” Kafka Consumer语义提交偏移,以提交Kafka偏移。 同时,我还有另一个使用不同组ID的使用者。在这个使用者中,我只是增加消息计数器并提交偏移量。此使用者没有消息丢失。
try {
//kafkaConsumer.registerTopic();
consumerThread = new Thread(() -> {
final String topicName1 = "topic-0";
final String topicName2 = "topic-1";
final String topicName3 = "topic-2";
final String topicName4 = "topic-3";
String groupId = "group-0";
final Properties consumerProperties = new Properties();
consumerProperties.put(ConsumerConfig.BOOTSTRAP_SERVERS_CONFIG, "192.168.13.49:9092");
consumerProperties.put(ConsumerConfig.KEY_DESERIALIZER_CLASS_CONFIG, "org.apache.kafka.common.serialization.ByteArrayDeserializer");
consumerProperties.put(ConsumerConfig.VALUE_DESERIALIZER_CLASS_CONFIG, "org.apache.kafka.common.serialization.ByteArrayDeserializer");
consumerProperties.put(ConsumerConfig.GROUP_ID_CONFIG, groupId);
consumerProperties.put(ConsumerConfig.MAX_POLL_RECORDS_CONFIG, "100");
consumerProperties.put(ConsumerConfig.ENABLE_AUTO_COMMIT_CONFIG, "false");
consumerProperties.put(ConsumerConfig.AUTO_COMMIT_INTERVAL_MS_CONFIG, 1000);
try {
consumer = new KafkaConsumer<>(consumerProperties);
consumer.subscribe(Arrays.asList(topicName1, topicName2, topicName3, topicName4));
} catch (KafkaException ke) {
logTrace(MODULE, ke);
}
while (service.isServiceStateRunning()) {
ConsumerRecords<String, byte[]> records = consumer.poll(Duration.ofMillis(100));
for (TopicPartition partition : records.partitions()) {
List<ConsumerRecord<String, byte[]>> partitionRecords = records.records(partition);
for (ConsumerRecord<String, byte[]> record : partitionRecords) {
processMessage(simpleMessage);
}
}
consumer.commitSync();
}
kafkaConsumer.closeResource();
}, "KAKFA_CONSUMER");
} catch (Exception e) {
}
答案 0 :(得分:2)
在这里使用subscribe()似乎有问题。
Subscribe用于订阅主题而不是分区。要使用特定的分区,您需要使用assign()。阅读文档摘录:
公共无效订阅(java.util.Collection主题)
订阅给定主题列表以动态分配 分区。主题订阅不是增量订阅。此清单将 替换当前分配(如果有)。这不可能 将主题订阅与组管理和手册结合起来 通过Assign(Collection)进行分区分配。如果给定的清单 topic为空,与unsubscribe()相同。这是一个 subscription(Collection,ConsumerRebalanceListener)的简写,其中 使用noop侦听器。如果您需要寻求特定能力 偏移量,您应该更喜欢subscription(Collection, ConsumerRebalanceListener),因为组重新平衡会导致 要重置的分区偏移量。您还应该提供自己的 侦听器,如果您正在执行自己的偏移量管理,因为 监听器使您有机会在重新平衡之前提交偏移量 完成。
公共无效分配(java.util.Collection分区)
手动为此用户分配分区列表。这个介面 不允许增量分配,并将替换 上一个作业(如果有)。如果给定的主题列表 partitions为空,与unsubscribe()相同。手册 通过此方法分配主题不使用使用者的组 管理功能。这样一来,就不会再有平衡 组成员资格或集群和主题时触发操作 元数据更改。请注意,不能同时使用两个手册 使用assign(Collection)进行分区分配,使用a subscription(Collection,ConsumerRebalanceListener)。