Java, Як отримати кількість повідомлень у темі в apache kafka


93

Я використовую apache kafka для обміну повідомленнями. Я застосував виробника та споживача на Java. Як ми можемо отримати кількість повідомлень у темі?

Відповіді:


34

Єдиний спосіб, який для цього приходить на думку з погляду споживача, - це насправді споживати повідомлення та підраховувати їх тоді.

Брокер Kafka виставляє лічильники JMX за кількістю повідомлень, отриманих з моменту запуску, але ви не можете знати, скільки з них вже очищено.

У найпоширеніших сценаріях повідомлення в Kafka найкраще розглядаються як нескінченний потік, і отримання дискретного значення того, скільки в даний час зберігається на диску, не має значення. Крім того, все ускладнюється, коли йдеться про групу брокерів, кожна з яких має підмножину повідомлень у темі.


Дивіться мою відповідь stackoverflow.com/a/47313863/2017567 . Клієнт Java Kafka дозволяє отримати цю інформацію.
Крістоф Квінтард,

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

1
Так, це правда. Вам потрібно вирахувати різницю, якщо найдавніші зсуви не дорівнюють нулю.
ssemichev

Це те, що я думав :).
kisna

1
Чи є БУДЬ-який спосіб використовувати це як API і так всередині коду (JAVA, Scala або Python)?
salvob

Ось поєднання мого коду та коду від Kafka. Це може бути корисно. Я використовував його для Спарк потоковому - Кафка інтеграція KafkaClient gist.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 $)
Шимон Садло

1
Так, це я сказав.
Руді

Ваше останнє речення не є точним. Вищевказана команда все ще працює в 0.10.0.1, і попередження те саме, що і мій попередній коментар.
Шимон Садло

14

Іноді інтерес полягає у знанні кількості повідомлень у кожному розділі, наприклад, під час тестування спеціального розділу. Наступні кроки були протестовані для роботи з Kafka 0.10.2.1-2 з Confluent 3.2. Дано тему Кафки 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кількість повідомлень у розділі теми:

введіть тут опис зображення

Також ви можете спробувати використовувати кафкакат . Це проект з відкритим кодом, який може допомогти вам прочитати повідомлення з теми та розділу та роздрукувати їх у stdout. Ось зразок, який читає останні 10 повідомлень з sample-kafka-topicтеми, а потім виходить:

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

11

Використовуйте https://prestodb.io/docs/current/connector/kafka-tutorial.html

Супер SQL-механізм, наданий Facebook, який підключається до кількох джерел даних (Cassandra, Kafka, JMX, Redis ...).

PrestoDB працює як сервер із необов’язковими працівниками (існує автономний режим без зайвих робітників), тоді ви використовуєте невеликий виконуваний файл JAR (званий presto CLI) для створення запитів.

Після того, як ви добре налаштували сервер Presto, ви можете використовувати традиційний SQL:

SELECT count(*) FROM TOPIC_NAME;

цей інструмент приємний, але якщо він не буде працювати, якщо ваша тема має більше 2 крапок.
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 читає рядки, пропускає рядок заголовка і додає 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

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

За допомогою Java-клієнта Kafka 2.11-1.0.0 ви можете зробити наступне:

    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.
Адаслав

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

Дуже грубий код, оскільки я щойно змусив це працювати, але в основному ви хочете відняти зміщення початку теми від кінцевого зміщення, і це буде поточний рахунок повідомлень для теми.

Ви не можете просто покладатися на кінцевий зсув через інші конфігурації (політика очищення, утримування-ms тощо), які можуть призвести до видалення старих повідомлень із вашої теми. Зміщення лише "рухаються" вперед, тому саме початковий зсув рухатиметься вперед ближче до кінця зсуву (або врешті-решт до того самого значення, якщо тема зараз не містить повідомлення).

В основному кінцевий зсув представляє загальну кількість повідомлень, які пройшли через цю тему, а різниця між ними представляє кількість повідомлень, які тема містить зараз.


0

Витяги з документів Kafka

Зниження в 0.9.0.0

Kafka-consumer-offset-checker.sh (kafka.tools.ConsumerOffsetChecker) застарілий. В майбутньому використовуйте kafka-consumer-groups.sh (kafka.admin.ConsumerGroupCommand) для цієї функції.

Я запускаю брокера Kafka з увімкненим SSL як для сервера, так і для клієнта. Нижче я використовую команду

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). Майте на увазі, що вам потрібно перевірити кожну з копій даного розділу, або вам потрібно з’ясувати, хто з посередників є лідером для даного розділу (і це може змінюватися з часом).

Крім того, ви можете використовувати споживчі методи KafkabeginningOffsets та endOffsets.


-1

Я не пробував це сам, але це , здається, має сенс.

Ви також можете використовувати kafka.tools.ConsumerOffsetChecker( джерело ).



-1

Ви можете використовувати kafkatool . Будь ласка, перевірте це посилання -> http://www.kafkatool.com/download.html

Kafka Tool - це графічний додаток для управління та використання кластерів Apache Kafka. Він забезпечує інтуїтивно зрозумілий інтерфейс, який дозволяє швидко переглядати об'єкти в кластері Kafka, а також повідомлення, що зберігаються в темах кластера.введіть тут опис зображення

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.