Cảnh báo phổ biến nhất trên RabbitMQ là "hàng đợi vượt N thông điệp". Bài này dựng hai tình huống có cùng độ sâu — một bình thường, một hỏng nặng — để xem chỉ số đó nói được gì.

Bật Prometheus

docker exec rmq rabbitmq-plugins enable rabbitmq_prometheus
curl -s localhost:15692/metrics

191 tên chỉ số khác nhau. Bài này không liệt kê hết; nó đi tìm những cái thật sự phân biệt được "đang bận" với "đang chết".

Hai tình huống, cùng một hàng đợi 30 000 thông điệp

Cả hai đều có đúng một consumer, prefetch 100. Khác nhau ở chỗ consumer thứ hai nhận thông điệp rồi không bao giờ ack — đúng kiểu một luồng bị treo ở lời gọi HTTP không có phép chờ.

A. đang rút bình thường B. consumer kẹt cứng
messages_ready 26 140 29 900
messages_unacked 100 100
consumers 1 1
tốc độ ack 795/s 0/s

Ba dòng đầu gần như không phân biệt được: cùng số consumer, cùng số unacked, và độ sâu thì chỉ khác nhau ở chỗ một bên đang giảm dần — thứ mà một lần đọc không thấy được.

Ảnh chụp một thời điểm của độ sâu hàng đợi không mang thông tin nào về sức khoẻ. Hàng đợi 30 000 thông điệp đang rút 800 cái mỗi giây là hoàn toàn bình thường; hàng đợi 30 000 thông điệp không rút cái nào là sự cố. Con số giống nhau.

Chỉ số quyết định là tốc độ ack

Dòng cuối bảng là thứ tách được hai tình huống, và nó tách rất dứt khoát: 795 so với 0.

Nói rộng hơn, thứ đáng theo dõi là quan hệ giữa tốc độ vào và tốc độ ra:

  • Tốc độ ack ≈ tốc độ publish → hệ thống theo kịp, độ sâu bao nhiêu cũng không sao.
  • Tốc độ ack < tốc độ publish → độ sâu đang tăng; cảnh báo khi xu hướng kéo dài, không phải khi vượt ngưỡng.
  • Tốc độ ack = 0 mà có consumer → đây mới là cảnh báo cần đánh thức người trực.

Trường hợp cuối là thứ mà cảnh báo theo ngưỡng độ sâu luôn báo muộn: nó phải chờ hàng đợi dồn tới ngưỡng, trong khi tốc độ ack đã về 0 từ giây đầu tiên.

Một chỉ số tôi không dùng

consumer_utilisation hay được nhắc tới, nên tôi đo luôn. Kết quả:

A. đang rút bình thường : consumer_utilisation = 0,05
B. consumer kẹt cứng    : consumer_utilisation = 0,42

Ngược hẳn với điều cái tên gợi ra. Tôi không có giải thích chắc chắn cho con số này, nên bài không đưa ra lời khuyên nào dựa trên nó — và cũng khuyên bạn đừng đặt cảnh báo lên một chỉ số mà mình chưa giải thích được. Tốc độ ack thì không có chỗ nào để hiểu nhầm.

Sáu chỉ số đáng đặt cảnh báo

Chỉ số Cảnh báo khi Vì sao
rabbitmq_global_messages_acknowledged_total (tốc độ) về 0 mà consumers > 0 Bảng đầu bài
rabbitmq_queue_messages_unacked dừng ở đúng bằng prefetch và không đổi Consumer treo, không phải bận
rabbitmq_consumers = 0 trên hàng đợi công việc Phần 32: hàng đợi bị bỏ quên ăn đĩa
rabbitmq_global_messages_dead_lettered_*_total tăng Bốn hậu tố rejected / expired / maxlen / delivery_limit khớp đúng bốn nguyên nhân ở phần 14
rabbitmq_disk_space_available_bytes dưới ngưỡng Phần 32: đĩa đầy làm broker chặn mọi producer
rabbitmq_alarms_free_disk_space_watermark = 1 Báo động đã kích hoạt — lúc này producer đã bị chặn rồi

Chi tiết đáng khen của bản Prometheus: nhóm dead_lettered tách theo nguyên nhân. Cảnh báo trên maxlen nghĩa là hàng đợi đang tràn; trên rejected nghĩa là mã của bạn đang ném ngoại lệ; trên expired nghĩa là TTL đang cắt thông điệp. Ba việc khác nhau, ba cách chữa khác nhau, và trước đây phải đi bới x-death mới biết.

Còn độ sâu thì sao

Vẫn theo dõi, nhưng như một xu hướng, không phải một ngưỡng. Và với stream thì bỏ hẳn: phần 35 đo được rằng stream luôn báo messages = 0 dù đang giữ đủ dữ liệu.

Bài sau: gom toàn bộ phép đo của sê-ri thành một bảng — thứ gì thật sự đổi được hiệu năng, và thứ gì ai cũng khuyên mà đo ra không khác gì.

Thử ba mươi giây

curl -s localhost:15692/metrics | grep -E "^rabbitmq_(global_messages_acknowledged_total|queue_messages_unacked|consumers|disk_space_available_bytes) "

Chạy hai lần cách nhau mười giây. Nếu acknowledged_total không đổi trong khi consumers khác 0, bạn có một consumer đang treo — và độ sâu hàng đợi lúc này còn chưa kịp nhúc nhích.