Phần trước dùng rabbitmqctl để đọc trạng thái thông điệp. Bài này nói hẳn về ba cách nhìn vào broker, và về hai con số mà cả ba cách đều dễ làm bạn hiểu sai.
Ba đường vào
| Đường | Dùng khi | Điểm yếu |
|---|---|---|
Giao diện :15672 |
Nhìn nhanh bằng mắt, nghịch thử | Số liệu là ảnh chụp có độ trễ |
rabbitmqctl |
Sự thật ngay lúc này, script trên chính máy chủ | Phải vào được container |
HTTP API :15672/api |
Giám sát, tự động hoá từ xa | Cùng độ trễ với giao diện |
Giao diện quản trị chính là HTTP API — nó chỉ là một trang gọi vào đúng những endpoint đó. Nên mọi điều nói về độ trễ của giao diện cũng đúng với API.
Lệnh kiểm tra nào nói thật
Phần 2 đã cho thấy cổng TCP mở trước khi broker sẵn sàng. Lần này tôi bấm giờ tất cả các cách kiểm tra cùng lúc, trên một container mới khởi động:
| Mốc | Xanh lúc |
|---|---|
| TCP tới cổng 5672 | 0,0 s |
rabbitmq-diagnostics ping |
1,5 s |
| Bắt tay AMQP thật | 4,2 s |
HTTP /api/overview |
4,3 s |
rabbitmq-diagnostics check_port_connectivity |
4,4 s |
rabbitmq-diagnostics check_local_alarms |
4,4 s |
rabbitmq-diagnostics check_running |
4,5 s |
ping báo xanh sớm hơn 2,7 giây so với lúc broker thật sự nhận được một kết nối AMQP. Nó chỉ hỏi "node Erlang có trả lời không", không hỏi "RabbitMQ đã phục vụ được chưa". Dùng nó làm healthcheck là dựng một cái đèn xanh nói dối.
Ba lệnh cuối bảng mới là thứ đáng dùng, và chúng nói ba điều khác nhau: check_running — ứng dụng RabbitMQ đã khởi động xong; check_port_connectivity — các listener đã nghe; check_local_alarms — node không đang trong tình trạng báo động bộ nhớ hay đĩa. Healthcheck ở phần 2 dùng check_running, và bảng này là lý do.
Lưu ý cách chạy: docker exec mặc định là root, và phần 2 cho thấy gọi công cụ Erlang bằng root lúc broker đang lên sẽ giết chính nó. Luôn thêm -u rabbitmq.
Số trên giao diện chậm hơn CLI bảy lần
Gửi 2 000 thông điệp rồi hỏi cả hai nguồn tới khi chúng đọc ra đủ 2 000:
rabbitmqctl list_queues đọc được 2000 sau 489 ms
HTTP /api/queues đọc được 2000 sau 3 448 ms
rabbitmqctl hỏi thẳng tiến trình đang giữ hàng đợi. HTTP API đọc từ kho thống kê mà plugin quản trị gom lại theo chu kỳ — nên nó luôn là ảnh chụp của quá khứ gần.
Hệ quả thực tế: đừng viết test hay script tự động chờ một con số trên HTTP API rồi kết luận. Cũng đừng hoảng khi giao diện hiện hàng đợi còn tồn đọng trong khi ứng dụng đã rút sạch — đợi vài giây rồi tải lại.
Bốn lệnh rabbitmqctl đáng thuộc
$ rabbitmqctl -q list_queues name messages consumers memory
name messages consumers memory
do-tre 2000 0 2918168
$ rabbitmqctl -q list_exchanges name type
name type
direct ← default exchange, tên rỗng
amq.direct direct
amq.fanout fanout
$ rabbitmqctl -q list_bindings source_name destination_name routing_key
source_name destination_name routing_key
do-tre do-tre ← binding ngầm của default exchange
$ rabbitmq-diagnostics -q memory_breakdown
reserved_unallocated: 0.0897 gb (52.05%)
other_system: 0.0274 gb (15.92%)
Hai dòng có mũi tên xác nhận điều phần 3 nói: default exchange là một exchange thật, tên rỗng, và mỗi hàng đợi tự động có một binding tới nó với routing key trùng tên mình. Một broker mới có sẵn tám exchange — bảy cái amq.* cộng cái tên rỗng.
HTTP API để viết script
$ curl -su guest:guest localhost:15672/api/overview
rabbitmq_version : 4.3.5
erlang_version : 27.3.4.16
queue_totals : {'messages': 2000, 'messages_ready': 2000, 'messages_unacknowledged': 0}
object_totals : {'channels': 0, 'consumers': 0, 'exchanges': 8, 'queues': 1, 'connections': 0}
/api/queues/%2F/<tên> cho một hàng đợi cụ thể — %2F là vhost / đã mã hoá URL, và đây là chỗ mọi script vấp lần đầu.
Trong đó có hai trường dễ nhầm nhau:
message_bytes : 8 890 ← tổng thân của 2 000 thông điệp
memory : 1 145 920 ← bộ nhớ tiến trình hàng đợi
Dữ liệu thật chưa tới 9 KB, còn tiến trình giữ nó ăn hơn một megabyte. Chỉ số để đặt cảnh báo "hàng đợi đang phình" là message_bytes và messages, không phải memory — con số kia nói về bộ đệm và cấu trúc nội bộ, và nó dao động cả khi hàng đợi đứng yên. Bài 38 quay lại chuyện chọn chỉ số nào để cảnh báo.
Thử ba mươi giây
# so hai nguon ngay tren may ban: cai nao doi truoc?
watch -n1 'docker exec -u rabbitmq rmq rabbitmqctl -q list_queues name messages; \
curl -su guest:guest "localhost:15672/api/queues/%2F/do-tre" | jq .messages'
Bơm thông điệp vào rồi nhìn hai dòng đó lệch nhau. Khi bạn đã thấy tận mắt độ lệch ấy, bạn sẽ không bao giờ viết một script chờ đợi dựa trên HTTP API nữa.
Bài sau: khai báo hàng đợi — bốn cờ durable, exclusive, auto-delete, và tổ hợp làm channel của bạn đóng sập với PRECONDITION_FAILED.