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.
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.