Java, apache kafka'da bir konudaki mesajların sayısı nasıl alınır


93

Mesajlaşma için apache kafka kullanıyorum. Üreticiyi ve tüketiciyi Java'da uyguladım. Bir konudaki mesaj sayısını nasıl alabiliriz?

Yanıtlar:


34

Tüketici açısından bunun için akla gelen tek yol, mesajları gerçekten tüketip o zaman saymaktır.

Kafka komisyoncusu, başlangıçtan bu yana alınan mesaj sayısı için JMX sayaçlarını ortaya çıkarır, ancak bunlardan kaç tanesinin zaten temizlendiğini bilemezsiniz.

En yaygın senaryolarda, Kafka'daki mesajlar en iyi şekilde sonsuz bir akış olarak görülür ve şu anda diskte kaç tane tutulduğuna dair ayrı bir değer almak alakalı değildir. Dahası, hepsi bir konudaki mesajların bir alt kümesine sahip olan bir broker kümesi ile uğraşırken işler daha karmaşık hale gelir.


Cevabıma bakın stackoverflow.com/a/47313863/2017567 . Java Kafka istemcisi bu bilgilerin alınmasına izin verir.
Christophe Quintard

97

Java değil ama faydalı olabilir

./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
Bu, bölüm başına en erken ve en son ofset toplamının farkı olması gerekmez mi? 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 Ve sonra fark, konudaki gerçek bekleyen mesajları döndürür? Doğrumuyum?
kisna

1
Evet bu doğru. İlk uzaklık sıfıra eşit değilse bir fark hesaplamalısınız.
ssemichev

Bende böyle düşünmüştüm :).
kisna

1
Bunu bir API olarak ve dolayısıyla bir kodun içinde (JAVA, Scala veya Python) kullanmanın HERHANGİ BİR yolu var mı?
salvob

İşte benim kodumun ve Kafka'daki kodumun bir karışımı. Faydalı olabilir. Spark akışı için kullandım - Kafka entegrasyonu KafkaClient gist.github.com/ssemichev/c2d94dce7ad65339c9637e1b461f86cf KafkaCluster gist.github.com/ssemichev/fa3605c7b10cb6c7b9c8ab54ffbc5865
ssemichev

18

Aslında bunu POC'umu karşılaştırmak için kullanıyorum. ConsumerOffsetChecker'ı kullanmak istediğiniz öğe. Aşağıdaki gibi bash betiğini kullanarak çalıştırabilirsiniz.

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

Sonuç aşağıdadır: görüntü açıklamasını buraya girin Kırmızı kutuda görebileceğiniz gibi 999, şu anda konudaki mesaj sayısıdır.

Güncelleme: ConsumerOffsetChecker, 0.10.0'dan beri kullanımdan kaldırılmıştır, ConsumerGroupCommand'ı kullanmaya başlamak isteyebilirsiniz.


1
Lütfen ConsumerOffsetChecker'ın kullanımdan kaldırıldığını ve 0.9.0'dan sonraki sürümlerde bırakılacağını unutmayın. Bunun yerine ConsumerGroupCommand kullanın. (kafka.tools.ConsumerOffsetChecker $)
Szymon Sadło

1
Evet, ben de öyle dedim.
Rudy

Son cümlenin doğru değil. Yukarıdaki komut hala 0.10.0.1'de çalışıyor ve uyarı önceki yorumumla aynı.
Szymon Sadło

14

Bazen ilgi, örneğin özel bir bölümleyiciyi test ederken her bölümdeki mesaj sayısını bilmektir. Sonraki adımlar Confluent 3.2'den Kafka 0.10.2.1-2 ile çalışmak üzere test edilmiştir. Bir Kafka konusu ktve aşağıdaki komut satırı verildiğinde :

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

Bu, üç bölümdeki mesajların sayısını gösteren örnek çıktıyı yazdırır:

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

Konu için bölüm sayısına bağlı olarak satır sayısı az ya da çok olabilir.


4
Günlük sıkıştırma etkinleştirilirse, bölümlerin uzaklıklarının toplanması, konudaki mesajların tam sayısını vermeyebilir.

14

Yana ConsumerOffsetCheckerartık desteklenmiyor, konuya tüm iletileri kontrol etmek için bu komutu kullanabilirsiniz:

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

LAGKonu bölümündeki mesajların sayısı nerede :

görüntü açıklamasını buraya girin

Ayrıca kafkacat kullanmayı deneyebilirsiniz . Bu, bir konu ve bölümdeki mesajları okumanıza yardımcı olabilecek ve bunları standart çıktıya yazdıran açık kaynaklı bir projedir. Konudaki son 10 mesajı okuyan ve sample-kafka-topicardından çıkılan bir örnek :

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

11

Https://prestodb.io/docs/current/connector/kafka-tutorial.html kullanın

Facebook tarafından sağlanan ve çeşitli veri kaynaklarına (Cassandra, Kafka, JMX, Redis ...) bağlanan süper bir SQL motoru.

PrestoDB, isteğe bağlı çalışanların bulunduğu bir sunucu olarak çalışıyor (fazladan çalışanların olmadığı bağımsız bir mod var), ardından sorgu yapmak için küçük bir yürütülebilir JAR (presto CLI olarak adlandırılıyor) kullanıyorsunuz.

Presto sunucusunu iyi yapılandırdıktan sonra, geleneksel SQL'i kullanabilirsiniz:

SELECT count(*) FROM TOPIC_NAME;

Bu araç güzel, ancak eğer konunuzda 2'den fazla nokta varsa çalışmazsa.
armandfp

7

Apache Kafka bir konunun tüm bölümlerinde işlenmemiş mesajları almak için komut:

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

Baskılar:

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

Sütun 6, işlenmemiş mesajlardır. Bunları şu şekilde ekleyin:

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 satırları okur, başlık satırını atlar ve 6. sütunu toplar ve sonunda toplamı yazdırır.

Baskılar

5

5

Konu için depolanan tüm mesajları almak için, tüketiciyi her bölüm için akışın başına ve sonuna kadar arayabilir ve sonuçları toplayabilirsiniz.

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, sıkıştırmayı açtıysanız akışta boşluklar olabilir, bu nedenle gerçek mesaj sayısı burada hesaplanan toplamdan daha düşük olabilir. Doğru bir toplam elde etmek için mesajları tekrar dinlemeniz ve saymanız gerekecek.
AutomatedMike

5

Aşağıdakini çalıştırın ( kafka-console-consumer.shyolda olduğunu varsayarak ):

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"

Not: Ben kaldırıldı --new-consumero seçenek artık mevcut (ya da görünüşte gerekli) olduğu için
StephenBoesch

3

Kafka 2.11-1.0.0'ın Java istemcisini kullanarak aşağıdakileri yapabilirsiniz:

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

Çıktı şuna benzer:

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

Ben size cevabı ile karmaşa değil çünkü @AutomatedMike cevap karşılaştırarak cevap tercih seekToEnd(..)ve seekToBeginning(..)durumunu değiştirmek yöntemleri consumer.
adaslaw

2

Kafka Manager'ın en son sürümlerinde, Summed Recent Offsets başlıklı bir sütun bulunmaktadır .

görüntü açıklamasını buraya girin


2

Aynı soruyu sormuştum ve Kotlin'de bir KafkaConsumer'den bunu nasıl yapıyorum:

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

Çok kaba bir kod, bunu daha yeni çalıştırdım, ancak temelde konunun başlangıç ​​ofsetini bitiş ofsetinden çıkarmak istiyorsunuz ve bu, konu için geçerli mesaj sayısı olacaktır.

Konunuzdan eski mesajların silinmesine neden olabilecek diğer yapılandırmalar (temizleme politikası, bekletme-ms vb.) Nedeniyle yalnızca bitiş ofsetine güvenemezsiniz. Ofsetler yalnızca ileriye doğru "hareket eder", bu nedenle bitiş ofsetine daha yakın ileriye doğru hareket edecek olan başlangıç ​​ofsetidir (veya konu şu anda mesaj içermiyorsa, sonunda aynı değere).

Temel olarak bitiş uzaklığı, o konudan geçen toplam mesaj sayısını temsil eder ve ikisi arasındaki fark, konunun şu anda içerdiği mesajların sayısını temsil eder.


0

Kafka docs'dan alıntılar

0.9.0.0'daki kullanımdan kaldırmalar

Kafka-consumer-offset-checker.sh (kafka.tools.ConsumerOffsetChecker) kullanımdan kaldırıldı. İleriye dönük olarak, lütfen bu işlevsellik için kafka-consumer-groups.sh (kafka.admin.ConsumerGroupCommand) kullanın.

Kafka broker'ı hem sunucu hem de istemci için SSL etkinleştirilmiş olarak çalıştırıyorum. Kullandığım komutun altında

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 aşağıdaki gibidir

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

Sunucunun JMX arayüzüne erişiminiz varsa, başlangıç ​​ve bitiş uzaklıkları şu konumlarda mevcuttur:

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

( TOPICNAME& değiştirmelisiniz PARTITIONNUMBER). Ayı akılda size verilen bölüm kopyaları her biri için kontrol etmeniz gerekir, yoksa broker biri lideri için hangi bulmak gerekiyor verilmiş bölüm (ve bu zaman içinde değişebilir).

Alternatif olarak, Kafka Tüketici yöntemlerini beginningOffsetsve endOffsets.


-1

Ben denemedim bu kendim, ancak mantıklı görünmektedir.

Ayrıca kafka.tools.ConsumerOffsetChecker( kaynak ) kullanabilirsiniz .



-1

Kafkatool kullanabilirsiniz . Lütfen bu bağlantıyı kontrol edin -> http://www.kafkatool.com/download.html

Kafka Aracı, Apache Kafka kümelerini yönetmek ve kullanmak için bir GUI uygulamasıdır. Kişinin bir Kafka kümesindeki nesnelerin yanı sıra kümenin konularında depolanan mesajları hızlı bir şekilde görüntülemesini sağlayan sezgisel bir kullanıcı arabirimi sağlar.görüntü açıklamasını buraya girin

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.