คู่มือเกมแลค › L9 โปรเซสเกมฝั่งเซิร์ฟเวอร์
thread pool หมด Thread pool starvation
ID สาเหตุ sp-threadpool · ผู้รับผิดชอบหลัก พัฒนาเซิร์ฟเวอร์ (ทีมพัฒนาเกม)
เปิดการ์ดในฉบับหลักที่มีภาพและการทดลอง →
ถ้า worker thread ที่ประมวลผลงานติดอยู่กับงานช้าทั้งหมด คำขอใหม่จะต้องรอไปเรื่อย ๆ อย่างไม่มีกำหนด
ทำไม worker thread ติดรอการตอบกลับจาก API ภายนอกหรือ DB → ผลคือ ไม่มีเธรดว่างรับคำขอใหม่ → บนหน้าจอ บางฟีเจอร์ เช่น ล็อกอินหรือร้านค้า โหลดไม่จบ
- อาการ
- เข้าเกมไม่ได้/โหลดไม่จบ, อินพุตดีเลย์, ค้าง
- ปัจจัย
- การหยุดชะงัก
- ใครเจอ
- เฉพาะบางฟีเจอร์, ทั้งเซิร์ฟเวอร์
- เกิดเมื่อไร
- ตอนคนแห่มารวมกัน, หลังล็อกอิน/หลังปิดปรับปรุง
- ผู้รับผิดชอบ
- ผู้รับผิดชอบหลัก พัฒนาเซิร์ฟเวอร์ (ทีมพัฒนาเกม)
- งานฝั่งทีมพัฒนาเกม
- ตั้งไทม์เอาต์ให้การเรียกที่ช้า, แยก thread pool ตามฟีเจอร์, เปลี่ยนเป็นแบบ asynchronous
- บนกราฟ
- ชนเพดานแล้วแบนราบ · จำนวนเธรดและความยาวคิวของ thread pool, เวลาประมวลผลคำขอ
- จุดที่ต้องดู
- สำหรับ .NET ดูจำนวนเธรดและความยาวคิวของ thread pool ใน dotnet-counters monitor (.NET 9 ขึ้นไปคือ dotnet.thread_pool.thread.count และ dotnet.thread_pool.queue.length, 8 ลงไปคือ ThreadPool Thread Count และ ThreadPool Queue Length) และดูว่า worker thread รออยู่ที่ไหนด้วย dotnet-stack สำหรับ JVM และเซิร์ฟเวอร์ native ดูแบบเดียวกันจาก thread dump
- สัญญาณว่าใช่
- อัตราการใช้ CPU ต่ำกว่า 100% มาก แต่จำนวนเธรดค่อย ๆ เพิ่มขึ้นเรื่อย ๆ หรือติดเพดาน คิวสะสม และ worker ส่วนใหญ่รอการตอบกลับจากการเรียกภายนอกตัวเดียวกัน (DB, HTTP)
- สัญญาณว่าไม่ใช่
- คิวว่างแต่ยังช้า: ปลายทางที่เรียกช้าเอง น่าจะเป็นความล้มเหลวแบบลูกโซ่หรือการพึ่งพาเซอร์วิสภายนอก
- วิธีตรวจ
- ใช้เครื่องมือฝั่งอินฟรา (ไม่ต้องใช้โค้ดเกม)
- รายละเอียดเพิ่มเติม
- ถ้าการรับแพ็กเก็ตกับลอจิกเกมใช้ worker thread pool เดียวกัน ทันทีที่งานช้าไม่กี่งานถือครอง worker ทั้งหมด การประมวลผลแพ็กเก็ตของทั้งเซิร์ฟเวอร์จะหยุด
- กรณีจริง
- Riot Games 2021: League of Legends EUW ขัดข้อง 5 ชั่วโมง: DB เสริมตัวเดียวทำให้ทั้งเซิร์ฟเวอร์หยุด
แหล่งอ้างอิง
- Debug ThreadPool Starvation Microsoft
เมื่อ pool ไม่มีเธรดเหลือและงานใหม่ต้องรอ การตอบสนองจะช้าลง ต้นเหตุคือโค้ดแบบ blocking ที่ถือครองเธรด ใน dotnet-counters ถ้า CPU ต่ำกว่า 100% มากแต่ dotnet.thread_pool.thread.count ค่อย ๆ เพิ่มเรื่อย ๆ คือสัญญาณว่าหมด (dotnet.thread_pool.queue.length มักสูงด้วย), ดูจุดที่เธรดรอด้วย dotnet-stack - Avoiding insurmountable queue backlogs AWS
จำนวนงานพร้อมกัน = อัตราการเข้ามา × ความหน่วง (กฎของ Little) ที่ 100 คำขอต่อวินาที ถ้าความหน่วงเพิ่มจาก 100 ms เป็น 10 วินาที เธรด 10 ตัวจะกลายเป็น 1,000 ตัวจน pool หมด - Bulkhead Pattern Microsoft Azure
ถ้าแยก connection pool และ thread pool ไว้ต่อปลายทางที่เรียก ความขัดข้องของปลายทางหนึ่งจะบล็อกแค่ pool ของมันเอง - .NET runtime metrics .NET
dotnet.thread_pool.thread.count (จำนวนเธรดของ thread pool) และ dotnet.thread_pool.queue.length (จำนวนงานที่รออยู่) มีตั้งแต่ .NET 9 - Well-known EventCounters in .NET Microsoft
ThreadPool Thread Count (threadpool-thread-count) และ ThreadPool Queue Length (threadpool-queue-length) ของ .NET 8 ลงไป
สาเหตุที่ควรดูประกอบ
ชั้นเดียวกัน: L9 โปรเซสเกมฝั่งเซิร์ฟเวอร์
สาเหตุจากชั้นอื่นที่ทำให้เกิดอาการเดียวกัน (เข้าเกมไม่ได้/โหลดไม่จบ)
ดูการ์ดในฉบับหลักที่มีภาพและการทดลอง