Java, Comment obtenir le nombre de messages dans une rubrique dans Apache Kafka


93

J'utilise apache kafka pour la messagerie. J'ai implémenté le producteur et le consommateur en Java. Comment pouvons-nous obtenir le nombre de messages dans un sujet?

Réponses:


34

Le seul moyen qui me vient à l'esprit pour cela du point de vue du consommateur est de réellement consommer les messages et de les compter ensuite.

Le courtier Kafka expose les compteurs JMX pour le nombre de messages reçus depuis le démarrage, mais vous ne pouvez pas savoir combien d'entre eux ont déjà été purgés.

Dans la plupart des scénarios courants, les messages dans Kafka sont mieux perçus comme un flux infini et l'obtention d'une valeur discrète du nombre de messages actuellement conservés sur le disque n'est pas pertinente. De plus, les choses se compliquent lorsqu'il s'agit d'un groupe de courtiers qui ont tous un sous-ensemble de messages dans un sujet.


Voir ma réponse stackoverflow.com/a/47313863/2017567 . Le client Java Kafka permet d'obtenir ces informations.
Christophe Quintard

96

Ce n'est pas Java, mais peut être utile

./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
Cela ne devrait-il pas être la différence entre le premier et le dernier décalage par somme de partition? 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 Et puis la différence renvoie les messages en attente réels dans le sujet? Ai-je raison?
kisna

1
Oui c'est vrai. Vous devez calculer une différence si les premiers décalages ne sont pas égaux à zéro.
ssemichev

C'est ce que je pensais :).
kisna

1
Existe-t-il un moyen de l'utiliser comme API et donc dans un code (JAVA, Scala ou Python)?
salvob

Voici un mélange de mon code et du code de Kafka. Cela peut être utile. Je l'ai utilisé pour le streaming Spark - Intégration Kafka KafkaClient gist.github.com/ssemichev/c2d94dce7ad65339c9637e1b461f86cf KafkaCluster gist.github.com/ssemichev/fa3605c7b10cb6c7b9c8ab54ffbichec5865
2017

17

J'utilise en fait cela pour évaluer mon POC. L'élément que vous souhaitez utiliser ConsumerOffsetChecker. Vous pouvez l'exécuter en utilisant le script bash comme ci-dessous.

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

Et ci-dessous est le résultat: entrez la description de l'image ici comme vous pouvez le voir sur la boîte rouge, 999 est le nombre de messages actuellement dans le sujet.

Mise à jour: ConsumerOffsetChecker est obsolète depuis la 0.10.0, vous souhaiterez peut-être commencer à utiliser ConsumerGroupCommand.


1
Veuillez noter que ConsumerOffsetChecker est obsolète et sera supprimé dans les versions suivant la version 0.9.0. Utilisez plutôt ConsumerGroupCommand. (kafka.tools.ConsumerOffsetChecker $)
Szymon Sadło

1
Ouais, c'est ce que j'ai dit.
Rudy

Votre dernière phrase n'est pas exacte. La commande ci-dessus fonctionne toujours dans 0.10.0.1 et l'avertissement est le même que mon commentaire précédent.
Szymon Sadło

14

Parfois, l'intérêt est de connaître le nombre de messages dans chaque partition, par exemple, lors du test d'un partitionneur personnalisé.Les étapes suivantes ont été testées pour fonctionner avec Kafka 0.10.2.1-2 de Confluent 3.2. Étant donné un sujet Kafka ktet la ligne de commande suivante:

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

Cela imprime l'exemple de sortie montrant le nombre de messages dans les trois partitions:

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

Le nombre de lignes peut être supérieur ou inférieur en fonction du nombre de partitions pour le sujet.


4
Si le compactage du journal est activé, la somme des décalages des partitions peut ne pas donner le nombre exact de messages dans la rubrique.

14

Puisque ConsumerOffsetCheckern'est plus pris en charge, vous pouvez utiliser cette commande pour vérifier tous les messages de la rubrique:

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

LAGest le nombre de messages dans la partition de rubrique:

entrez la description de l'image ici

Vous pouvez également essayer d'utiliser kafkacat . Il s'agit d'un projet open source qui peut vous aider à lire les messages d'une rubrique et d'une partition et à les imprimer sur stdout. Voici un exemple qui lit les 10 derniers messages du sample-kafka-topicsujet, puis quittez:

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

11

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

Un moteur super SQL, fourni par Facebook, qui se connecte sur plusieurs sources de données (Cassandra, Kafka, JMX, Redis ...).

PrestoDB fonctionne en tant que serveur avec des workers optionnels (il existe un mode autonome sans workers supplémentaires), puis vous utilisez un petit exécutable JAR (appelé presto CLI) pour effectuer des requêtes.

Une fois que vous avez bien configuré le serveur Presto, vous pouvez utiliser le SQL traditionnel:

SELECT count(*) FROM TOPIC_NAME;

cet outil est sympa, mais s'il ne fonctionnera pas si votre sujet a plus de 2 points.
armandfp

7

Commande Apache Kafka pour obtenir des messages non gérés sur toutes les partitions d'un sujet:

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

Impressions:

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

La colonne 6 contient les messages non traités. Additionnez-les comme ceci:

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 lit les lignes, saute la ligne d'en-tête et ajoute la 6ème colonne et à la fin imprime la somme.

Tirages

5

5

Pour obtenir tous les messages stockés pour le sujet, vous pouvez rechercher le consommateur au début et à la fin du flux pour chaque partition et additionner les résultats

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
btw, si le compactage est activé, il peut y avoir des lacunes dans le flux, de sorte que le nombre réel de messages peut être inférieur au total calculé ici. Pour obtenir un total précis, vous devrez rejouer les messages et les compter.
AutomatedMike

5

Exécutez ce qui suit (en supposant qu'il se kafka-console-consumer.shtrouve sur le chemin):

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"

Remarque: j'ai supprimé le --new-consumercar cette option n'est plus disponible (ou apparemment nécessaire)
StephenBoesch

3

En utilisant le client Java de Kafka 2.11-1.0.0, vous pouvez effectuer les opérations suivantes:

    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));
            }
        }
    }

La sortie est quelque chose comme ceci:

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

Je préfère vous répondre à comparer réponse @AutomatedMike depuis votre réponse ne plaisante pas avec seekToEnd(..)et des seekToBeginning(..)méthodes qui changent l'état du consumer.
adaslaw

2

Dans les versions les plus récentes de Kafka Manager, il existe une colonne intitulée Summed Recent Offsets .

entrez la description de l'image ici


2

J'avais cette même question et voici comment je le fais, d'un KafkaConsumer, à Kotlin:

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()

Code très approximatif, car je viens de faire fonctionner cela, mais en gros, vous voulez soustraire le décalage de début du sujet du décalage de fin et ce sera le nombre de messages actuel pour le sujet.

Vous ne pouvez pas vous fier uniquement au décalage de fin à cause d'autres configurations (politique de nettoyage, rétention-ms, etc.) qui peuvent finir par provoquer la suppression d'anciens messages de votre rubrique. Les décalages "avancent" uniquement, c'est donc le décalage initial qui se rapproche du décalage de fin (ou éventuellement de la même valeur, si le sujet ne contient aucun message pour le moment).

Fondamentalement, le décalage de fin représente le nombre total de messages qui sont passés par cette rubrique et la différence entre les deux représente le nombre de messages que la rubrique contient actuellement.


0

Extraits de documents Kafka

Dépréciations dans 0.9.0.0

Le kafka-consumer-offset-checker.sh (kafka.tools.ConsumerOffsetChecker) est obsolète. À l'avenir, veuillez utiliser kafka-consumer-groups.sh (kafka.admin.ConsumerGroupCommand) pour cette fonctionnalité.

J'utilise le courtier Kafka avec SSL activé pour le serveur et le client. Ci-dessous la commande que j'utilise

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

où / tmp / ssl_config est comme ci-dessous

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

Si vous avez accès à l'interface JMX du serveur, les décalages de début et de fin sont présents à:

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

(vous devez remplacer TOPICNAME& PARTITIONNUMBER). Gardez à l'esprit que vous devez vérifier chacune des répliques d'une partition donnée, ou vous devez savoir lequel des courtiers est le leader pour une partition donnée (et cela peut changer avec le temps).

Vous pouvez également utiliser les méthodes Kafka ConsumerbeginningOffsets et endOffsets.


-1

Je n'ai pas essayé cela moi - même, mais cela semble logique.

Vous pouvez également utiliser kafka.tools.ConsumerOffsetChecker( source ).


-1

Le moyen le plus simple que j'ai trouvé est d'utiliser l'API REST Kafdrop /topic/topicNameet de spécifier la clé: "Accept"/ value: "application/json"header afin de récupérer une réponse JSON.

Ceci est documenté ici .


-1

Vous pouvez utiliser kafkatool . Veuillez vérifier ce lien -> http://www.kafkatool.com/download.html

Kafka Tool est une application GUI pour la gestion et l'utilisation des clusters Apache Kafka. Il fournit une interface utilisateur intuitive qui permet de visualiser rapidement les objets dans un cluster Kafka ainsi que les messages stockés dans les rubriques du cluster.entrez la description de l'image ici

En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.