คู่มือเกมแลค › L13 สถาปัตยกรรมเซิร์ฟเวอร์และการดูแลระบบ
ความล้มเหลวแบบลูกโซ่ Cascading failure
ID สาเหตุ in-cascade · ผู้รับผิดชอบหลัก พัฒนาเซิร์ฟเวอร์ (ทีมพัฒนาเกม) · ร่วมกับ อินฟราเครือข่าย (ทีมอินฟรา)
เปิดการ์ดในฉบับหลักที่มีภาพและการทดลอง →
เมื่อเซอร์วิสหนึ่งช้าลง เซิร์ฟเวอร์ที่เรียกใช้เซอร์วิสนั้นจะติดอยู่กับการรอคำตอบ จนฟีเจอร์ที่ไม่เกี่ยวข้องก็หยุดทำงานไปด้วย
ทำไม เซอร์วิสหนึ่ง เช่น DB หรือระบบยืนยันตัวตน ช้าลง → ผลคือ เธรดและการเชื่อมต่อของเซิร์ฟเวอร์ที่เรียกใช้ติดอยู่กับการรอคำตอบ และการลองส่งคำขอที่ล้มเหลวใหม่ยิ่งเพิ่มโหลด → บนหน้าจอ ฟีเจอร์ที่ดูไม่เกี่ยวข้องก็ช้าลงหรือค้างไปหมด
- อาการ
- ค้าง, อินพุตดีเลย์, เข้าเกมไม่ได้/โหลดไม่จบ
- ปัจจัย
- การหยุดชะงัก
- ใครเจอ
- ทั้งเซิร์ฟเวอร์
- เกิดเมื่อไร
- ตอนคนแห่มารวมกัน, สุ่มเป็นครั้งคราว
- ผู้รับผิดชอบ
- ผู้รับผิดชอบหลัก พัฒนาเซิร์ฟเวอร์ (ทีมพัฒนาเกม) · ร่วมกับ อินฟราเครือข่าย (ทีมอินฟรา)
- งานฝั่งทีมพัฒนาเกม
- ตั้งไทม์เอาต์ให้ทุกการเรียก, ใช้ circuit breaker, แยกส่วนตามฟีเจอร์ (bulkhead), ลองใหม่โดยเว้นช่วงห่างขึ้นเรื่อย ๆ และจำกัดจำนวนครั้ง, แยกการตอบ health check ออกจากงานที่หนัก
- งานฝั่งทีมอินฟรา
- ตั้งจำนวนครั้งที่ล้มเหลวและช่วงห่างของ health check บนโหลดบาลานเซอร์ให้มีระยะเผื่อ เพื่อไม่ให้ถอดเซิร์ฟเวอร์ที่ช้าแค่ชั่วครู่ออกทันที, จำกัดจำนวนเซิร์ฟเวอร์ที่ถูกถอดออกพร้อมกัน
- บนกราฟ
- ชนเพดานแล้วแบนราบ · เวลาตอบสนองและอัตราข้อผิดพลาดแยกตามเซอร์วิส, จำนวนเธรด/การเชื่อมต่อที่ใช้อยู่
- จุดที่ต้องดู
- วางเวลาตอบสนอง, อัตราข้อผิดพลาด และจำนวนการลองใหม่ของแต่ละเซอร์วิสบนหน้าจอเดียวโดยให้แกนเวลาตรงกัน แล้วหาจุดที่ช้าลงก่อน ถ้าอยู่หลังโหลดบาลานเซอร์ ให้ดูเวลาตอบสนองของ target (AWS ALB คือ TargetResponseTime), จำนวน 5xx ของ target (HTTPCode_Target_5XX_Count) และจำนวน target ที่ถูกถอดเพราะผิดปกติ (UnHealthyHostCount)
- สัญญาณว่าใช่
- ดีเลย์ของเซอร์วิสหนึ่งขึ้นก่อน ตามด้วยจำนวนเธรด/การเชื่อมต่อของฝั่งที่เรียกใช้ชนเพดาน error ลามไปเซอร์วิสอื่น และจำนวนการลองใหม่กับจำนวน target ที่ถูกถอดเพิ่มขึ้นพร้อมกัน
- สัญญาณว่าไม่ใช่
- หลายเซอร์วิสช้าลงพร้อมกันในจังหวะเดียวกัน: ให้ดูเหตุขัดข้องของทรัพยากรที่ใช้ร่วมกัน (DB, เครือข่าย, โฮสต์) ก่อน
- วิธีตรวจ
- ใช้เครื่องมือฝั่งอินฟรา (ไม่ต้องใช้โค้ดเกม)
- รายละเอียดเพิ่มเติม
- health check (การตรวจว่าเซิร์ฟเวอร์ยังทำงานอยู่) ก็ทำให้ลูกโซ่ลามหนักขึ้นได้ ถ้าเซิร์ฟเวอร์ที่งานล้นมือตอบการตรวจช้า โหลดบาลานเซอร์จะถอดเซิร์ฟเวอร์ที่ยังใช้งานได้ออก ทราฟฟิกนั้นจึงไหลไปรวมที่เซิร์ฟเวอร์ที่เหลือ และเซิร์ฟเวอร์ถัดไปก็ช้าตาม
- กรณีจริง
- Riot Games 2020: โฮสต์ edge ของเซิร์ฟเวอร์ League of Legends ยุโรปและบราซิลโหลดเกิน
Riot Games 2021: League of Legends EUW ขัดข้อง 5 ชั่วโมง: DB เสริมตัวเดียวทำให้ทั้งเซิร์ฟเวอร์หยุด
Roblox 2021: Roblox ล่ม 73 ชั่วโมง: การแย่งทรัพยากรในคลัสเตอร์ service discovery (Consul)
AWS 2021: เครือข่ายภายในของ AWS us-east-1 แออัด
AWS 2025: DNS ของ DynamoDB ใน AWS us-east-1 ขัดข้อง และการกู้คืนที่ยืดเยื้อ
แหล่งอ้างอิง
- Site Reliability Engineering, Chapter 22: Addressing Cascading Failures Google
เซิร์ฟเวอร์ที่โหลดเกินไม่ผ่าน health check แล้วถูกถอดออก โหลดจึงไปรวมที่เซิร์ฟเวอร์ที่เหลือ และการลองใหม่ยิ่งเพิ่มโหลด, แนะนำให้จำกัดจำนวนครั้งที่ลองใหม่, ใช้ exponential backoff แบบสุ่ม และกำหนด deadline - Circuit Breaker Pattern Microsoft Azure
คำขอที่ถูกบล็อกจนถึงไทม์เอาต์ถือครองเธรดและการเชื่อมต่อ DB ทำให้ฟีเจอร์ที่ไม่เกี่ยวข้องล้มเหลวไปด้วย, ถ้าความล้มเหลวสะสมถึงเกณฑ์ภายในเวลาที่กำหนด ให้ปฏิเสธการเรียกทันที - Timeouts, retries, and backoff with jitter AWS
Amazon Builders' Library การเรียกต่อกัน 5 ชั้นที่แต่ละชั้นลองใหม่ 3 ครั้ง ทำให้โหลดของ DB เพิ่มเป็น 243 เท่า, ให้ลองใหม่ที่จุดเดียวและจำกัดด้วย token bucket - CloudWatch metrics for your Application Load Balancer AWS
TargetResponseTime (เวลาตั้งแต่คำขอออกจากโหลดบาลานเซอร์จนถึง target เริ่มตอบ), HTTPCode_Target_5XX_Count (จำนวน 5xx ที่ target ส่งกลับ), UnHealthyHostCount (จำนวน target ที่ผิดปกติ)
สาเหตุที่ควรดูประกอบ
ชั้นเดียวกัน: L13 สถาปัตยกรรมเซิร์ฟเวอร์และการดูแลระบบ
สาเหตุจากชั้นอื่นที่ทำให้เกิดอาการเดียวกัน (ค้าง)
ดูการ์ดในฉบับหลักที่มีภาพและการทดลอง