Kafka phát ra hàng trăm chỉ số qua JMX. Bài này dựng một sự cố thật rồi xem chỉ số nào báo, và câu trả lời khiến phần lớn bảng theo dõi Kafka trở nên vô dụng.

Sự cố mà chỉ số broker không thấy, và danh sách chỉ số thật sự đáng cảnh báo

Sự cố: đường ống hỏng hoàn toàn

Producer chạy đều 20.000 tin/giây. Consumer đăng ký nhóm rồi ngừng đọc — mô phỏng một dịch vụ bị treo, hoặc bị OOMKilled mà không khởi động lại được.

Giây Lag UnderReplicatedPartitions OfflinePartitionsCount ActiveControllerCount
0 19.880 0 0 1
20 393.879 0 0 1
40 768.599 0 0 1
60 1.143.020 0 0 1

Lag tăng 57 lần trong 60 giây. Cả ba chỉ số sức khoẻ broker không nhúc nhích một chút nào.

Và chúng đang nói thật: broker hoàn toàn khoẻ. Nó nhận đủ dữ liệu, ghi đủ bản sao, có đủ leader. Cái hỏng là đường ống, và chỉ số broker không đo đường ống.

Đây là lý do một bảng theo dõi Kafka chỉ gồm chỉ số broker sẽ xanh mượt trong khi dữ liệu ngừng chảy tới hạ nguồn. Tôi đã thấy nhiều bảng như vậy, và chúng cho cảm giác an toàn sai.

Bốn chỉ số broker phải cảnh báo

Không phải hàng trăm. Bốn.

OfflinePartitionsCount > 0 — sự cố. Partition không có leader: không đọc được, không ghi được. Đây là chỉ số duy nhất trong danh sách mà giá trị khác 0 luôn có nghĩa là đang có sự cố thật. Phần 15 đã đo tình huống dẫn tới nó.

ActiveControllerCount != 1 — sự cố. Bằng 0 nghĩa là không ai điều khiển cụm: không bầu được leader, không tạo được topic. Lớn hơn 1 nghĩa là não phân liệt. Chỉ số này phải được cộng trên toàn cụm — mỗi broker báo 0 hoặc 1, và tổng phải luôn bằng 1.

UnderReplicatedPartitions > 0 — cảnh báo sớm. Có follower đang tụt lại. Chưa mất gì, nhưng mức dự phòng đã giảm. Với replication-factor=3min.insync.replicas=2 (phần 14), đây là mức cảnh báo cuối trước khi việc ghi bị chặn.

RequestHandlerAvgIdlePercent < 0,3 — sắp quá tải. Tỉ lệ thời gian rỗi của luồng xử lý yêu cầu. Xuống dưới 30% nghĩa là hàng đợi sắp dồn, và mọi độ trễ sắp tăng.

Bốn cái đó bao gần hết những gì broker có thể nói về chính nó. Thêm chỉ số nữa thường chỉ làm bảng theo dõi khó đọc hơn.

Ba chỉ số phía client — thứ thật sự nói đường ống có chạy

Không có chỉ số nào trong ba cái này nằm ở broker. Chúng nằm ở ứng dụng của bạn, và phải được thu thập từ đó.

records-lag-max (consumer) — consumer đang tụt bao xa. Đây là chỉ số duy nhất bắt được sự cố ở bảng đầu bài. Nó có sẵn qua JMX của chính consumer: kafka.consumer:type=consumer-fetch-manager-metrics,client-id=*.

record-error-rate (producer) — tỉ lệ tin gửi hỏng. Producer thử lại âm thầm (phần 4), nên tin hỏng có thể không bao giờ thành ngoại lệ trong mã của bạn.

commit-latency-avg (consumer) — chốt offset có chậm bất thường không. Tăng đột ngột thường là dấu hiệu topic __consumer_offsets đang có vấn đề, và nó ảnh hưởng mọi nhóm cùng lúc (phần 15).

Nếu bảng theo dõi của bạn chỉ có một chỉ số, hãy chọn records-lag-max. Phần sau đo cách đọc nó cho đúng.

Lấy chỉ số qua JMX

kafka-jmx.sh --jmx-url service:jmx:rmi:///jndi/rmi://kf:9101/jmxrmi \
  --object-name "kafka.server:type=ReplicaManager,name=UnderReplicatedPartitions" \
  --one-time

# 1788031197550,0

Broker phải bật JMX bằng biến môi trường KAFKA_JMX_PORT. Trong container, việc này hay hỏng vì RMI công bố tên máy chủ mà bên ngoài không phân giải được — nên phải đặt KAFKA_JMX_HOSTNAME khớp với tên container.

Trong môi trường thật, gần như không ai gọi JMX bằng tay. Cách thông dụng là chạy JMX Exporter của Prometheus như một Java agent trên broker, biến toàn bộ cây JMX thành điểm cuối HTTP.

Đọc một chỉ số cho đúng

Chỉ số Kafka kiểu Meter trả về nhiều trường một lúc:

MessagesInPerSec:
  Count=498721   MeanRate=13813   OneMinuteRate=6547
  FiveMinuteRate=1526   FifteenMinuteRate=522

Hai cái bẫy.

Count là số cộng dồn từ lúc broker khởi động, không phải tốc độ. Vẽ nó lên đồ thị sẽ ra một đường thẳng đi lên và không nói gì. Phải lấy đạo hàm.

MeanRate là trung bình từ lúc khởi động, nên nó phản ứng cực chậm. Ở bảng trên, MeanRate là 13.813 trong khi OneMinuteRate là 6.547 — broker vừa chậm lại một nửa, và chỉ OneMinuteRate cho thấy điều đó.

Với cảnh báo, dùng OneMinuteRate. Với đồ thị dài hạn, dùng Count rồi tự tính chênh lệch.

Hai chỉ số hay bị hiểu sai

RequestQueueSize bằng 0 hầu như luôn, kể cả khi broker đang bận — vì luồng xử lý nhặt yêu cầu ra rất nhanh. Nó chỉ khác 0 khi đã quá tải nặng, nên nó là chỉ số quá muộn. RequestHandlerAvgIdlePercent báo sớm hơn nhiều.

NetworkProcessorAvgIdlePercent bằng 1,0 trong phép đo của tôi ngay cả khi đang nhận 20.000 tin/giây. Luồng mạng ít khi là nút thắt; đừng dùng nó làm chỉ báo tải.

Chỉ số về dung lượng

kafka-log-dirs.sh --bootstrap-server kf:9092 --describe
# 54 partition, tổng 893 MB

Đây là con số duy nhất cho biết bạn còn bao nhiêu chỗ trước khi đầy đĩa. Phần 17 đã đo hai bội số khiến dung lượng thật lớn hơn retention.bytes nhiều lần — nên đừng tính toán, hãy đo.

Bảng theo dõi tối thiểu

Nếu phải dựng lại từ đầu, sáu ô:

  1. OfflinePartitionsCount — cộng toàn cụm, cảnh báo ở > 0
  2. ActiveControllerCount — cộng toàn cụm, cảnh báo nếu ≠ 1
  3. UnderReplicatedPartitions — cộng toàn cụm, cảnh báo ở > 0 kéo dài 5 phút
  4. Lag theo nhóm consumer — cảnh báo theo xu hướng, không theo ngưỡng cố định
  5. RequestHandlerAvgIdlePercent — cảnh báo ở < 0,3
  6. Dung lượng đĩa mỗi broker — cảnh báo ở 75%

Ô số 4 là ô duy nhất bắt được sự cố ở đầu bài, và cũng là ô khó đặt ngưỡng nhất. Phần sau dành riêng cho nó.

Thử ba mươi giây

Kiểm bảng theo dõi của bạn có bắt được sự cố ở đầu bài không:

# dựng một nhóm không đọc gì
kafka-console-consumer.sh --bootstrap-server kf:9092 --topic <topic-ban-nhieu> \
  --group thu-nghiem-lag --max-messages 1 --timeout-ms 5000

# rồi để yên và nhìn bảng theo dõi trong 5 phút
kafka-consumer-groups.sh --bootstrap-server kf:9092 --describe --group thu-nghiem-lag

Nếu không có gì trên bảng theo dõi thay đổi trong năm phút đó, bảng của bạn không đo đường ống — và một dịch vụ chết sẽ không được phát hiện cho tới khi có người dùng phàn nàn.

Phần sau đo lag: 2 triệu tin lag nghe rất tệ, nhưng 102,6 giây thì lại là con số hành động được.