เจาะลึกวิกฤตระบบล่ม: เมื่อ Event Hub พาร์ทิชันเดียวกลายเป็นคอขวด
บทเรียนราคาแพงจากเหตุการณ์ระบบฮาร์ทบีทพุ่งกระฉูดในเดือนมกราคม 2026 พร้อมวิธีแก้ด้วย KEDA และ Azure Container Apps

ภาพประกอบจากคลังภาพสต็อก ไม่ใช่ภาพจากเหตุการณ์จริง
- เหตุการณ์ความผิดปกติเริ่มขึ้นในวันที่ 5 มกราคม 2026 เวลาประมาณ 7:00 น. ตามเวลา PST
- ปริมาณอีเวนต์พุ่งสูงขึ้นถึง 8 เท่า และจำนวนการเชื่อมต่อ SignalR พุ่งขึ้น 11 เท่าจากภาวะปกติ
- ต้นตอมาจาก 507 เซสชันซอมบี้และบัญชีผู้ใช้งานเดียวที่สร้างโหลดกว่า 33% ของทราฟฟิกทั้งหมด
- แก้ปัญหาเร่งด่วนด้วยการปรับระยะเวลาฮาร์ทบีทจาก 30 วินาทีเป็น 90 วินาทีเพื่อลดทราฟฟิก
นี่คือเรื่องราวส่วนที่สามของซีรีส์ User Connectivity Architecture ซึ่งย้อนกลับไปดูสถาปัตยกรรมระบบเดิมที่ประกอบด้วยการส่งสัญญาณฮาร์ทบีทตามเวลาที่กำหนด, Event Hub, เวิกเกอร์ที่คอยเขียนเซสชันลงใน Redis และการหมดอายุของคีย์ Redis ที่ทำหน้าที่ประเมินสถานะออนไลน์หรือออฟไลน์ของสถานที่ต่างๆ โดยในระบบปกติ API จะเป็นผู้กำหนดความถี่ในการเรียกใช้งานของไคลเอนต์ ซึ่งค่าเริ่มต้นถูกตั้งไว้ที่ทุกๆ 30 วินาที หลังจากระบบนี้รันบนโปรดักชันมานานถึงสองปี เดือนมกราคม 2026 กลับกลายเป็นช่วงเวลาที่ระบบต้องเผชิญกับบททดสอบครั้งใหญ่เมื่อทราฟฟิกฮาร์ทบีทเกิดความผิดปกติอย่างรุนแรงยาวนานราวสี่สัปดาห์เต็ม
ความโกลาหลเริ่มต้นขึ้นในวันที่ 5 มกราคม 2026 เวลาประมาณ 7:00 น. ตามเวลา PST เมื่อกราฟปริมาณทราฟฟิกไม่ได้อยู่ในระดับปกติอีกต่อไป ปริมาณอีเวนต์พุ่งสูงขึ้นถึง 8 เท่าภายในเวลาเพียงหนึ่งชั่วโมงและยังคงทะยานขึ้นต่อเนื่อง ขณะเดียวกันจำนวนการเชื่อมต่อผ่าน SignalR ก็พุ่งสูงขึ้นถึง 11 เท่า ซึ่งหมายความว่าระบบต้องคอยติดตาม รักษาการเชื่อมต่อ และรายงานสถานะของเซสชันเบราว์เซอร์จำนวนมหาศาลตลอดเวลาโดยไม่มีทีท่าว่าจะลดลงจนทีมงานต้องเร่งสืบหาต้นตออย่างเร่งด่วน
เมื่อแกะรอยจนพบสาเหตุ ทีมงานพบว่าปัญหามาจาก 507 เซสชันซอมบี้ที่ไม่ยอมตัดการเชื่อมต่อและรันโค้ดไคลเอนต์รุ่นเก่าที่ถูกแคชไว้ รวมถึงบัญชีผู้ใช้งานเพียงบัญชีเดียวที่สร้างภาระให้กับระบบ API สูงถึง 33% ของทราฟฟิกทั้งหมด แต่ประเด็นสำคัญที่แท้จริงกลับอยู่ที่สถาปัตยกรรมเบื้องหลัง ในระบบ Azure Event Hubs จำนวนพาร์ทิชันคือตัวกำหนดความสามารถในการอ่านข้อมูลแบบขนาน ภายในคอนซูเมอร์กรุ๊ปหนึ่งพาร์ทิชันจะถูกถือครองโดยโปรเซสเซอร์เพียงตัวเดียวในแต่ละช่วงเวลา หากมีเพียงหนึ่งพาร์ทิชันก็จะมีเพียงหนึ่งช่องทาง ไม่ว่าระบบจะมีอินสแตนซ์เพิ่มขึ้น ใช้ซีพียูสูงขึ้น หรือโค้ดจะดีแค่ไหนก็ไม่สามารถช่วยได้

ภาพประกอบจากคลังภาพสต็อก ไม่ใช่ภาพจากเหตุการณ์จริง
การวิเคราะห์เพิ่มเติม: ปัญหาคอขวดของพาร์ทิชันเดี่ยวเปรียบเสมือนถนนที่มีเพียงเลนเดียว แม้จะมีรถวิ่งมาจำนวนมากแต่ก็ต้องเข้าแถวรอทีละคัน การออกแบบระบบสตรีมมิ่งข้อมูลจึงจำเป็นต้องคำนึงถึงการกระจายโหลด (Partitioning) ตั้งแต่เริ่มต้น เพื่อป้องกันไม่ให้ทราฟฟิกจากจุดใดจุดหนึ่งมาบล็อกการทำงานทั้งหมดของระบบ
ในขณะที่อีเวนต์ไหลเข้ามามากกว่าหนึ่งร้อยรายการต่อวินาที แต่โปรเซสเซอร์ HeartbeatMonitor กลับต้องประมวลผลแบบเรียงแถวทีละรายการ ส่งผลให้สถานะการเชื่อมต่อที่โรงพยาบาลและหน่วยแพทย์ฉุกเฉินต้องพึ่งพานั้นเกิดความล่าช้า ไม่เพียงเท่านั้น แผนการใช้งานแบบ Consumption Plan ยังทำให้เกิดปัญหาการขาดแคลนพอร์ต SNAT เนื่องจากทราฟฟิกมหาศาลทำให้พอร์ตขาออกถูกใช้งานเร็วกว่าอัตราการปล่อย ส่งผลให้การเชื่อมต่อใหม่เกิดความล่าช้า ไคลเอนต์พยายามลองเชื่อมต่อซ้ำจนยิ่งเพิ่มโหลดให้ระบบกลายเป็นวงจรอุบาทว์ที่ทำลายตัวเอง
ก่อนที่จะเริ่มทำการเขียนโค้ดใหม่ ทีมงานจำเป็นต้องประคับประคองสถานการณ์ให้รอดพ้นจากวิกฤตนี้ก่อน โดยเลือกใช้วิธีแก้ปัญหาเฉพาะหน้าด้วยการปรับค่าช่วงเวลาฮาร์ทบีทที่ส่งจาก API ไปยังไคลเอนต์ จากเดิม 30 วินาทีให้ขยับขึ้นเป็น 90 วินาที ซึ่งช่วยลดปริมาณอีเวนต์ขาเข้าลงได้ราวสองในสามโดยไม่ต้องทำการอัปเดตแอปพลิเคชันฝั่งไคลเอนต์แต่อย่างใด แม้จะทำให้ข้อมูลสถานะความเชื่อมต่อมีความละเอียดลดลงบ้าง แต่ก็ช่วยยื้อชีวิตให้ระบบยังคงทำงานต่อไปได้ระหว่างที่กำลังพัฒนาแนวทางแก้ไขระยะยาว
สำหรับการแก้ปัญหาที่โครงสร้างพื้นฐาน ทีมงานได้สร้าง Event Hub ตัวใหม่ชื่อว่า heartbeat-p8 ซึ่งกำหนดพาร์ทิชันไว้จำนวน 8 พาร์ทิชัน พร้อมทั้งสร้างคอนซูเมอร์กรุ๊ปเฉพาะสำหรับ heartbeat-monitor เพื่อให้กระบวนการทำงานสามารถประมวลผลแบบขนานได้ถึง 8 สตรีมพร้อมกัน ลดความเสี่ยงที่ทราฟฟิกหนาแน่นจากจุดเดียวจะส่งผลกระทบต่อพายป์ไลน์ทั้งหมด โดยมีเครื่องมืออย่าง KEDA คอยทำหน้าที่ตรวจสอบจำนวนอีเวนต์ที่ค้างอยู่ใน Event Hub และปรับลดหรือเพิ่มจำนวนรีพลีกาของเวิร์กเกอร์ให้สอดคล้องโดยอัตโนมัติ โดยมีการกำหนดค่า maxReplicas ให้เท่ากับจำนวนพาร์ทิชันพอดีเพื่อประสิทธิภาพสูงสุด
ที่มา: Dev.to
พบข้อมูลผิดพลาดในบทความนี้? แจ้งปัญหาบทความนี้
ความคิดเห็น
แสดงความคิดเห็น