Flow Control & Alarms
ความไม่สมดุลพื้นฐาน
หัวข้อที่มีชื่อว่า “ความไม่สมดุลพื้นฐาน”queue จะแข็งแรงได้ก็ต่อเมื่อ consumer ตาม producer ทัน ในระยะยาว เมื่อ publisher วิ่งเร็วกว่า consumer อย่างต่อเนื่อง backlog จะโต, memory จะเต็ม และต้องมีอะไรสักอย่างยอมแตก RabbitMQ มีกลไกหลายอย่าง — ตั้งแต่นุ่มนวลไปถึงเด็ดขาด — เพื่อกัน broker ที่ overload ไม่ให้ crash
alarm block publisher (backpressure โดยตั้งใจ)
หัวข้อที่มีชื่อว่า “alarm block publisher (backpressure โดยตั้งใจ)”คุณเจอ alarm ไปแล้วในบทที่แล้ว นี่คือว่า รู้สึก ยังไง เมื่อ memory high-watermark หรือ limit ของ disk ว่างถูกข้าม RabbitMQ จะยก alarm และ block ทุก publishing connection publisher จะถูกหยุด — การเรียก publish จะไม่คืบหน้า — ขณะที่ consumer ยังไหล queue ออกต่อ
flowchart TB fast["Publisher (เร็วเกินไป)"] --> q["Queue เต็ม memory สูงขึ้น"] q --> alarm["ข้าม memory high-watermark → ALARM"] alarm --> block["publishing connection ถูก BLOCK"] cons["Consumer ยังไหล ออกต่อ"] --> q block --> recover["memory ลด → alarm เคลียร์ → publisher ทำงานต่อ"]
นี่คือ backpressure โดยตั้งใจ: แทนที่จะรับ message จนตัวเองตาย broker ดันแรงกดกลับไปที่ producer producer ที่ประพฤติดีจะสังเกตว่าถูก block (client มีสัญญาณ “connection blocked”) แล้วชะลอตัว ส่วนตัวที่ประพฤติไม่ดีก็แค่กอง publish ที่ถูก block ไว้ ไม่ว่าทางไหน broker ก็รอด
per-connection flow control
หัวข้อที่มีชื่อว่า “per-connection flow control”ก่อนจะถึง alarm ระดับ global ด้วยซ้ำ RabbitMQ ใช้ internal flow control ต่อ connection: ถ้า publisher ส่งเร็วกว่าที่ broker จะ route และ persist ได้ broker จะ throttle connection นั้นโดยเฉพาะเพื่อไม่ให้ publisher ถล่ม pipeline ภายใน ใน management UI connection แบบนี้จะแสดงสถานะ flow — เป็นสัญญาณปกติที่บอกว่า publisher นี้กำลังถูกจังหวะ ไม่ใช่ error
lazy queue และ backlog ขนาดใหญ่
หัวข้อที่มีชื่อว่า “lazy queue และ backlog ขนาดใหญ่”โดย default classic queue พยายามเก็บ message ไว้ใน memory เพื่อความเร็ว queue ที่ลึกมาก (message เป็นล้าน) จึงกิน RAM เยอะและอาจ trip memory alarm lazy queue (และ storage แบบ classic-queue v2 ตัวใหม่) เก็บ message ไว้บน disk แทน แลก latency นิดหน่อยกับ memory footprint ที่เล็กลงมาก — เป็นตัวเลือกที่ถูกเมื่อ backlog โตได้ ส่วน quorum queue เก็บบน disk เสมอและรับมือ backlog ลึก ๆ ได้ดี
ออกแบบให้ alarm เกิดยาก
หัวข้อที่มีชื่อว่า “ออกแบบให้ alarm เกิดยาก”alarm และ flow control เป็นตาข่ายกันตก ไม่ใช่โหมดการทำงานปกติ ถ้าทำงานสม่ำเสมอ แปลว่าออกแบบผิด วิธีทำให้เกิดยาก:
- scale consumer ให้ ack rate เท่ากับ publish rate ในระยะยาว
- bound queue ด้วย
max-lengthหรือ TTL เพื่อไม่ให้ producer ที่หลุดควบคุมโต queue ได้ไม่จำกัด (drop หรือ dead-letter ส่วนที่ล้นแทน) - ใช้ lazy หรือ quorum queue สำหรับงานที่ backlog โตลึกได้จริง
- จัดการ “connection blocked” ใน producer — ถอยแทนที่จะกระหน่ำ
- alert เมื่อ queue depth ไต่ขึ้น เพื่อ scale consumer ก่อน memory alarm จะทำงาน