ข้ามไปยังเนื้อหา

Flow Control & Alarms

queue จะแข็งแรงได้ก็ต่อเมื่อ consumer ตาม producer ทัน ในระยะยาว เมื่อ publisher วิ่งเร็วกว่า consumer อย่างต่อเนื่อง backlog จะโต, memory จะเต็ม และต้องมีอะไรสักอย่างยอมแตก RabbitMQ มีกลไกหลายอย่าง — ตั้งแต่นุ่มนวลไปถึงเด็ดขาด — เพื่อกัน broker ที่ overload ไม่ให้ crash

คุณเจอ 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 ทำงานต่อ"]
alarm ดัน backpressure กลับไปที่ publisher

นี่คือ backpressure โดยตั้งใจ: แทนที่จะรับ message จนตัวเองตาย broker ดันแรงกดกลับไปที่ producer producer ที่ประพฤติดีจะสังเกตว่าถูก block (client มีสัญญาณ “connection blocked”) แล้วชะลอตัว ส่วนตัวที่ประพฤติไม่ดีก็แค่กอง publish ที่ถูก block ไว้ ไม่ว่าทางไหน broker ก็รอด

ก่อนจะถึง alarm ระดับ global ด้วยซ้ำ RabbitMQ ใช้ internal flow control ต่อ connection: ถ้า publisher ส่งเร็วกว่าที่ broker จะ route และ persist ได้ broker จะ throttle connection นั้นโดยเฉพาะเพื่อไม่ให้ publisher ถล่ม pipeline ภายใน ใน management UI connection แบบนี้จะแสดงสถานะ flow — เป็นสัญญาณปกติที่บอกว่า publisher นี้กำลังถูกจังหวะ ไม่ใช่ error

โดย 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 และ 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 จะทำงาน
RabbitMQ ทำอะไรกับ publisher เมื่อ memory หรือ disk alarm ทำงาน?
connection แสดงสถานะ "flow" ใน management UI หมายความว่าอะไร?
lazy queue (และ classic v2 / quorum storage) แก้ปัญหาอะไร?
วิธีที่ดีที่สุดในการทำให้ alarm และ flow control เกิดยากคืออะไร?