TTL & Limits
queue โตไปเรื่อย ๆ ไม่ได้
หัวข้อที่มีชื่อว่า “queue โตไปเรื่อย ๆ ไม่ได้”ถ้า producer เร็วกว่า consumer queue จะโตแบบไม่มีขอบเขตจนกิน memory หรือ disk ของ broker — แล้วทุกอย่างก็หยุดชะงัก TTL และ length limit คือราวกันตกที่ใส่เพดานให้การโตนั้น และให้คุณตัดสินใจว่า จะทิ้งอะไร แทนที่จะล้มทั้งระบบ
TTL — message ที่หมดอายุ
หัวข้อที่มีชื่อว่า “TTL — message ที่หมดอายุ”TTL (time-to-live) ทำให้ message หมดอายุหลังจากจำนวนมิลลิวินาทีที่ตั้งไว้ ตั้งได้สองแบบ:
- ต่อ queue (
x-message-ttl) — ทุก message ใน queue หมดอายุหลัง N ms - ต่อ message (property
expiration) — message ตัวนี้โดยเฉพาะหมดอายุหลัง N ms
เมื่อ message หมดอายุ RabbitMQ จะลบออกจาก queue ที่สำคัญคือ ถ้า queue มี dead-letter exchange message ที่หมดอายุจะถูก dead-letter แทนที่จะถูกทิ้งเงียบ ๆ — ที่เป็นพื้นฐานทั้งหมดของทริค delayed-retry ด้านล่าง
Queue TTL (x-expires) ต่างออกไป: ตัวนี้ลบ ทั้ง queue หลังจาก queue ไม่ถูกใช้ (ไม่มี consumer, ไม่มี get) เป็นเวลา N ms มีประโยชน์สำหรับเก็บกวาด queue ชั่วคราว
length limit — จำกัด backlog
หัวข้อที่มีชื่อว่า “length limit — จำกัด backlog”x-max-length จำกัดจำนวน message (หรือ x-max-length-bytes จำกัดขนาดรวม) เมื่อ queue เต็มและมี message ใหม่มาถึง พฤติกรรม overflow ตัดสินว่าอะไรจะยอม:
drop-head(default) — ทิ้ง message ที่เก่าที่สุดเพื่อเปิดที่ให้ตัวใหม่reject-publish— reject message ตัวใหม่ (บอก publisher ได้ผ่าน publisher confirms)
การเลือกระหว่างสองแบบเป็นการตัดสินใจจริง: drop-head เอาข้อมูลสดไว้ก่อน (ดีสำหรับ live metrics), reject-publish เลือกไม่ทำอะไรหายและ push back ไปที่ producer (ดีสำหรับงานที่ทิ้งไม่ได้)
declare queue พร้อม TTL และ length cap
หัวข้อที่มีชื่อว่า “declare queue พร้อม TTL และ length cap”await channel.assertQueue('events', { durable: true, arguments: { 'x-message-ttl': 60000, // messages expire after 60s 'x-max-length': 10000, // keep at most 10k messages 'x-overflow': 'reject-publish', // reject new ones when full },});channel.queue_declare( queue="events", durable=True, arguments={ "x-message-ttl": 60000, # messages expire after 60s "x-max-length": 10000, # keep at most 10k messages "x-overflow": "reject-publish", # reject new ones when full },)args := amqp.Table{ "x-message-ttl": int32(60000), // messages expire after 60s "x-max-length": int32(10000), // keep at most 10k messages "x-overflow": "reject-publish", // reject new ones when full}ch.QueueDeclare("events", true, false, false, false, args)ทริค: TTL + DLX = delayed retry
หัวข้อที่มีชื่อว่า “ทริค: TTL + DLX = delayed retry”นี่คือเหตุผลที่ TTL สำคัญเกินกว่าการเก็บกวาด ใส่ TTL บน queue ที่ ไม่มี consumer แล้วชี้ dead-letter exchange ของตัวเองกลับไปที่ main queue ของคุณ message ที่ส่งไปที่นั่นจะนั่งรอตาม TTL หมดอายุ แล้วถูก dead-letter กลับเข้า flow หลัก — เป็น delay โดยไม่ต้องมี scheduler
flowchart LR main["main queue"] -->|"fail, ส่งไป retry"| retry["retry queue (TTL 30s, ไม่มี consumer)"] retry -->|"TTL หมดอายุ → dead-letter"| main main --> worker["consumer"]
นี่คือวิธีมาตรฐานของ RabbitMQ ในการทำ retry-with-backoff และโมดูล Reliability กับ Consumer Patterns ต่อยอดจากทริคนี้โดยตรง