Java、Apachekafkaのトピック内のメッセージ数を取得する方法


93

メッセージングにApachekafkaを使用しています。私はJavaでプロデューサーとコンシューマーを実装しました。トピック内のメッセージの数を取得するにはどうすればよいですか?

回答:


34

消費者の観点からこれについて頭に浮かぶ唯一の方法は、実際にメッセージを消費し、それを数えることです。

Kafkaブローカーは、起動以降に受信したメッセージの数についてJMXカウンターを公開しますが、既にパージされているメッセージの数を知ることはできません。

最も一般的なシナリオでは、Kafkaのメッセージは無限のストリームとして最もよく見られ、現在ディスクに保持されているメッセージの数の離散値を取得することは関係ありません。さらに、トピック内のメッセージのサブセットをすべて持つブローカーのクラスターを処理する場合、事態はさらに複雑になります。


私の答えstackoverflow.com/a/47313863/2017567を参照してください。Java Kafkaクライアントでは、その情報を取得できます。
クリストフキンタード2018年

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 2016年

1
はい、本当です。最も早いオフセットがゼロに等しくない場合は、差を計算する必要があります。
ssemichev 2016年

私もそう思っていました :)。
kisna 2016年

1
それをAPIとして、つまりコード(JAVA、Scala、Python)内で使用する方法はありますか?
salvob 2017

これが私のコードとKafkaのコードの組み合わせです。役に立つかもしれません。Sparkストリーミングに使用しました-Kafka統合KafkaClientgist.github.com/ssemichev/c2d94dce7ad65339c9637e1b461f86cf KafkaCluster gist.github.com/ssemichev/fa3605c7b10cb6c7b9c8ab54ffbc5865
ssemichev

16

私は実際にこれをPOCのベンチマークに使用しています。ConsumerOffsetCheckerを使用するアイテム。以下のようなbashスクリプトを使用して実行できます。

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

結果は次の ここに画像の説明を入力してください とおりです。赤いボックスでわかるように、999は現在トピックにあるメッセージの数です。

更新:ConsumerOffsetCheckerは0.10.0以降非推奨になっているため、ConsumerGroupCommandの使用を開始することをお勧めします。


1
ConsumerOffsetCheckerは非推奨であり、0.9.0以降のリリースでは削除されることに注意してください。代わりにConsumerGroupCommandを使用してください。(kafka.tools.ConsumerOffsetChecker $)
SzymonSadło2016年

1
ええ、それは私が言ったことです。
ルディ

あなたの最後の文は正確ではありません。上記のコマンドは0.10.0.1でも機能し、警告は以前のコメントと同じです。
のSzymonSadło

14

カスタムパーティショナーをテストする場合など、各パーティション内のメッセージの数を知ることに関心がある場合があります。次の手順は、Confluent3.2のKafka0.10.2.1-2で動作するようにテストされています。Kafkaトピック、ktおよび次のコマンドラインがあるとします。

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

これにより、3つのパーティション内のメッセージの数を示すサンプル出力が出力されます。

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が提供する、複数のデータソース(Cassandra、Kafka、JMX、Redisなど)に接続するスーパーSQLエンジン。

PrestoDBは、オプションのワーカーを備えたサーバーとして実行されており(追加のワーカーがないスタンドアロンモードがあります)、小さな実行可能JAR(presto CLIと呼ばれます)を使用してクエリを実行します。

Prestoサーバーを適切に構成したら、従来のSQLを使用できます。

SELECT count(*) FROM TOPIC_NAME;

このツールは便利ですが、トピックに2つ以上のドットがあると機能しない場合。
armandfp 2017年

7

トピックのすべてのパーティションで未処理のメッセージを取得するApacheKafkaコマンド:

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は行を読み取り、ヘッダー行をスキップして6番目の列を合計し、最後に合計を出力します。

プリント

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 2017年

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

私はこれと同じ質問をしました、そしてこれは私がコトリンの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()

これが機能するようになったので、非常に大まかなコードですが、基本的には、トピックの開始オフセットを終了オフセットから減算すると、これがトピックの現在のメッセージ数になります。

トピックから古いメッセージが削除される可能性のある他の構成(クリーンアップポリシー、retention-msなど)があるため、エンドオフセットだけに依存することはできません。オフセットは前方に「移動」するだけなので、終了オフセットに近づく(またはトピックに現在メッセージが含まれていない場合は最終的に同じ値に移動する)のは最初のオフセットです。

基本的に、終了オフセットは、そのトピックを通過したメッセージの総数を表し、2つの違いは、トピックに現在含まれているメッセージの数を表します。


0

Kafkaドキュメントからの抜粋

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

TOPICNAME&を置き換える必要がありますPARTITIONNUMBER)。クマは念頭に置いて、あなたは、特定のパーティションのレプリカごとにチェックする必要がある、またはあなたがのためのリーダーであるブローカーのどちらを知る必要がある特定のパーティション(これは、時間とともに変化することができます)。

または、KafkaConsumerメソッドbeginningOffsetsとを使用することもできますendOffsets


-1

私はこれを自分で試したことがありませんが、それは理にかなっているようです。

kafka.tools.ConsumerOffsetCheckersource)を使用することもできます。



-1

kafkatoolを使用できます。このリンクを確認してください-> http://www.kafkatool.com/download.html

Kafka Toolは、ApacheKafkaクラスターを管理および使用するためのGUIアプリケーションです。これは、Kafkaクラスター内のオブジェクトとクラスターのトピックに保存されているメッセージをすばやく表示できる直感的なUIを提供します。ここに画像の説明を入力してください

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.