Java, Cách lấy số lượng thư trong một chủ đề trong apache kafka


93

Tôi đang sử dụng apache kafka để nhắn tin. Tôi đã triển khai trình sản xuất và người tiêu dùng bằng Java. Làm thế nào chúng ta có thể nhận được số lượng tin nhắn trong một chủ đề?

Câu trả lời:


34

Cách duy nhất để làm được điều này theo quan điểm của người tiêu dùng là thực sự sử dụng các thông điệp và đếm chúng sau đó.

Nhà môi giới Kafka tiết lộ bộ đếm JMX cho số lượng tin nhắn nhận được kể từ khi khởi động nhưng bạn không thể biết bao nhiêu trong số chúng đã được xóa.

Trong hầu hết các trường hợp phổ biến, các thông báo trong Kafka tốt nhất được xem như một luồng vô hạn và việc nhận giá trị rời rạc về số lượng hiện đang được lưu trên đĩa là không phù hợp. Hơn nữa, mọi thứ trở nên phức tạp hơn khi giao dịch với một nhóm các nhà môi giới mà tất cả đều có một tập hợp con các thông báo trong một chủ đề.


Xem câu trả lời của tôi stackoverflow.com/a/47313863/2017567 . Máy khách Java Kafka cho phép lấy thông tin đó.
Christophe Quintard

96

Nó không phải là java, nhưng có thể hữu ích

./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
Đây không phải là sự khác biệt của bù đắp sớm nhất và mới nhất trên mỗi tổng phân vùng? 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 Và sau đó sự khác biệt trả về các tin nhắn thực tế đang chờ xử lý trong chủ đề? Tôi có đúng không?
kisna

1
Vâng đó là sự thật. Bạn phải tính toán chênh lệch nếu hiệu số sớm nhất không bằng 0.
ssemichev

Đó là những gì tôi nghĩ :).
kisna

1
Có BẤT KỲ cách nào để sử dụng nó làm API và như vậy bên trong mã (JAVA, Scala hoặc Python) không?
salvob

Đây là sự kết hợp giữa mã của tôi và mã từ Kafka. Nó có thể hữu ích. Tôi sử dụng nó cho Spark trực tuyến - Kafka hội nhập KafkaClient gist.github.com/ssemichev/c2d94dce7ad65339c9637e1b461f86cf KafkaCluster gist.github.com/ssemichev/fa3605c7b10cb6c7b9c8ab54ffbc5865
ssemichev

16

Tôi thực sự sử dụng điều này để đo điểm chuẩn POC của mình. Mục bạn muốn sử dụng ConsumerOffsetChecker. Bạn có thể chạy nó bằng cách sử dụng tập lệnh bash như bên dưới.

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

Và dưới đây là kết quả: nhập mô tả hình ảnh ở đây Như bạn thấy trên ô màu đỏ, 999 là số tin nhắn đang có trong lô đề.

Cập nhật: ConsumerOffsetChecker không được dùng nữa kể từ 0.10.0, bạn có thể muốn bắt đầu sử dụng ConsumerGroupCommand.


1
Xin lưu ý rằng ConsumerOffsetChecker không được dùng nữa và sẽ bị loại bỏ trong các bản phát hành sau 0.9.0. Sử dụng ConsumerGroupCommand thay thế. (kafka.tools.ConsumerOffsetChecker $)
Szymon Sadło

1
Vâng, đó là những gì tôi đã nói.
Rudy

Câu cuối cùng của bạn không chính xác. Lệnh trên vẫn hoạt động trong 0.10.0.1 và cảnh báo giống như nhận xét trước đây của tôi.
Szymon Sadło

14

Đôi khi, mối quan tâm là biết số lượng thư trong mỗi phân vùng, ví dụ, khi kiểm tra phân vùng tùy chỉnh. Các bước tiếp theo đã được kiểm tra để hoạt động với Kafka 0.10.2.1-2 từ Confluent 3.2. Đưa ra một chủ đề Kafka ktvà dòng lệnh sau:

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

Điều đó in ra kết quả mẫu hiển thị số lượng tin nhắn trong ba phân vùng:

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

Số lượng dòng có thể nhiều hơn hoặc ít hơn tùy thuộc vào số lượng phân vùng cho chủ đề.


4
Nếu tính năng nén nhật ký được bật, thì việc tổng hợp hiệu số của các phân vùng có thể không đưa ra số lượng chính xác các thông báo trong chủ đề.

14

ConsumerOffsetCheckerkhông còn được hỗ trợ, bạn có thể sử dụng lệnh này để kiểm tra tất cả các thư trong chủ đề:

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

Trong trường hợp LAGlà số lượng tin nhắn trong phân vùng chủ đề:

nhập mô tả hình ảnh ở đây

Ngoài ra, bạn có thể thử sử dụng kafkacat . Đây là một dự án mã nguồn mở có thể giúp bạn đọc các thư từ một chủ đề và phân vùng và in chúng ra stdout. Đây là mẫu đọc 10 tin nhắn cuối cùng từ sample-kafka-topicchủ đề, sau đó thoát:

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

11

Sử dụng https://prestodb.io/docs/current/connector/kafka-tutorial.html

Một siêu SQL engine do Facebook cung cấp, kết nối trên một số nguồn dữ liệu (Cassandra, Kafka, JMX, Redis ...).

PrestoDB đang chạy như một máy chủ với các công nhân tùy chọn (có một chế độ độc lập không có thêm nhân công), sau đó bạn sử dụng một JAR thực thi nhỏ (được gọi là presto CLI) để thực hiện các truy vấn.

Khi bạn đã định cấu hình tốt máy chủ Presto, bạn có thể sử dụng SQL truyền thống:

SELECT count(*) FROM TOPIC_NAME;

công cụ này rất hay, nhưng nó sẽ không hoạt động nếu chủ đề của bạn có nhiều hơn 2 dấu chấm.
armandfp

7

Lệnh Apache Kafka để nhận các thông báo chưa được xử lý trên tất cả các phân vùng của một chủ đề:

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

Bản in:

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

Cột 6 là các thư chưa được xử lý. Thêm chúng lên như thế này:

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 đọc các hàng, bỏ qua dòng tiêu đề và cộng cột thứ 6 và ở cuối in ra tổng.

Bản in

5

5

Để nhận tất cả các thông báo được lưu trữ cho chủ đề, bạn có thể tìm kiếm người tiêu dùng ở đầu và cuối luồng cho mỗi phân vùng và tổng hợp kết quả

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, nếu bạn đã bật nén thì có thể có khoảng trống trong luồng nên số lượng thư thực tế có thể thấp hơn tổng số được tính ở đây. Để có được tổng số chính xác, bạn sẽ phải phát lại các tin nhắn và đếm chúng.
AutomatedMike

5

Chạy như sau (giả sử kafka-console-consumer.shlà trên đường dẫn):

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"

Lưu ý: tôi loại bỏ các --new-consumertừ tùy chọn đó không còn có sẵn (hoặc rõ ràng là cần thiết)
StephenBoesch

3

Sử dụng ứng dụng khách Java của Kafka 2.11-1.0.0, bạn có thể thực hiện những việc sau:

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

Đầu ra là một cái gì đó như thế này:

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

Tôi thích bạn trả lời hơn so với câu trả lời @AutomatedMike vì câu trả lời của bạn không gây nhầm seekToEnd(..)lẫn và seekToBeginning(..)các phương pháp thay đổi trạng thái của consumer.
adaslaw

2

Trong các phiên bản gần đây nhất của Trình quản lý Kafka, có một cột có tiêu đề Tổng số lần giảm giá gần đây .

nhập mô tả hình ảnh ở đây


2

Tôi đã có câu hỏi tương tự và đây là cách tôi đang làm điều đó, từ một 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()

Mã rất thô, vì tôi vừa mới làm việc này, nhưng về cơ bản bạn muốn trừ phần bù đầu của chủ đề khỏi phần bù kết thúc và đây sẽ là số lượng tin nhắn hiện tại cho chủ đề.

Bạn không thể chỉ dựa vào phần bù cuối vì các cấu hình khác (chính sách dọn dẹp, thời gian lưu giữ, v.v.) có thể dẫn đến việc xóa các thư cũ khỏi chủ đề của bạn. Giá trị bù chỉ "di chuyển" về phía trước, do đó, giá trị ăn mòn sẽ di chuyển về phía trước gần với giá trị kết thúc (hoặc cuối cùng đến cùng một giá trị, nếu chủ đề không chứa thông báo ngay bây giờ).

Về cơ bản, phần bù kết thúc đại diện cho tổng số thư đã xem qua chủ đề đó và sự khác biệt giữa hai phần này đại diện cho số lượng thư mà chủ đề có ngay bây giờ.


0

Trích từ tài liệu của Kafka

Không dùng nữa trong 0.9.0.0

Kafka-consumer-offset-checker.sh (kafka.tools.ConsumerOffsetChecker) không được dùng nữa. Trong tương lai, vui lòng sử dụng kafka-consumer-groups.sh (kafka.admin.ConsumerGroupCommand) cho chức năng này.

Tôi đang chạy nhà môi giới Kafka với SSL được bật cho cả máy chủ và máy khách. Lệnh dưới đây tôi sử dụng

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

trong đó / tmp / ssl_config như bên dưới

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

Nếu bạn có quyền truy cập vào giao diện JMX của máy chủ, các hiệu số bắt đầu và kết thúc có tại:

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

(bạn cần thay thế TOPICNAME& PARTITIONNUMBER). Hãy nhớ rằng bạn cần phải kiểm tra từng bản sao của phân vùng nhất định hoặc bạn cần tìm hiểu xem ai trong số các nhà môi giới dẫn đầu cho một phân vùng nhất định (và điều này có thể thay đổi theo thời gian).

Ngoài ra, bạn có thể sử dụng các phương pháp Kafka ConsumerbeginningOffsetsendOffsets.


-1

Tôi chưa thử điều này bản thân mình, nhưng nó có vẻ hợp lý.

Bạn cũng có thể sử dụng kafka.tools.ConsumerOffsetChecker( nguồn ).



-1

Bạn có thể sử dụng kafkatool . Vui lòng kiểm tra liên kết này -> http://www.kafkatool.com/download.html

Kafka Tool là một ứng dụng GUI để quản lý và sử dụng các cụm Apache Kafka. Nó cung cấp một giao diện người dùng trực quan cho phép người ta xem nhanh các đối tượng trong một cụm Kafka cũng như các thông báo được lưu trữ trong các chủ đề của cụm.nhập mô tả hình ảnh ở đây

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.