Monitoring & Management
คุณ operate สิ่งที่มองไม่เห็นไม่ได้
หัวข้อที่มีชื่อว่า “คุณ operate สิ่งที่มองไม่เห็นไม่ได้”RabbitMQ มาพร้อม management plugin ที่ให้ web UI และ HTTP API บน port 15672 เปิดขึ้นมาแล้วคุณจะเฝ้าดู queue, connection, channel และ rate ได้แบบ live:
rabbitmq-plugins enable rabbitmq_management# UI อยู่ที่ http://localhost:15672 (default guest/guest, localhost เท่านั้น)UI เหมาะกับการดูปัญหาด้วยตา แต่สำหรับ monitoring จริงคุณต้องใช้ HTTP API (สำหรับ script และ health check) และ Prometheus plugin (rabbitmq_prometheus) ป้อนเข้า Grafana dashboard และ alert
metric ที่สำคัญจริง
หัวข้อที่มีชื่อว่า “metric ที่สำคัญจริง”metric มีเป็นสิบ ๆ ตัว แต่ไม่กี่ตัวก็บอกเกือบทุกอย่าง:
| สัญญาณ | หมายความว่าอะไร | ระวังเมื่อ |
|---|---|---|
Queue depth (messages_ready) | message ที่รอถูก deliver | ค่อย ๆ สูงขึ้น = consumer ตามไม่ทัน |
Unacked (messages_unacknowledged) | deliver แล้วแต่ยังไม่ ack | สูง/ค้าง = consumer ช้าหรือแฮงก์ |
| Publish rate เทียบ deliver/ack rate | throughput ของ producer เทียบ consumer | publish > ack นาน ๆ = backlog กำลังโต |
| Consumer count | จำนวน consumer บน queue | ตกลงเป็น 0 = ไม่มีใครทำงาน queue นี้ |
| Memory & disk | headroom ของทรัพยากร broker | ใกล้ limit = alarm กำลังจะทำงาน |
| Connections / channels | footprint ของ client | พุ่งเร็ว = บั๊ก connection churn |
alert ที่มีประโยชน์ที่สุดคือ queue depth ที่กำลังไต่ขึ้น ขณะที่ consumer count หรือ ack rate นิ่ง — นั่นคือ consumer ที่ค้างหรือ scale ไม่พอ ซึ่งจับได้ก่อน queue จะกิน memory จนเต็ม
อ่านจาก script
หัวข้อที่มีชื่อว่า “อ่านจาก script”// Query the management HTTP API for a queue's depth.const res = await fetch('http://localhost:15672/api/queues/%2F/orders', { headers: { Authorization: 'Basic ' + btoa('guest:guest') },});const q = await res.json();console.log('ready:', q.messages_ready, 'unacked:', q.messages_unacknowledged);import requests
# %2F is the URL-encoded default vhost "/"r = requests.get("http://localhost:15672/api/queues/%2F/orders", auth=("guest", "guest"))q = r.json()print("ready:", q["messages_ready"], "unacked:", q["messages_unacknowledged"])req, _ := http.NewRequest("GET", "http://localhost:15672/api/queues/%2F/orders", nil)req.SetBasicAuth("guest", "guest")resp, _ := http.DefaultClient.Do(req)defer resp.Body.Close()var q struct { Ready int `json:"messages_ready"` Unack int `json:"messages_unacknowledged"`}json.NewDecoder(resp.Body).Decode(&q)log.Printf("ready=%d unacked=%d", q.Ready, q.Unack)สำหรับเช็คเร็ว ๆ บนเครื่อง rabbitmqctl list_queues name messages_ready messages_unacknowledged consumers ให้ตัวเลขชุดเดียวกันจาก command line
alarm: broker ปกป้องตัวเอง
หัวข้อที่มีชื่อว่า “alarm: broker ปกป้องตัวเอง”RabbitMQ เฝ้าดูทรัพยากรสองอย่างและยก alarm เมื่ออันใดอันหนึ่งเหลือน้อย:
- Memory alarm — memory ที่ใช้ทั้งหมดข้าม high-watermark (default 40% ของ RAM)
- Disk alarm — disk ว่างต่ำกว่า limit ที่ตั้งไว้
เมื่อ alarm ทำงาน RabbitMQ จะ block publisher (หยุดรับ message ใหม่) แต่ยัง deliver ให้ consumer ต่อ เพื่อให้ backlog ไหลออกแทนที่จะโตขึ้น alarm เป็นกลไกความปลอดภัย ไม่ใช่ความล้มเหลว — แต่ถ้า alarm ทำงาน บ่อย แปลว่า consumer ช้าเกินไปหรือ queue ไม่มีขอบเขต บทเรียนถัดไปจะพูดถึงว่า publisher-blocking รู้สึกยังไงและออกแบบเลี่ยงอย่างไร