Java,如何获取Apache Kafka中某个主题的消息数


93

我正在使用apache kafka进行消息传递。我已经用Java实现了生产者和消费者。我们如何获取主题中的消息数量?

Answers:


34

从消费者的角度来看,想到此的唯一方法是实际消费消息并进行计数。

Kafka代理公开了自启动以来收到的消息数量的JMX计数器,但是您不知道已经清除了其中的多少。

在最常见的情况下,最好将Kafka中的消息视为无限流,而获得磁盘上当前保留的离散值并不重要。此外,当与一组经纪人进行交易时,事情变得更加复杂,这些经纪人都具有主题中消息的一部分。


见我的答案stackoverflow.com/a/47313863/2017567。Java Kafka客户端允许获取该信息。
Christophe Quintard,

96

它不是Java,但可能有用

./bin/kafka-run-class.sh kafka.tools.GetOffsetShell 
  --broker-list <broker>:  <port> 
  --topic <topic-name> --time -1 --offsets 1 
  | awk -F  ":" '{sum += $3} END {print sum}'

12
这不是每个分区的最早偏移量和最新偏移量之差吗? bash-4.3# $KAFKA_HOME/bin/kafka-run-class.sh kafka.tools.GetOffsetShell --broker-list 10.35.25.95:32774 --topic test-topic --time -1 | awk -F ":" '{sum += $3} END {print sum}' 13818663 bash-4.3# $KAFKA_HOME/bin/kafka-run-class.sh kafka.tools.GetOffsetShell --broker-list 10.35.25.95:32774 --topic test-topic --time -2 | awk -F ":" '{sum += $3} END {print sum}' 12434609 然后差异返回主题中的实际待处理消息?我对么?
kisna '16

1
是的,这是真的。如果最早的偏移量不等于零,则必须计算差值。
ssemichev

那正是我所想 :)。
kisna

1
有什么方法可以将其用作API,以及在代码内部(JAVA,Scala或Python)吗?
salvob

这是我的代码和来自Kafka的代码的组合。这可能很有用。我将其用于Spark流-Kafka集成KafkaClient gist.github.com/ssemichev/c2d94dce7ad65339c9637e1b461f86cf KafkaCluster gist.github.com/ssemichev/fa3605c7b10cb6c7b9c8ab54ffbc5865
ssemiche

16

我实际上用它来基准测试我的POC。您要使用ConsumerOffsetChecker的项目。您可以使用bash脚本运行它,如下所示。

bin/kafka-run-class.sh kafka.tools.ConsumerOffsetChecker  --topic test --zookeeper localhost:2181 --group testgroup

结果如下: 在此处输入图片说明 正如您在红色框中看到的那样,999是当前主题中的消息数。

更新:自0.10.0开始不推荐使用ConsumerOffsetChecker,您可能要开始使用ConsumerGroupCommand。


1
请注意,不建议使用ConsumerOffsetChecker,并将在0.9.0之后的版本中删除。请改用ConsumerGroupCommand。(kafka.tools.ConsumerOffsetChecker $)
SzymonSadło16年

1
是的,那是我说的。
鲁迪

您的最后一句话不正确。上面的命令在0.10.0.1中仍然有效,并且警告与我先前的注释相同。
SzymonSadło'16 -10-11

14

有时感兴趣的是知道每个分区中的消息数,例如在测试自定义分区程序时。随后的步骤已经过测试,可以与Confluent 3.2中的Kafka 0.10.2.1-2一起使用。给定一个Kafka主题,kt以及以下命令行:

$ kafka-run-class kafka.tools.GetOffsetShell \
  --broker-list host01:9092,host02:9092,host02:9092 --topic kt

打印输出示例,显示三个分区中消息的数量:

kt:2:6138
kt:1:6123
kt:0:6137

行数或多或少取决于主题的分区数。


4
如果启用了日志压缩,那么对分区的偏移量求和可能无法提供该主题中消息的确切数量。

14

由于ConsumerOffsetChecker不再受支持,因此您可以使用此命令来检查主题中的所有消息:

bin/kafka-run-class.sh kafka.admin.ConsumerGroupCommand \
    --group my-group \
    --bootstrap-server localhost:9092 \
    --describe

LAG主题分区中的邮件计数在哪里:

在此处输入图片说明

您也可以尝试使用kafkacat。这是一个开源项目,可以帮助您从主题和分区中读取消息并将其打印到stdout。这是一个示例,该示例从sample-kafka-topic主题读取最后10条消息,然后退出:

kafkacat -b localhost:9092 -t sample-kafka-topic -p 0 -o -10 -e

11

使用https://prestodb.io/docs/current/connector/kafka-tutorial.html

Facebook提供的超级SQL引擎,可连接多个数据源(Cassandra,Kafka,JMX,Redis ...)。

PrestoDB在带有可选工作程序的服务器上运行(存在一个没有额外工作程序的独立模式),然后使用小型可执行JAR(称为presto CLI)进行查询。

正确配置Presto服务器后,就可以使用传统的SQL:

SELECT count(*) FROM TOPIC_NAME;

这个工具不错,但是如果您的主题有两个以上的点,则无法使用。
armandfp

7

Apache Kafka命令在主题的所有分区上获取未处理的消息:

kafka-run-class kafka.tools.ConsumerOffsetChecker 
    --topic test --zookeeper localhost:2181 
    --group test_group

印刷品:

Group      Topic        Pid Offset          logSize         Lag             Owner
test_group test         0   11051           11053           2               none
test_group test         1   10810           10812           2               none
test_group test         2   11027           11028           1               none

列6是未处理的消息。像这样添加它们:

kafka-run-class kafka.tools.ConsumerOffsetChecker 
    --topic test --zookeeper localhost:2181 
    --group test_group 2>/dev/null | awk 'NR>1 {sum += $6} 
    END {print sum}'

awk读取行,跳过标题行并累加第六列,最后打印总和。

版画

5

5

要获取针对该主题存储的所有消息,您可以在每个分区的流的开头和结尾处寻找使用者,并对结果求和

List<TopicPartition> partitions = consumer.partitionsFor(topic).stream()
        .map(p -> new TopicPartition(topic, p.partition()))
        .collect(Collectors.toList());
    consumer.assign(partitions); 
    consumer.seekToEnd(Collections.emptySet());
Map<TopicPartition, Long> endPartitions = partitions.stream()
        .collect(Collectors.toMap(Function.identity(), consumer::position));
    consumer.seekToBeginning(Collections.emptySet());
System.out.println(partitions.stream().mapToLong(p -> endPartitions.get(p) - consumer.position(p)).sum());

1
顺便说一句,如果打开了压缩,那么流中可能会有间隙,因此消息的实际数量可能少于此处计算的总数。为了获得准确的总数,您将需要重播消息并对其进行计数。
AutomatedMike

5

运行以下命令(假设kafka-console-consumer.sh在路径上):

kafka-console-consumer.sh  --from-beginning \
--bootstrap-server yourbroker:9092 --property print.key=true  \
--property print.value=false --property print.partition \
--topic yourtopic --timeout-ms 5000 | tail -n 10|grep "Processed a total of"

注意:--new-consumer由于该选项不再可用(或显然是必需的),我删除了
StephenBoesch

3

使用Kafka 2.11-1.0.0的Java客户端,您可以执行以下操作:

    KafkaConsumer<String, String> consumer = new KafkaConsumer<>(props);
    consumer.subscribe(Collections.singletonList("test"));
    while(true) {
        ConsumerRecords<String, String> records = consumer.poll(100);
        for (ConsumerRecord<String, String> record : records) {
            System.out.printf("offset = %d, key = %s, value = %s%n", record.offset(), record.key(), record.value());

            // after each message, query the number of messages of the topic
            Set<TopicPartition> partitions = consumer.assignment();
            Map<TopicPartition, Long> offsets = consumer.endOffsets(partitions);
            for(TopicPartition partition : offsets.keySet()) {
                System.out.printf("partition %s is at %d\n", partition.topic(), offsets.get(partition));
            }
        }
    }

输出是这样的:

offset = 10, key = null, value = un
partition test is at 13
offset = 11, key = null, value = deux
partition test is at 13
offset = 12, key = null, value = trois
partition test is at 13

与@AutomatedMike答案相比,我更喜欢您的答案,因为您的答案不会弄乱,seekToEnd(..)并且seekToBeginning(..)方法会更改的状态consumer
adaslaw

2

在最新版本的Kafka Manager中,有一列标题为“汇总最近的偏移量”

在此处输入图片说明


2

我有同样的问题,这是我在Kotlin的KafkaConsumer中的操作方式:

val messageCount = consumer.listTopics().entries.filter { it.key == topicName }
    .map {
        it.value.map { topicInfo -> TopicPartition(topicInfo.topic(), topicInfo.partition()) }
    }.map { consumer.endOffsets(it).values.sum() - consumer.beginningOffsets(it).values.sum()}
    .first()

非常粗糙的代码,正如我刚开始使用的那样,但是基本上您想从结束偏移中减去主题的开始偏移,这将是该主题的当前消息数。

由于其他配置(清理策略,remaining-ms等)可能最终导致从主题中删除旧消息,因此您不能仅仅依靠结束偏移量。偏移量仅“向前”移动,因此开始偏移量将更靠近末端偏移量(如果主题现在不包含消息,则最终偏移相同的值)。

基本上,结束偏移量表示通过该主题的消息总数,而两者之间的差表示该主题当前包含的消息数。


0

卡夫卡文档摘录

0.9.0.0中的弃用

kafka-consumer-offset-checker.sh(kafka.tools.ConsumerOffsetChecker)已弃用。今后,请使用kafka-consumer-groups.sh(kafka.admin.ConsumerGroupCommand)来实现此功能。

我正在运行同时为服务器和客户端启用SSL的Kafka代理。下面我使用的命令

kafka-consumer-groups.sh --bootstrap-server Broker_IP:Port --list --command-config /tmp/ssl_config kafka-consumer-groups.sh --bootstrap-server Broker_IP:Port --command-config /tmp/ssl_config --describe --group group_name_x

/ tmp / ssl_config如下

security.protocol=SSL
ssl.truststore.location=truststore_file_path.jks
ssl.truststore.password=truststore_password
ssl.keystore.location=keystore_file_path.jks
ssl.keystore.password=keystore_password
ssl.key.password=key_password

0

如果您有权访问服务器的JMX界面,则起始和结束偏移量位于:

kafka.log:type=Log,name=LogStartOffset,topic=TOPICNAME,partition=PARTITIONNUMBER
kafka.log:type=Log,name=LogEndOffset,topic=TOPICNAME,partition=PARTITIONNUMBER

(您需要替换TOPICNAMEPARTITIONNUMBER)。请记住,您需要检查给定分区的每个副本,或者您需要找出哪个代理是给定分区的领导者(并且这会随着时间而变化)。

另外,您可以使用Kafka Consumer方法beginningOffsetsendOffsets


-1

我还没有尝试过这个自己,但它似乎是有道理的。

您也可以使用kafka.tools.ConsumerOffsetCheckersource)。



-1

您可以使用kafkatool。请检查此链接-> http://www.kafkatool.com/download.html

Kafka工具是用于管理和使用Apache Kafka集群的GUI应用程序。它提供了一个直观的UI,可让用户快速查看Kafka集群中的对象以及存储在集群主题中的消息。在此处输入图片说明

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.