พูดถึงความสามารถของ RabbitMQ


จากที่เคยพูดถึง kafka ไป; ตัว RabbitMQ เองก็เป็นหนึ่งในเครื่องมือที่เอาไว้ใช้ทำ Message Queue; ใน Kafka จะจัดงานโดยใช้เรื่อง Partition มาช่วยแต่ใน RabbitMQ นั้นจะมีวิธีจัดการที่ต่างออกไป

ใน RabbitMQ เราจะให้แบ่งออกเป็นสี่ส่วน ก็คือ Producer, Exchange, Queue และ Consumer (Channel)

Producer ก็เป็นคนส่งข้อมูลและ Consumer ก็คือคนรับข้อมูลเหมือนเดิม; Producer นั้นจะไม่ได้ส่งข้อมูลมาที่ Queue ตรง ๆ ให้ Consumer ใช้ แต่จะผ่าน Exchange ก่อน;

Exchange จะทำการดูแลเรื่อง routing ว่าข้อมูลควรจะถูกส่งไปที่ Queue ตัวไหนก่อนที่จะให้ Consumer ดึงข้อมูลจาก Queue อีกที

Queue สามารถควบคุมได้ว่าจะให้ consumers อ่านข้อมูลได้ 1 consumer หรือหลาย consumers ได้โดยการตั้งค่าเรื่อง exclusive; กรณีที่ Queue ตัวนึงถูก consumers อ่านหลายตัว ข้อมูลที่เข้ามาตัวนึงใน queue นั้นจะไม่ได้แชร์ส่งไปให้ consumers ทุกตัว แต่จะใช้ระบบ round robin คือวนแจกข้อมูลไปให้กับ consumers แต่ละตัวในที่อ่านใน queue เดียวกัน; กล่าวก็คือ consumer ตัวนึงจะได้อ่านข้อมูลอีกครั้งเมื่อข้อมูลผ่านไป N ตัว (เมื่อ N คือจำนวน consumers ใน queue ณ ขณะนั้น)

เสริม เราสามารถตั้งค่าให้ consumer ได้อ่านข้อมูลจาก Queue ทีละตัวโดยที่ไม่ดึงข้อมูลมาที่ consumer ล่วงหน้า (ที่เป็นค่าเริ่มต้น) เนื่องจาก round robin จะไม่รู้ว่า consumers นั้นจัดการกับข้อมูลแต่ละตัวเสร็จแล้วหรือยัง และจะให้ข้อมูลไปทิ้งไว้ที่ consumers ล่วงหน้า ทำให้มี consumer บางตัวทำงานหนักเกินไปได้; เราจึงมีการตั้งค่าเพื่อป้องกันไม่ให้ consumer ตัวนึงมีงานกองมากเกินไป โดยจะให้ consumer นั้นดึงข้อมูลก็ต่อเมื่อจัดการกับข้อมูลปัจจุบันเรียบร้อยแล้ว; ตรงนี้จะเรียกว่า Quality of Service

Exchange กับ Queue

ข้อมูลที่ส่งมาจาก Producer จะดูแลเรื่องการ routing ข้อมูลที่จะส่งไปให้ที่ queue; เบื้องต้นในการทำงานจะเป็นนี้

  • สร้าง Exchange และกำหนดประเภทของ Exchange ตัวนั้น (จะอธิบายแต่ละประเภทต่อไป)
  • สร้าง Queue แล้ว bind เข้ากับ Exchange แล้วกำหนด preferred routing key (binding key) ให้กับ Queue
  • Queue นั้นสามารถ bind กับ Exchange ได้หลายครั้งเพื่อเพิ่ม routing key หรือจะ bind กับ Exchange ตัวอื่นก็ได้
  • consumers เลือก Queue ที่จะอ่าน
  • producer ปล่อยข้อมูลโดยกำหนด exchange เป้าหมายและ routing key ที่จะส่ง; หาก exchange นั้นมี queue ที่ bind ด้วย routing key ตรงกันข้อมูลจะส่งไปให้ queue ตัวนั้น (อาจจะ queue หลายตัวที่ routing key ตรงกันก็จะคัดลอกข้อมูลไปให้ทุก queue)

ต่อไปจะเป็นเรื่องประเภทของ Exchange ว่ากำหนด routing อย่างไร

  • Fanout ตัวนี้จะไม่มีการกำหนดค่า routing key; ข้อมูลที่ถูกเข้ามาที่ exchange ประเภทนี้จะถูกส่งให้กับ queue ทุกตัวที่ bind อยู่กับ exchange โดยอัตโนมัติ ถึงแม้ว่าจะกำหนด routing key ก็จะไม่มีผล
  • Direct ตัวนี้นั้นมีการกำหนด routing key ถ้าหาก producer ส่งข้อมูลมาที่ exchange และมีการกำหนด routing key ตรงกับ routing key ที่ queue ทำการ bind ไว้กับ exchange (exact match) แล้ว queue ตั้วนั้นจะได้ข้อมูลไป
  • Topic เหมือนกับ Direct เพียงแต่การกำหนด routing key ของฝั่ง queue นั้นจะเป็นอิสระกว่า เช่นการใช้ # แทนคำศูนย์คำหรือมากกว่าและ * สำหรับ 1 คำ; เช่น routing key ที่ bind ไว้เป็น *.juice แล้ว producer ที่ส่งมาแล้วกำหนด routing key เป็น orange.juice ก็จะส่งไปหาได้ แต่ถ้าเป็น apple.pen ก็จะไม่ถูกส่ง (ต้องเป็นคำอะไรก็ได้ตามด้วย .juice)

RabbitMQ นั้นมีระบบสำหรับตอบกลับข้อมูลที่ส่งมาโดยการกำหนดชื่อ queue ที่จะให้ตอบกลับผ่าน reply to ตอนที่ส่งข้อมูลมา แล้ว consumer ก็จะใช้ชื่อ queue นั้นตอบกลับไป (อาจมีการกำหนด correlation id เพื่อระบุตัวตน)