คู่มือเกมแลค ฉบับข้อความ
228 สาเหตุที่ทำให้เกมออนไลน์ภาพกระตุก ตัวละครวาร์ป หรือหลุด เรียงทีละชั้นตั้งแต่หน้าจอของเราไปจนถึงฐานข้อมูลบนเซิร์ฟเวอร์ รวมไว้ในฉบับข้อความนี้ ทุกสาเหตุมีอาการ, ทีมที่รับผิดชอบ (ทีมพัฒนาเกม/ทีมอินฟรา), ตัวเลข และแหล่งอ้างอิงที่เชื่อถือได้
ฉบับหลักที่มีภาพและการทดลองให้ลองปรับเองคือ คู่มือเกมแลค ฉบับนี้รวบรวมสาเหตุ คำศัพท์ และแหล่งอ้างอิงชุดเดียวกันไว้ในหน้าเดียวให้อ่านได้โดยไม่ต้องใช้ JavaScript แต่ละสาเหตุยังมีหน้าของตัวเองด้วย (c/ID.html) และมีฉบับ Markdown ไฟล์เดียวที่ llms-full.txt
สารบัญ
ค้นหาตามอาการ
แลคเริ่มต้นจากปัจจัยสี่อย่าง: ความหน่วง (ระยะทาง, คิว และเวลาประมวลผล ทำให้แพ็กเก็ตทุกตัวมาถึงช้าเท่า ๆ กัน) จิตเตอร์ (ค่าเฉลี่ยยังดีอยู่ แต่บางแพ็กเก็ตมาเร็ว บางแพ็กเก็ตมาช้า ต้นเหตุคือ Wi-Fi, เครือข่ายที่แออัด และ CPU ที่ทำงานหนัก) แพ็กเก็ตหาย (คิวที่ล้น, คลื่นรบกวน และอุปกรณ์ที่เสีย ทำให้แพ็กเก็ตถูกทิ้ง การที่เน็ตขาดไปชั่วครู่ก็นับเป็นแพ็กเก็ตหายต่อเนื่องเช่นกัน) การหยุดชะงัก (ทิกของเซิร์ฟเวอร์ช้าลงหรือหยุด (GC, ล็อก, synchronous call, โหลดเกิน) หรือเฟรมบน PC ของเราหยุด เกิดได้แม้เน็ตจะปกติดี)
กระตุก (60 สาเหตุ): การเคลื่อนไหวไม่ลื่น หยุดสั้น ๆ แล้วขยับต่อ สลับกันไปเรื่อย ๆวาร์ป (47 สาเหตุ): ตัวละครย้ายไปยังตำแหน่งที่ไกลออกไปในทีเดียว โดยไม่เห็นช่วงระหว่างทางดีดกลับ (14 สาเหตุ): ตัวละครของเรากำลังเดินหน้า แล้วโดนดึงกลับไปยังจุดที่เพิ่งผ่านมากรอเร็ว (36 สาเหตุ): หน้าจอที่หยุดไปกลับมาขยับอีกครั้ง แล้วการเคลื่อนไหว การโจมตี และดาเมจที่สะสมไว้ก็ผ่านไปอย่างรวดเร็วในทีเดียวสโลว์โมชั่น (24 สาเหตุ): ทุกอย่างเคลื่อนที่ช้าลง การร่ายสกิลและการเดินของมอนสเตอร์ดูยืดยาด ขึ้นกับการออกแบบเซิร์ฟเวอร์ บางเกมความเร็วยังเท่าเดิม และไปแสดงเป็นอาการกระตุกหรือวาร์ปแทนอินพุตดีเลย์ (76 สาเหตุ): กดแล้วต้องรอสักพักกว่าผลจะออก ตัวภาพบนจออาจยังลื่นตามปกติค้าง (67 สาเหตุ): ทุกอย่างบนจอหยุดไปชั่วครู่ (0.5 วินาทีถึงหลายวินาที) แล้วกลับมาขยับต่อกดไม่ติด/โรลแบ็ค (36 สาเหตุ): การกระทำที่ทำไปแล้วแน่ ๆ กลับไม่เกิดผล หรือผลถูกพลิกกลับหลังผ่านไปพักใหญ่หลุด (51 สาเหตุ): การเชื่อมต่อขาดระหว่างเล่น แล้วเด้งกลับไปหน้าล็อกอินหรือหน้าต่างเชื่อมต่อใหม่เข้าเกมไม่ได้/โหลดไม่จบ (45 สาเหตุ): เข้าไปในเกมไม่ได้ หรือติดอยู่ที่หน้าโหลดหรือหน้าเข้าเกมมองไม่เห็น/ตัวผี (20 สาเหตุ): NPC มอนสเตอร์ หรือผู้เล่นที่ควรจะอยู่ กลับไม่มีบนจอของเราคนเดียว หรือสิ่งที่หายไปแล้วยังเหลืออยู่บนจอของเราคนเดียว
ทีมที่รับผิดชอบและรหัสผู้รับผิดชอบ
รหัส ทีม ผู้รับผิดชอบ ขอบเขต
cliทีมพัฒนาเกม พัฒนาไคลเอนต์ โค้ดไคลเอนต์ของเกม: เฟรม, GC, การโหลด, interpolation, extrapolation, prediction และการจัดการเครือข่ายฝั่งไคลเอนต์ (รวมการส่ง heartbeat และการเชื่อมต่อใหม่อัตโนมัติ)
srvทีมพัฒนาเกม พัฒนาเซิร์ฟเวอร์ โค้ดเซิร์ฟเวอร์ของเกม: ทิก, เธรด, ล็อก, การออกแบบการซิงก์, การรับการเชื่อมต่อ (ลูป accept และอาร์กิวเมนต์ของ listen), การตอบ heartbeat และการเก็บกวาดการเชื่อมต่อที่ขาดไปแล้ว, socket option, การออกแบบคิวรีและทรานแซกชัน
netทีมอินฟรา อินฟราเครือข่าย วงจรอินเทอร์เน็ตและอุปกรณ์เครือข่ายใน IDC (สวิตช์, เราเตอร์, ไฟร์วอลล์, โหลดบาลานเซอร์, ระบบป้องกัน DDoS), network ACL, VPC routing และโหลดบาลานเซอร์บนคลาวด์, ISP และ peering
sysทีมอินฟรา อินฟราเซิร์ฟเวอร์ เครื่องเซิร์ฟเวอร์และอินสแตนซ์บนคลาวด์ (รวม security group และ connection tracking), การตั้งค่า OS และเคอร์เนล, NIC, สภาพแวดล้อมสำหรับ deploy และมอนิเตอร์
dbaทีมอินฟรา อินฟรา DB เซิร์ฟเวอร์ DB และสตอเรจ, การตั้งค่า DB, replication, การสำรองข้อมูล, เซิร์ฟเวอร์แคช
extภายนอก ภายนอก PC และเครือข่ายในบ้านของผู้เล่น, ช่วงเครือข่ายของ ISP (อยู่นอกสัญญาของเรา), ผู้ให้บริการคลาวด์ ส่วนนี้เราแก้เองโดยตรงไม่ได้ จึงรับมือด้วยการแนะนำผู้เล่น ร้องขอไปยังผู้ให้บริการ หรือหาทางเลี่ยง
L1 โปรเซสเกมฝั่งไคลเอนต์
16 สาเหตุ · บทในฉบับหลัก
ID cg-hitch · ผู้รับผิดชอบหลัก พัฒนาไคลเอนต์ (ทีมพัฒนาเกม)
เฟรมหนึ่งใช้เวลาคำนวณนานกว่าปกติหลายเท่า ภาพบนจอจึงหยุดไปครู่หนึ่ง
ทำไม เอฟเฟกต์สกิลเยอะผิดปกติ, spawn จำนวนมาก และการอัปเดต UI ทั้งหน้าจอ มารวมอยู่ในเฟรมเดียว → ผลคือ ทำไม่เสร็จภายใน 16.7 ms และกินเวลา 50–300 ms → บนหน้าจอ ภาพหยุดแวบ แล้วทุกตัวขยับไปพร้อมกันในเฟรมถัดไป
อาการ กระตุก , ค้าง
ปัจจัย การหยุดชะงัก
ใครเจอ เราคนเดียว
เกิดเมื่อไร ตอนคนแห่มารวมกัน, ตอนทำแอ็กชันบางอย่าง, สุ่มเป็นครั้งคราว
ผู้รับผิดชอบ ผู้รับผิดชอบหลัก พัฒนาไคลเอนต์ (ทีมพัฒนาเกม)
งานฝั่งทีมพัฒนาเกม แบ่งงานหนักไปทำในหลายเฟรม, ใช้ profiler หาเฟรมที่พุ่ง, จำกัดจำนวนเอฟเฟกต์
ตัวเลขที่ควรรู้ หนึ่งเฟรมที่ 60 FPS คือ 16.7 ms แค่มีเฟรมเดียวที่เกิน 50 ms ก็รู้สึกได้ง่ายว่า “กระตุก”
บนกราฟ พุ่งแบบสุ่มเป็นครั้งคราว · เฟรมไทม์
จุดที่ต้องดู ใช้ PresentMon อัดเฟรมไทม์ (FrameTime) และเวลาที่ CPU/GPU ใช้กับเฟรมนั้น (CPUBusy/GPUBusy) ระหว่างเล่น บนมือถือดูเมตริก slow sessions และ slow rendering ของ Android vitals สัญญาณว่าใช่ จังหวะที่เฟรมไทม์ซึ่งปกติอยู่ราว 16.7 ms พุ่งเกิน 50 ms ตรงกับเอฟเฟกต์สกิล, spawn จำนวนมาก หรือการอัปเดต UI ทั้งหน้าจอ และขณะนั้นปิงยังเท่าเดิม สัญญาณว่าไม่ใช่ เฟรมไทม์สม่ำเสมอ แต่มีแค่ตัวละครอื่นที่หยุดแวบ: น่าจะเป็นฝั่งเครือข่าย เช่น “ไม่มี interpolation buffer หรือสั้นเกินไป” ถ้าพุ่งเป็นรอบสม่ำเสมอ ให้ดู “GC ฝั่งไคลเอนต์” ก่อน วิธีตรวจ ตรวจที่สภาพแวดล้อมฝั่งผู้เล่น
แหล่งอ้างอิง 3 รายการ
GC ฝั่งไคลเอนต์ Client GC (Unity C#, Unreal, Lua)
ID cg-gc · ผู้รับผิดชอบหลัก พัฒนาไคลเอนต์ (ทีมพัฒนาเกม)
ทั้งเกมหยุดระหว่างเก็บคืนหน่วยความจำที่ใช้แล้วทิ้ง (garbage) จุดสังเกตคือกระตุกเป็นจังหวะสม่ำเสมอ
ทำไม สร้าง string, array และ list ชั่วคราวแล้วทิ้งทุกเฟรม → ผลคือ เมื่อ garbage สะสมมากพอ GC จะหยุดเมนเธรดเพื่อเก็บคืน → บนหน้าจอ กระตุกเป็นจังหวะทุกไม่กี่วินาทีถึงหลายสิบวินาที
อาการ กระตุก , ค้าง
ปัจจัย การหยุดชะงัก
ใครเจอ เราคนเดียว
เกิดเมื่อไร เป็นรอบสม่ำเสมอ, ตอนคนแห่มารวมกัน
ผู้รับผิดชอบ ผู้รับผิดชอบหลัก พัฒนาไคลเอนต์ (ทีมพัฒนาเกม)
งานฝั่งทีมพัฒนาเกม ลดการจัดสรรหน่วยความจำ (เลี่ยงการต่อ string, LINQ และ lambda capture), ใช้ object pool, เปิด incremental GC ไว้ (เป็นค่าเริ่มต้นตั้งแต่ Unity 2020), สั่ง GC ล่วงหน้าในจังหวะที่หยุดได้ เช่น หน้าโหลด
ตัวเลขที่ควรรู้ ปกติครั้งละหลักหน่วย ms ถึง 100 ms ส่วนมือถือสเปกต่ำหรือเกมที่ใช้หน่วยความจำมากอาจนานกว่านั้น (ในการทดลองราว 150–170 ms) GC ของ Unity ตรวจทั้ง heap ทุกครั้งที่ทำงาน ยิ่งเกมใช้หน่วยความจำมากก็ยิ่งนาน
บนกราฟ พุ่งเป็นรอบ · เฟรมไทม์, เวลาที่ GC ทำงาน
จุดที่ต้องดู ดู marker GC.Collect และ GC.Alloc ใน Unity Profiler บน development build ส่วน Unreal ดู stat GC และ stat Hitches (บันทึกเฟรมที่เกินเวลาที่ตั้งไว้ใน t.HitchFrameTimeThreshold ลง log) สัญญาณว่าใช่ ทุกเฟรมที่พุ่งมีช่วง GC.Collect ยาวใกล้เคียงกับช่วงที่พุ่ง และเกิดเป็นรอบสม่ำเสมอทุกไม่กี่วินาทีถึงหลายสิบวินาที ในที่ที่คนเยอะ GC.Alloc ต่อเฟรมเพิ่มขึ้น สัญญาณว่าไม่ใช่ เฟรมที่พุ่งไม่มีช่วง GC: น่าจะเป็น “โหลดแบบ synchronous และคอมไพล์ shader บนเมนเธรด” หรือ “ภาระการเรนเดอร์ตัวละครจำนวนมาก” วิธีตรวจ ต้องมี log หรือเมตริกจากเซิร์ฟเวอร์/ไคลเอนต์เกม
รายละเอียดเพิ่มเติม พบบ่อยในไคลเอนต์ที่เขียนด้วย C# อย่าง Unity ตัวการหลักคือโค้ดที่สร้าง string ของ combat log, ตัวเลขดาเมจ และข้อความ UI ขึ้นใหม่ทุกเฟรม ถ้ากระตุกเฉพาะที่ที่คนเยอะ แปลว่ามีโค้ดที่สร้าง garbage เพิ่มตามจำนวนผู้เล่น incremental GC แบ่งเก็บทีละนิดในแต่ละเฟรม (ค่าเริ่มต้นของ Unity คือ 3 ms) แต่ถ้าสร้าง garbage เร็วกว่าที่เก็บทัน สุดท้ายก็ต้องหยุดเก็บรวดเดียวอยู่ดี Unreal Engine ก็มี GC ของตัวเองที่เก็บกวาด game object ที่ไม่ได้ใช้ ค่าจะต่างกันไปตามเวอร์ชันเอนจินและการตั้งค่า แต่ค่าเริ่มต้นจะทำงานราวทุก 1 นาที จึงอาจเกิดอาการหยุดแวบทุก 1 นาทีได้ ไคลเอนต์ที่เขียนกฎของเกมด้วยสคริปต์อย่าง Lua ยังมี GC ของสคริปต์นั้นทำงานแยกอีกชุดหนึ่ง
แหล่งอ้างอิง 5 รายการ
ID cg-sync-load · ผู้รับผิดชอบหลัก พัฒนาไคลเอนต์ (ทีมพัฒนาเกม)
เกมหยุดเพราะต้องอ่านไฟล์และสร้าง shader ก่อนวาดพื้นที่, มอนสเตอร์ หรือเอฟเฟกต์ที่เพิ่งเห็นเป็นครั้งแรก
ทำไม เข้าพื้นที่ใหม่ หรือเจอสกิล, อุปกรณ์สวมใส่ และมอนสเตอร์ที่ไม่เคยเห็น → ผลคือ เมนเธรดรอการอ่านไฟล์และการคอมไพล์ shader → บนหน้าจอ ค้าง 0.1–1 วินาทีแค่ครั้งแรก ตั้งแต่ครั้งที่สองก็ปกติ
อาการ ค้าง , กระตุก
ปัจจัย การหยุดชะงัก
ใครเจอ เราคนเดียว
เกิดเมื่อไร ระหว่างเดินทาง/ย้ายแมพ, ตอนทำแอ็กชันบางอย่าง
ผู้รับผิดชอบ ผู้รับผิดชอบหลัก พัฒนาไคลเอนต์ (ทีมพัฒนาเกม)
งานฝั่งทีมพัฒนาเกม โหลดแบบ async, โหลดเตรียมไว้ล่วงหน้า (prewarming), คอมไพล์ shader ล่วงหน้าตอนหน้าโหลดหรือตอนเปิดเกมครั้งแรก, ใช้ประโยชน์จากหน้าโหลด
ตัวเลขที่ควรรู้ คอมไพล์ shader หนึ่งตัวใช้หลายสิบ ms ถ้านานอาจเกิน 100 ms ส่วนการโหลด texture ใช้หลายสิบถึงหลายร้อย ms ขึ้นกับความเร็วของสตอเรจ
บนกราฟ พุ่งทันทีหลังเปิดเซิร์ฟ/ปิดปรับปรุง · จำนวนเฟรมที่พุ่ง (ทันทีหลังแพตช์หรืออัปเดตไดรเวอร์)
จุดที่ต้องดู อัดด้วย PresentMon บนเส้นทางเดิมสองรอบ แล้วเทียบการไปครั้งแรกกับครั้งที่สอง ใน development build ของ Unreal เปิด r.PSOPrecache.Validation แล้วดู stat PSOPrecache และ “PSO PRECACHING MISS” ใน log ส่วน Unity ดูช่วงโหลดและ shader ของเฟรมที่พุ่งใน Timeline ของ Profiler สัญญาณว่าใช่ พุ่ง 0.1–1 วินาทีเฉพาะที่ที่ไปครั้งแรกหรือสกิลที่ใช้ครั้งแรก และหายไปในครั้งที่สอง การแจ้งปัญหาพุ่งขึ้นทันทีหลังแพตช์หรืออัปเดตไดรเวอร์กราฟิก แล้วค่อย ๆ ลดลง สัญญาณว่าไม่ใช่ พุ่งที่จุดเดิมทุกครั้ง: ไม่ใช่ปัญหา shader cache ถ้าเกิดซ้ำทุกครั้งที่เคลื่อนที่และเป็นเฉพาะ PC ที่สตอเรจช้า น่าจะเป็น “สตอเรจช้าจนสตรีมแอสเซ็ตไม่ทัน” ถ้าหน่วยความจำ GPU เฉพาะ (dedicated) เต็ม น่าจะเป็น “หน่วยความจำกราฟิก (VRAM) ไม่พอ” วิธีตรวจ ต้องมี log หรือเมตริกจากเซิร์ฟเวอร์/ไคลเอนต์เกม
รายละเอียดเพิ่มเติม บน PC ไดรเวอร์กราฟิกจะเก็บ shader ที่สร้างแล้วไว้ใน shader cache เพื่อใช้ซ้ำ ดังนั้นหลังอัปเดตไดรเวอร์กราฟิกหรือหลังเกมลงแพตช์ใหม่ แคชนี้จะใช้ไม่ได้ คนที่เคยเล่นได้ลื่นก็จะกลับมากระตุกอยู่ช่วงหนึ่ง การแจ้งปัญหาแบบ “หลังแพตช์ ไปที่ไหนครั้งแรกก็หยุดแวบทุกที่” เป็นรูปแบบการแจ้งปัญหาที่เจอได้บ่อย
แหล่งอ้างอิง 5 รายการ
ID cg-asset-stream · ผู้รับผิดชอบหลัก พัฒนาไคลเอนต์ (ทีมพัฒนาเกม) · ร่วมกับ ภายนอก (ภายนอก)
บนสตอเรจช้าอย่าง HDD การอ่าน texture และโมเดลของโอเพนเวิลด์ตามการเคลื่อนที่ไม่ทัน เอนทิตีจึงโผล่ช้า หรือเกมกระตุกระหว่างรออ่านข้อมูล
ทำไม เคลื่อนที่เร็วด้วยพาหนะหรือเทเลพอร์ต หรือเข้าไปในที่ที่คนเยอะ จนต้องใช้ texture และโมเดลใหม่จำนวนมากพร้อมกัน → ผลคือ สตอเรจช้าอย่าง HDD อ่านได้ไม่ทันความเร็วที่ต้องการ คำขออ่านจึงกองรอ และการโหลดบางส่วนทำให้เมนเธรดต้องรอจนเสร็จ → บนหน้าจอ texture เบลออยู่พักหนึ่ง อาคารและตัวละครโผล่ช้า และกระตุกหรือค้างตอนที่รออ่าน
อาการ มองไม่เห็น/ตัวผี , กระตุก , ค้าง
ปัจจัย การหยุดชะงัก
ใครเจอ เราคนเดียว
เกิดเมื่อไร ระหว่างเดินทาง/ย้ายแมพ, ตอนคนแห่มารวมกัน
ผู้รับผิดชอบ ผู้รับผิดชอบหลัก พัฒนาไคลเอนต์ (ทีมพัฒนาเกม) · ร่วมกับ ภายนอก (ภายนอก)
งานฝั่งทีมพัฒนาเกม สตรีมแบบ async ที่ไม่ให้เมนเธรดรอการอ่าน, อ่านล่วงหน้าตามทิศทางและความเร็วการเคลื่อนที่, แสดงความละเอียดต่ำ (mipmap) หรือโมเดลอย่างง่ายก่อนแล้วค่อยเปลี่ยน, ถ้าสตรีมไม่ทันระหว่างเคลื่อนที่เร็วให้จำกัดความเร็วการเคลื่อนที่ชั่วคราวหรือใช้หน้าโหลด, ระบุในสเปกขั้นต่ำและสเปกแนะนำว่าต้องใช้ SSD หรือไม่
งานฝั่งภายนอก แนะนำให้ผู้เล่นติดตั้งเกมบน SSD, แนะนำให้ผู้เล่นตรวจว่ามีการดาวน์โหลดหรือการสแกนของแอนตี้ไวรัสทำงานอยู่บนดิสก์เดียวกันหรือไม่
ตัวเลขที่ควรรู้ ตามคำอธิบายของ Microsoft ฮาร์ดดิสก์รุ่นเก่าอ่านได้หลายสิบ MB ใน 1 วินาที NVMe SSD อ่านได้หลาย GB ใน 1 วินาที และเกมยุคก่อนใช้แบนด์วิดท์สำหรับการสตรีมราว 50 MB ใน 1 วินาที ถ้าเอาเกมที่ออกแบบโดยถือว่ามีความเร็วระดับ SSD และอ่านมากกว่านี้มากไปเล่นบน HDD การอ่านก็มักตามการเคลื่อนที่ไม่ทัน
บนกราฟ สูงเฉพาะบางกลุ่ม · จำนวนเฟรมที่พุ่ง (แยกตามชนิดสตอเรจ), ดีเลย์การอ่านดิสก์
จุดที่ต้องดู บันทึก PhysicalDisk\Avg. Disk sec/Read (เวลาเฉลี่ยต่อการอ่านหนึ่งครั้ง) และ Current Disk Queue Length จาก Performance Monitor ของ Windows คู่กับเฟรมไทม์จาก PresentMon ขณะเคลื่อนที่เร็ว ใน development build ดู stat Streaming และ stat AsyncLoad ของ Unreal หรือคำเตือน AssetBundle.asset/allAssets ใน Unity Profiler (ขอผลลัพธ์ก่อนโหลดเสร็จ เมนเธรดจึงต้องรอ) สัญญาณว่าใช่ ตอนเคลื่อนที่เร็ว ดีเลย์การอ่านดิสก์และคิวพุ่งสูง และในเวลาเดียวกันเฟรมพุ่งหรือ texture และเอนทิตีโผล่ช้า เล่นฉากเดียวกันบน SSD แล้วหายไป สัญญาณว่าไม่ใช่ ดิสก์ว่างแต่ texture เบลอ: น่าจะเป็น “หน่วยความจำกราฟิก (VRAM) ไม่พอ” ถ้าไปที่เดิมครั้งที่สองแล้วปกติ น่าจะเป็น “โหลดแบบ synchronous และคอมไพล์ shader บนเมนเธรด” วิธีตรวจ ตรวจที่สภาพแวดล้อมฝั่งผู้เล่น
รายละเอียดเพิ่มเติม ถ้าหยุดแค่ครั้งแรกแล้วครั้งต่อไปปกติ จะใกล้กับ “โหลดแบบ synchronous และคอมไพล์ shader บนเมนเธรด” แต่ถ้าเกิดซ้ำทุกครั้งที่เคลื่อนที่และเป็นเฉพาะ PC ที่สตอเรจช้า ก็คือสาเหตุนี้ ส่วน “หน่วยความจำกราฟิก (VRAM) ไม่พอ” ซึ่งต้องปลด texture ออกแล้วโหลดกลับเข้ามาเพราะหน่วยความจำกราฟิกไม่พอ ก็ทำให้ texture เบลอได้เหมือนกัน จึงควรดูการรออ่านดิสก์คู่กับปริมาณการใช้หน่วยความจำกราฟิก การสแกนแบบเรียลไทม์ของแอนตี้ไวรัสที่เข้ามาแทรกทุกครั้งที่เปิดไฟล์เกม ก็อาจทำให้อ่านช้าลงไปอีก
แหล่งอ้างอิง 8 รายการ
ID cg-crowd · ผู้รับผิดชอบหลัก พัฒนาไคลเอนต์ (ทีมพัฒนาเกม)
เมื่อคนหลายร้อยคนเข้ามาอยู่ในจอเดียว เช่น ศึกชิงปราสาทหรือเวิลด์บอส ลำพังต้นทุนการวาดภาพก็รับไม่ไหวแล้ว
ทำไม คนหลายร้อยคนและเอฟเฟกต์ซ้อนกันอยู่ในจอเดียว → ผลคือ ต้นทุนของแอนิเมชัน, เงา, ป้ายชื่อ และเอฟเฟกต์ เพิ่มขึ้นตามจำนวนคน → บนหน้าจอ FPS ตกจาก 60 → 15 ทุกการเคลื่อนไหวกระตุก และอินพุตก็ช้าตาม
อาการ กระตุก , อินพุตดีเลย์
ปัจจัย การหยุดชะงัก
ใครเจอ บางจุด/บางแชนแนล, เราคนเดียว
เกิดเมื่อไร ตอนคนแห่มารวมกัน
ผู้รับผิดชอบ ผู้รับผิดชอบหลัก พัฒนาไคลเอนต์ (ทีมพัฒนาเกม)
งานฝั่งทีมพัฒนาเกม ลดรายละเอียดตามระยะ (LOD), จำกัดจำนวนคนที่แสดง, เพิ่มตัวเลือกลดเอฟเฟกต์, ลดความถี่การอัปเดตแอนิเมชัน
ตัวเลขที่ควรรู้ ต่อให้ใช้แค่ 0.02–0.1 ms ต่อตัวละคร 1 ตัว ถ้ามี 300 ตัวก็เป็น 6–30 ms งบเวลาต่อเฟรมที่ 60 FPS คือ 16.7 ms แค่ส่วนนี้ก็กินไปเกิน 1/3 แล้ว และถ้ามากก็เกินงบ
บนกราฟ สูงตามจำนวนคนและโหลด · เฟรมไทม์, จำนวนตัวละครบนจอ
จุดที่ต้องดู เทียบเฟรมไทม์และ CPUBusy/GPUBusy จาก PresentMon ก่อนและหลังศึกชิงปราสาทหรือเวิลด์บอส ใน development build ใช้ stat Unit ของ Unreal (เวลาของเธรดเกม, เธรดเรนเดอร์ และ GPU) สัญญาณว่าใช่ ยิ่งคนบนจอเพิ่ม เฟรมไทม์ยิ่งสูงตาม และดีขึ้นทันทีเมื่อเปิดตัวเลือกจำกัดจำนวนคนที่แสดงหรือลดเอฟเฟกต์ สัญญาณว่าไม่ใช่ พุ่งโดยไม่เกี่ยวกับจำนวนคน: น่าจะเป็น “เฟรมไทม์พุ่ง” หรือ “GC ฝั่งไคลเอนต์” ถ้า FPS ปกติแต่มีแค่การเคลื่อนไหวของคนอื่นที่ช้า น่าจะเป็น “คอขวดการประมวลผลแพ็กเก็ตบนเมนเธรด” วิธีตรวจ ตรวจที่สภาพแวดล้อมฝั่งผู้เล่น
แหล่งอ้างอิง 4 รายการ
ID cg-net-mainthread · ผู้รับผิดชอบหลัก พัฒนาไคลเอนต์ (ทีมพัฒนาเกม) · ร่วมกับ พัฒนาเซิร์ฟเวอร์ (ทีมพัฒนาเกม)
ถ้าประมวลผลแพ็กเก็ตที่รับมาได้แค่จำนวนที่กำหนดในแต่ละเฟรม แพ็กเก็ตที่ทะลักเข้ามาจะถูกเลื่อนไปเฟรมถัดไปเรื่อย ๆ
ทำไม ในที่ที่คนเยอะ มีอัปเดตเข้ามาหลายพันรายการต่อวินาที → ผลคือ เมนเธรดชนเพดานปริมาณที่ประมวลผลได้ต่อเฟรม จึงอ่านได้ไม่หมด → บนหน้าจอ การเคลื่อนไหวของคนอื่นแสดงช้าลงเรื่อย ๆ แล้วมาเป็นชุดรวดเดียว
อาการ กรอเร็ว , อินพุตดีเลย์
ปัจจัย การหยุดชะงัก, ความหน่วง
ใครเจอ บางจุด/บางแชนแนล, เราคนเดียว
เกิดเมื่อไร ตอนคนแห่มารวมกัน
ผู้รับผิดชอบ ผู้รับผิดชอบหลัก พัฒนาไคลเอนต์ (ทีมพัฒนาเกม) · ร่วมกับ พัฒนาเซิร์ฟเวอร์ (ทีมพัฒนาเกม)
งานฝั่งทีมพัฒนาเกม ไคลเอนต์: แยกการรับและการแปลงข้อมูลไปไว้อีกเธรด, รวมอัปเดตตำแหน่งเก่าของเป้าหมายเดียวกันแล้วใช้เฉพาะอันล่าสุด เซิร์ฟเวอร์: ในที่ที่คนเยอะ ส่งอัปเดตของตัวละครที่อยู่ไกลให้ห่างขึ้นเพื่อลดปริมาณการส่ง
ตัวเลขที่ควรรู้ เมื่อแพ็กเก็ตที่ประมวลผลไม่ทันกองรอ แค่ไม่กี่วินาทีก็ตามหลังไปถึง 1 วินาทีได้แล้ว
บนกราฟ สูงตามจำนวนคนและโหลด · จำนวนแพ็กเก็ตขาเข้าที่ประมวลผลไม่ทัน, ดีเลย์ตั้งแต่รับจนนำไปใช้
จุดที่ต้องดู จำนวนแพ็กเก็ตที่ไคลเอนต์ประมวลผลไม่ทันและเหลือไว้ในแต่ละเฟรม และดีเลย์ตั้งแต่แพ็กเก็ตมาถึงจนนำไปใช้ในเกม เก็บเป็น log แล้วดูคู่กับจำนวนคนรอบตัว สัญญาณว่าใช่ ในที่ที่คนเยอะ จำนวนแพ็กเก็ตที่เหลือและดีเลย์การนำไปใช้เพิ่มขึ้นเรื่อย ๆ ขณะที่ปิงและช่วงห่างการส่งของเซิร์ฟเวอร์ในเวลาเดียวกันปกติ สัญญาณว่าไม่ใช่ ไม่มีดีเลย์การนำไปใช้ แต่ตัวแพ็กเก็ตเองมาถึงช้า: น่าจะเป็นช่วงเครือข่าย ถ้าเฟรมไทม์สูงขึ้นมาก น่าจะเป็น “ภาระการเรนเดอร์ตัวละครจำนวนมาก” วิธีตรวจ ต้องมี log หรือเมตริกจากเซิร์ฟเวอร์/ไคลเอนต์เกม
แหล่งอ้างอิง 2 รายการ Actor Priority in Unreal Engine Epic Games เมื่อแบนด์วิดท์ไม่พอ จะจัดลำดับความสำคัญตามระยะห่างจากผู้ดูและเวลาตั้งแต่ replicate ครั้งล่าสุด แทนการ replicate ทุก actor ทุกครั้ง Replication Graph in Unreal Engine Epic Games เกมที่มีผู้เชื่อมต่อและเป้าหมายที่ต้อง replicate จำนวนมาก (เช่น MMORPG) ต้องจัดกลุ่มตามตำแหน่งแล้วส่งเฉพาะเป้าหมายที่จำเป็น จึงจะเลี่ยงคอขวด CPU ของเซิร์ฟเวอร์ได้
ID cg-no-buffer · ผู้รับผิดชอบหลัก พัฒนาไคลเอนต์ (ทีมพัฒนาเกม) · ร่วมกับ พัฒนาเซิร์ฟเวอร์ (ทีมพัฒนาเกม)
ถ้าวาดทันทีที่ได้รับแพ็กเก็ตจากเซิร์ฟเวอร์ จิตเตอร์ (ช่วงเวลาที่แพ็กเก็ตมาถึงไม่สม่ำเสมอ) จะแสดงออกมาบนจอตรง ๆ
ทำไม วาดตำแหน่งที่ได้รับทันที หรือบัฟเฟอร์สั้นกว่าจิตเตอร์ → ผลคือ หยุดนานเท่าที่แพ็กเก็ตมาช้า และกระโดดไปเท่าที่แพ็กเก็ตมาพร้อมกันหลายอัน → บนหน้าจอ ตัวละครอื่นขยับแบบหยุดแวบเป็นระยะ
อาการ กระตุก
ปัจจัย จิตเตอร์
ใครเจอ เราคนเดียว
เกิดเมื่อไร ตลอดเวลา
ผู้รับผิดชอบ ผู้รับผิดชอบหลัก พัฒนาไคลเอนต์ (ทีมพัฒนาเกม) · ร่วมกับ พัฒนาเซิร์ฟเวอร์ (ทีมพัฒนาเกม)
งานฝั่งทีมพัฒนาเกม ไคลเอนต์: มี interpolation buffer, ปรับความยาวบัฟเฟอร์อัตโนมัติตามสภาพเน็ต เซิร์ฟเวอร์: ใช้ lag compensation (ตัดสินผลด้วยการย้อนเวลา) เพื่อให้ตัดสินได้ถูกต้องแม้ผู้เล่นจะยิงโดยดูภาพในอดีตย้อนหลังไปเท่าความยาวบัฟเฟอร์
ตัวเลขที่ควรรู้ ปกติจะตั้งบัฟเฟอร์ไว้ราว 2 เท่าของช่วงห่างที่เซิร์ฟเวอร์ส่งแพ็กเก็ต (ถ้ารับ 20 ครั้งใน 1 วินาทีก็คือ 100 ms)
บนกราฟ สูงตลอดตั้งแต่แรก · ช่วงห่างการมาถึงของแพ็กเก็ต, จำนวนครั้งที่ interpolation buffer ว่าง
จุดที่ต้องดู บันทึกการกระจายของช่วงห่างการมาถึงของแพ็กเก็ตจากเซิร์ฟเวอร์ที่ไคลเอนต์ และจำนวนเฟรมที่หยุดหรือเปลี่ยนไปใช้ extrapolation เพราะไม่มีสแนปช็อตถัดไปให้ interpolate สัญญาณว่าใช่ ความไม่สม่ำเสมอของช่วงห่างการมาถึงเกินความยาว interpolation buffer บ่อย ๆ และทุกครั้งที่เกิน บัฟเฟอร์จะว่างจนตัวละครอื่นหยุดแวบ เพิ่มบัฟเฟอร์แล้วลดลง สัญญาณว่าไม่ใช่ บัฟเฟอร์พอแล้วแต่ยังหยุดแวบ: ตรวจว่าช่วงห่างที่เซิร์ฟเวอร์ส่งออกมาเองไม่สม่ำเสมอหรือไม่ (ทิกล่าช้า) วิธีตรวจ ต้องมี log หรือเมตริกจากเซิร์ฟเวอร์/ไคลเอนต์เกม
รายละเอียดเพิ่มเติม ยิ่งเพิ่มบัฟเฟอร์ภาพก็ยิ่งลื่น แต่ก็จะเห็นอีกฝ่ายเป็นภาพในอดีตนานขึ้นเท่ากัน การตัดสินการโจมตีจึงใช้ lag compensation ควบคู่ไปด้วย โดยเซิร์ฟเวอร์ย้อนเวลากลับไปตรวจที่ “อดีตที่ผู้เล่นคนนั้นเห็น”
แหล่งอ้างอิง 3 รายการ
ID cg-predict · ผู้รับผิดชอบหลัก พัฒนาไคลเอนต์ (ทีมพัฒนาเกม) · ร่วมกับ พัฒนาเซิร์ฟเวอร์ (ทีมพัฒนาเกม)
ไคลเอนต์ของเราแสดงการเคลื่อนที่ไปก่อน แต่ถ้าเซิร์ฟเวอร์คำนวณออกมาต่างกัน ตัวละครของเราจะโดนดึงกลับ
ทำไม ไคลเอนต์ขยับไปก่อนที่เซิร์ฟเวอร์จะยืนยัน (prediction) → ผลคือ เซิร์ฟเวอร์คำนวณการชน, ความเร็วการเคลื่อนที่ หรือบัฟต่างออกไป หรือไม่ได้รับคำสั่ง → บนหน้าจอ พอผลยืนยันมาถึง ตัวละครของเราโดนดึงถอยหลัง
อาการ ดีดกลับ
ปัจจัย แพ็กเก็ตหาย, ความหน่วง
ใครเจอ เราคนเดียว
เกิดเมื่อไร ระหว่างเดินทาง/ย้ายแมพ, สุ่มเป็นครั้งคราว
ผู้รับผิดชอบ ผู้รับผิดชอบหลัก พัฒนาไคลเอนต์ (ทีมพัฒนาเกม) · ร่วมกับ พัฒนาเซิร์ฟเวอร์ (ทีมพัฒนาเกม)
งานฝั่งทีมพัฒนาเกม ไคลเอนต์: ใช้โค้ดการเคลื่อนที่ชุดเดียวกับเซิร์ฟเวอร์, ส่งอินพุตซ้ำ, แก้ตำแหน่งอย่างนุ่มนวล เซิร์ฟเวอร์: ใช้โค้ดการเคลื่อนที่ชุดเดียวกับไคลเอนต์, กรองอินพุตที่มาซ้ำด้วยหมายเลขอินพุตแล้วประมวลผลครั้งเดียว
ตัวเลขที่ควรรู้ ระยะที่โดนดึงคือ “เวลาที่คลาดกัน × ความเร็วการเคลื่อนที่” แค่คำสั่งหายไปไม่กี่อันก็ 1–3 เมตร
บนกราฟ พุ่งแบบสุ่มเป็นครั้งคราว · จำนวนครั้งที่เซิร์ฟเวอร์แก้ตำแหน่ง (prediction ผิด)
จุดที่ต้องดู บันทึกจำนวนครั้งและระยะที่เซิร์ฟเวอร์ส่งมาแก้ตำแหน่ง Unreal ดูการแก้ด้วย ClientAdjustPosition ของเซิร์ฟเวอร์ ส่วน Unity Netcode for Entities นับจำนวนครั้งที่ย้อนกลับไปคำนวณใหม่เพราะ prediction ผิด สัญญาณว่าใช่ การแก้ตำแหน่งกระจุกตรงเวลาที่มีคนแจ้งอาการดีดกลับ และระยะแก้ตำแหน่งใหญ่ซ้ำ ๆ กับบัฟ, ภูมิประเทศ หรือสกิลเคลื่อนที่บางอย่าง สัญญาณว่าไม่ใช่ การแก้ตำแหน่งกระจุกเฉพาะตอนแพ็กเก็ตหายมาก: น่าจะเป็นแพ็กเก็ตอินพุตหาย (ฝั่งเน็ต) ถ้าไม่มีการแก้ตำแหน่ง แต่เห็นแค่ตัวละครอื่นโดนดึง น่าจะเป็น “extrapolation มากเกินไป (dead reckoning)” วิธีตรวจ ต้องมี log หรือเมตริกจากเซิร์ฟเวอร์/ไคลเอนต์เกม
แหล่งอ้างอิง 3 รายการ
ID cg-fixed-step · ผู้รับผิดชอบหลัก พัฒนาไคลเอนต์ (ทีมพัฒนาเกม)
หลังหยุดไปครั้งหนึ่ง เกมเร่งคำนวณส่วนที่ตามหลังรวดเดียว แล้วการคำนวณนั้นเองก็ทำให้ตามหลังอีก
ทำไม เกมรันการจำลองด้วยช่วงเวลาคงที่ แล้วเกิดหยุดไปครั้งหนึ่ง → ผลคือ คำนวณ step ที่ตามหลังทั้งหมดรวดเดียวในเฟรมเดียว → บนหน้าจอ เฟรมยาวเกิดต่อกันเป็นพรวนจนภาพกระตุก หรือชนเพดานแล้วโลกในเกมช้าลง
อาการ กระตุก , กรอเร็ว , สโลว์โมชั่น
ปัจจัย การหยุดชะงัก
ใครเจอ เราคนเดียว
เกิดเมื่อไร สุ่มเป็นครั้งคราว, ตอนคนแห่มารวมกัน
ผู้รับผิดชอบ ผู้รับผิดชอบหลัก พัฒนาไคลเอนต์ (ทีมพัฒนาเกม)
งานฝั่งทีมพัฒนาเกม จำกัดการไล่ตามต่อเฟรม, จัดการเวลาที่เหลือด้วย interpolation
บนกราฟ พุ่งแบบสุ่มเป็นครั้งคราว · เฟรมไทม์, จำนวน fixed step ต่อเฟรม
จุดที่ต้องดู ดูใน profiler ของ development build ว่าในหนึ่งเฟรม fixed step ทำงานกี่ครั้ง (Unity คือจำนวน marker ของขั้น FixedUpdate เช่น FixedBehaviourUpdate) คู่กับเฟรมไทม์ สัญญาณว่าใช่ หลังเฟรมยาวหนึ่งเฟรม มีเฟรมยาวที่รัน step หลายครั้งตามมาเป็นพรวน และเมื่อชนเพดาน (Maximum Allowed Timestep ของ Unity) เวลาในเกมจะเดินช้ากว่าความจริง สัญญาณว่าไม่ใช่ เฟรมยาวเกิดครั้งเดียวแล้วจบ: น่าจะเป็น “เฟรมไทม์พุ่ง” หรือ “GC ฝั่งไคลเอนต์” วิธีตรวจ ต้องมี log หรือเมตริกจากเซิร์ฟเวอร์/ไคลเอนต์เกม
รายละเอียดเพิ่มเติม การคำนวณฟิสิกส์ของ Unity (FixedUpdate) คือตัวอย่างที่ชัดของ fixed step (ค่าเริ่มต้น 0.02 วินาที หรือ 50 ครั้งใน 1 วินาที) Maximum Allowed Timestep ในการตั้งค่า Time (เวลาสูงสุดที่ไล่ตามได้ในหนึ่งเฟรม ค่าเริ่มต้นราว 0.33 วินาที) คือเพดานการไล่ตาม ถ้าเฟรมหนึ่งยาวกว่านี้ เวลาส่วนที่เกินจะถูกทิ้ง นาฬิกาเกมจึงช้ากว่าความจริงไปเท่านั้น
แหล่งอ้างอิง 3 รายการ
ID cg-clock · ผู้รับผิดชอบหลัก พัฒนาไคลเอนต์ (ทีมพัฒนาเกม)
ถ้าเวลาเซิร์ฟเวอร์ที่ไคลเอนต์ประมาณไว้ผิด จังหวะ interpolation และการตัดสินคูลดาวน์จะคลาดกัน
ทำไม ตั้งเวลาให้ตรงกับเซิร์ฟเวอร์แค่ครั้งเดียวตอนเชื่อมต่อ แม้ปิงเปลี่ยนก็ไม่ปรับ → ผลคือ จังหวะที่ใช้ interpolate และเวลาที่คูลดาวน์หมดคลาดจากเซิร์ฟเวอร์ → บนหน้าจอ อีกฝ่ายหยุดแวบเป็นบางครั้ง คูลดาวน์หมดแล้วแต่สกิลถูกปฏิเสธ
อาการ กระตุก , กดไม่ติด/โรลแบ็ค
ปัจจัย ความหน่วง
ใครเจอ เราคนเดียว
เกิดเมื่อไร ยิ่งเปิดไว้นานยิ่งเป็น, สุ่มเป็นครั้งคราว
ผู้รับผิดชอบ ผู้รับผิดชอบหลัก พัฒนาไคลเอนต์ (ทีมพัฒนาเกม)
งานฝั่งทีมพัฒนาเกม ซิงก์เวลาเป็นระยะ (วัดเวลาไปกลับแล้วชดเชย), ค่อย ๆ ปรับเข้าหาแทนการเปลี่ยนกะทันหัน, วัดเวลาที่ผ่านไปด้วย monotonic clock แทนเวลาของ PC
บนกราฟ ค่อย ๆ สูงขึ้น · ค่าคลาดเคลื่อนของเวลาเซิร์ฟเวอร์ที่ประมาณไว้
จุดที่ต้องดู บันทึกผลต่างระหว่างเวลาเซิร์ฟเวอร์ที่ไคลเอนต์ประมาณไว้กับเวลาเซิร์ฟเวอร์ (หมายเลขทิก) ที่เซิร์ฟเวอร์ใส่มาในแพ็กเก็ต เป็นระยะ สัญญาณว่าใช่ ค่าคลาดเคลื่อนโตขึ้นเรื่อย ๆ หลังเชื่อมต่อ หรือกระโดดทีเดียวตอนที่นาฬิกา PC ถูกปรับ และช่วงนั้นมีการแจ้งสกิลถูกปฏิเสธหรือหยุดแวบเพิ่มขึ้น สัญญาณว่าไม่ใช่ ค่าคลาดเคลื่อนยังเล็กอยู่แต่สกิลถูกปฏิเสธ: ให้ดูฝั่งการตัดสินผลของเซิร์ฟเวอร์และความหน่วง วิธีตรวจ ต้องมี log หรือเมตริกจากเซิร์ฟเวอร์/ไคลเอนต์เกม
รายละเอียดเพิ่มเติม ถ้าวัดเวลาที่ผ่านไปด้วยวันที่และเวลาของ PC (wall clock) ทันทีที่ Windows ปรับนาฬิกาตามเวลาอินเทอร์เน็ตหรือผู้ใช้เปลี่ยนนาฬิกา เวลาในเกมจะกระโดด เวลาที่ผ่านไปต้องวัดด้วยนาฬิกาที่ไม่ย้อนกลับ (monotonic clock เช่น Stopwatch)
แหล่งอ้างอิง 3 รายการ
ID cg-float-time · ผู้รับผิดชอบหลัก พัฒนาไคลเอนต์ (ทีมพัฒนาเกม)
ถ้าเก็บเวลาในเกมเป็นทศนิยมความแม่นยำต่ำ (float) ยิ่งเปิดเกมไว้นาน ความละเอียดของเวลา (ผลต่างของเวลาที่เล็กที่สุดที่แยกได้) ก็ยิ่งลดลง การเคลื่อนไหวและเอฟเฟกต์จึงสั่น
ทำไม สะสมเวลาที่ผ่านไปตั้งแต่เปิดเกมเป็น float หรือส่งค่านั้นให้ shader ตรง ๆ → ผลคือ ยิ่งเปิดไว้นาน ผลต่างที่เล็กที่สุดที่ float แสดงได้ก็ยิ่งใหญ่ขึ้น → บนหน้าจอ เฉพาะไคลเอนต์ที่เปิดทิ้งไว้หลายวัน ตัวละคร, แอนิเมชัน และเอฟเฟกต์ที่เคลื่อนไหลสั่นระริก แต่เปิดเกมใหม่แล้วปกติ
อาการ กระตุก
ปัจจัย จิตเตอร์
ใครเจอ เราคนเดียว
เกิดเมื่อไร ยิ่งเปิดไว้นานยิ่งเป็น
ผู้รับผิดชอบ ผู้รับผิดชอบหลัก พัฒนาไคลเอนต์ (ทีมพัฒนาเกม)
งานฝั่งทีมพัฒนาเกม เก็บเวลาที่ผ่านไปเป็น double (64 บิต) หรือจำนวนเต็ม, วนค่าเวลาที่ส่งให้ shader กลับเป็นรอบ, ทดสอบอัตโนมัติแบบรันยาวหลายวัน
ตัวเลขที่ควรรู้ float 32 บิตมีเลขนัยสำคัญราว 7 หลัก ถ้าเปิดไว้หนึ่งวัน (ราว 86,400 วินาที) ความละเอียดของเวลาจะเหลือราว 8 ms หรือราวครึ่งเฟรมที่ 60 FPS (16.7 ms) และถ้าเปิดไว้หนึ่งสัปดาห์จะราว 60 ms ซึ่งมากกว่าหนึ่งเฟรม
บนกราฟ ค่อย ๆ สูงขึ้น · การแจ้งอาการสั่นแยกตามระยะเวลาที่เปิดเกมไว้
จุดที่ต้องดู ขอระยะเวลาที่เปิดไคลเอนต์ไว้มาพร้อมการแจ้งอาการสั่น แล้วเทียบก่อนและหลังรีสตาร์ต ฝั่งพัฒนาทดสอบโดยตั้งค่าเวลาเริ่มเกมเป็นค่าที่ผ่านไปแล้วหลายวัน สัญญาณว่าใช่ สั่นเฉพาะไคลเอนต์ที่เปิดไว้หลายวัน รีสตาร์ตแล้วหาย และยิ่งเปิดไว้นานยิ่งหนัก สัญญาณว่าไม่ใช่ สั่นตั้งแต่เพิ่งเปิด: น่าจะเป็น “ไม่มี interpolation buffer หรือสั้นเกินไป” หรือ “ความละเอียดของตัวจับเวลา” วิธีตรวจ ตรวจที่สภาพแวดล้อมฝั่งผู้เล่น
รายละเอียดเพิ่มเติม เจอบ่อยเป็นพิเศษในเกม MMO มือถือที่ผู้เล่นเปิดออโต้ทิ้งไว้หลายวันโดยไม่ปิด Time.time ของ Unity ก็เป็น float เช่นกัน Unity จึงมี Time.timeAsDouble ที่เป็น double แยกไว้และแนะนำให้ใช้ตัวนี้
แหล่งอ้างอิง 2 รายการ
ID cg-vsync · ผู้รับผิดชอบหลัก พัฒนาไคลเอนต์ (ทีมพัฒนาเกม) · ร่วมกับ ภายนอก (ภายนอก)
ระหว่างที่ GPU เก็บเฟรมที่วาดเสร็จไว้ในคิวหลายเฟรม แล้วค่อยส่งออกตามรอบของจอ อินพุตจะช้าลง
ทำไม ไดรเวอร์กราฟิกเก็บเฟรมไว้ล่วงหน้าในคิว 1–3 เฟรม → ผลคือ อินพุตต้องใช้เวลานานขึ้นเท่านั้นกว่าจะแสดงบนจอ → บนหน้าจอ ปิงต่ำแต่การควบคุมหนืดและตอบสนองช้า
อาการ อินพุตดีเลย์ , กระตุก
ปัจจัย ความหน่วง
ใครเจอ เราคนเดียว
เกิดเมื่อไร ตลอดเวลา
ผู้รับผิดชอบ ผู้รับผิดชอบหลัก พัฒนาไคลเอนต์ (ทีมพัฒนาเกม) · ร่วมกับ ภายนอก (ภายนอก)
งานฝั่งทีมพัฒนาเกม รองรับโหมด low latency, ลดคิวเฟรม, มีตัวเลือกจำกัดเฟรมเรตให้ต่ำกว่าอัตรารีเฟรชเล็กน้อย, บนมือถือเปิดฟีเจอร์ frame pacing
งานฝั่งภายนอก แนะนำให้ผู้เล่นใช้จอ VRR คู่กับการจำกัดเฟรมเรตให้ต่ำกว่าอัตรารีเฟรชเล็กน้อย, แนะนำให้เปิดโหมด low latency ในไดรเวอร์กราฟิก
ตัวเลขที่ควรรู้ ที่ 60 Hz เฟรมละ 16.7 ms ถ้า CPU เร็วกว่า GPU หรือรอบของจอ จนคิวสามเฟรม (ค่าเริ่มต้นของ DirectX 11) เต็ม จะเพิ่มขึ้นมา 50 ms ใน V-Sync แบบ double buffer เฟรมที่ใช้ 17 ms ต้องรอจนถึงรอบรีเฟรชจอถัดไป (33.3 ms) และระหว่างนั้นเฟรมก่อนหน้าจะแสดงซ้ำอีกครั้ง
บนกราฟ สูงตลอดตั้งแต่แรก · ดีเลย์จากอินพุตถึงจอ
จุดที่ต้องดู เทียบค่า MsClickToPhotonLatency, MsAllInputToPhotonLatency (ตั้งแต่อินพุตเมาส์/คีย์บอร์ดจนส่งภาพออกจอ) และ DisplayLatency ของ PresentMon ขณะสลับเปิดปิด V-Sync, โหมด low latency และการจำกัดเฟรมเรต MsPCLatency (ตั้งแต่ PC รับอินพุตจนส่งภาพออกจอ) จะถูกบันทึกเฉพาะเมื่อเกมส่ง PC Latency event ออกมา สัญญาณว่าใช่ ตอนเปิด V-Sync หรือไม่จำกัดเฟรมเรต ดีเลย์นี้เพิ่มขึ้นหนึ่งถึงสองเฟรม (หลายสิบ ms) และลดลงเมื่อใช้โหมด low latency หรือจำกัดเฟรมเรตให้ต่ำกว่าอัตรารีเฟรชเล็กน้อย ปิงเท่าเดิม สัญญาณว่าไม่ใช่ ดีเลย์ภายใน PC ต่ำแต่การควบคุมยังช้า: น่าจะเป็น “ดีเลย์จากจอ, อุปกรณ์อินพุต และ frame generation” ถ้าปิงสูง ให้ดูฝั่งเครือข่าย วิธีตรวจ ตรวจที่สภาพแวดล้อมฝั่งผู้เล่น
รายละเอียดเพิ่มเติม V-Sync (vertical sync) คือการตั้งค่าที่ส่งเฟรมใหม่ออกไปเฉพาะจังหวะที่จอเปลี่ยนภาพ ภาพฉีก (screen tearing) จะหายไป แต่อินพุตจะช้าลงเท่าเวลาที่ต้องรอจังหวะนั้น และถ้า FPS ต่ำกว่า 60 จะสลับไปมาระหว่าง 60 กับ 30 จนภาพกระตุก จอ VRR (อัตรารีเฟรชแบบแปรผัน) จะเปลี่ยนภาพตามจังหวะที่เฟรมพร้อม จึงลดการรอนี้ได้ บนมือถือก็เกิดแบบเดียวกัน ถ้าเกม 30 FPS ส่งเฟรมออกให้สม่ำเสมอกับจอ 60 Hz ไม่ได้ ค่าเฉลี่ยจะยังเป็น 30 FPS แต่แต่ละเฟรมอยู่บนจอนานไม่เท่ากัน เช่น 49, 16, 33 ms จนภาพกระตุก (ตัวอย่างจากเอกสารนักพัฒนา Android) ลดได้ด้วยไลบรารี frame pacing (การทำให้ช่วงห่างการส่งเฟรมสม่ำเสมอ) ของ Android หรือตัวเลือกแบบเดียวกันในเอนจิน
แหล่งอ้างอิง 5 รายการ
ID cg-leak · ผู้รับผิดชอบหลัก พัฒนาไคลเอนต์ (ทีมพัฒนาเกม)
ยิ่งเปิดไว้นาน หน่วยความจำยิ่งเพิ่ม เกมช้าลงเรื่อย ๆ แล้วสุดท้ายก็ถูกบังคับปิด
ทำไม texture, UI และเอฟเฟกต์ไม่ถูกปล่อยคืนเมื่อย้ายแมพไปมา → ผลคือ GC ทำงานถี่ขึ้น และหน่วยความจำของ OS ไม่พอจนเกิด swap → บนหน้าจอ เล่นไปหลายชั่วโมงแล้วกระตุกขึ้นเรื่อย ๆ จนถูกบังคับปิด (ผู้เล่นเห็นเหมือนหลุด)
อาการ กระตุก , หลุด
ปัจจัย การหยุดชะงัก
ใครเจอ เราคนเดียว
เกิดเมื่อไร ยิ่งเปิดไว้นานยิ่งเป็น
ผู้รับผิดชอบ ผู้รับผิดชอบหลัก พัฒนาไคลเอนต์ (ทีมพัฒนาเกม)
งานฝั่งทีมพัฒนาเกม วัดปริมาณการใช้หน่วยความจำตอนย้ายแมพ, หาและแก้ texture, UI และเอฟเฟกต์ที่ไม่ถูกปล่อยคืน, ทดสอบอัตโนมัติแบบรันยาว (soak test)
บนกราฟ ค่อย ๆ สูงขึ้น · หน่วยความจำของโปรเซสเกม
จุดที่ต้องดู บันทึก Process(เกม)\Private Bytes ด้วย Performance Monitor หลายชั่วโมง บนมือถือดูสาเหตุการปิด (REASON_LOW_MEMORY) จาก ApplicationExitInfo ของ Android และรายงาน jetsam ของ iOS สัญญาณว่าใช่ หน่วยความจำเพิ่มขึ้นทุกครั้งที่ย้ายแมพและไม่ลดลง ยิ่งเปิดไว้นาน อาการกระตุกและการถูกบังคับปิดยิ่งเพิ่ม สัญญาณว่าไม่ใช่ หน่วยความจำคงที่ แต่ยิ่งเปิดนานยิ่งสั่นอย่างเดียว: น่าจะเป็น “เวลาแบบ float สูญเสียความแม่นยำ” วิธีตรวจ ตรวจที่สภาพแวดล้อมฝั่งผู้เล่น
รายละเอียดเพิ่มเติม มือถือส่วนใหญ่ประคองไว้ด้วยการบีบอัดหน่วยความจำ ถ้ายังไม่พออีก OS จะปิดเกมทันที (เด้ง) เครื่องที่ RAM น้อยยิ่งโดนปิดก่อน
แหล่งอ้างอิง 4 รายการ
ID cg-crash · ผู้รับผิดชอบหลัก พัฒนาไคลเอนต์ (ทีมพัฒนาเกม) · ร่วมกับ ภายนอก (ภายนอก)
เกมปิดตัวลงเพราะข้อผิดพลาดที่ไม่ได้จัดการ ผู้เล่นเห็นเหมือนหลุด แต่เซิร์ฟเวอร์ปกติ
ทำไม null reference, หน่วยความจำไม่พอ, ไดรเวอร์กราฟิกผิดพลาด → ผลคือ โปรเซสเกมถูกบังคับปิด → บนหน้าจอ มีคนแจ้งว่า “เกมเด้ง” ขณะที่คนอื่นในเวลาเดียวกันปกติ
อาการ หลุด
ปัจจัย การหยุดชะงัก
ใครเจอ เราคนเดียว
เกิดเมื่อไร ตอนทำแอ็กชันบางอย่าง, สุ่มเป็นครั้งคราว
ผู้รับผิดชอบ ผู้รับผิดชอบหลัก พัฒนาไคลเอนต์ (ทีมพัฒนาเกม) · ร่วมกับ ภายนอก (ภายนอก)
งานฝั่งทีมพัฒนาเกม เก็บ crash report, ทำสถิติแยกตามเครื่องและไดรเวอร์, แก้ข้อผิดพลาดที่เกิดบ่อยที่สุดก่อน
งานฝั่งภายนอก ถ้ากระจุกที่ไดรเวอร์กราฟิกบางเวอร์ชัน แนะนำให้ผู้เล่นอัปเดตไดรเวอร์
บนกราฟ สูงเฉพาะบางกลุ่ม · จำนวนการแครช (แยกตามเครื่อง/ไดรเวอร์กราฟิก/บิลด์)
จุดที่ต้องดู ดู crash report และอัตราการแครชใน Android vitals แยกตามเครื่อง, ไดรเวอร์ และบิลด์ บน PC ของผู้เล่นดู Event ID 1000 ใน Application log ของ Event Viewer (ชื่อโมดูลที่เกิดข้อผิดพลาด) และบันทึก “Display driver stopped responding and has recovered” สัญญาณว่าใช่ มีบันทึกการแครชตรงเวลาที่แจ้งว่าหลุด ขณะที่ผู้เล่นอื่นในเซิร์ฟเวอร์เดียวกันเวลาเดียวกันปกติ กระจุกที่บางเครื่อง, บางเวอร์ชันไดรเวอร์ หรือบางโมดูล สัญญาณว่าไม่ใช่ ไม่มีบันทึกการแครชแต่การเชื่อมต่อหลุด: น่าจะเป็น “NAT mapping หมดอายุ” หรือฝั่งเน็ต วิธีตรวจ ต้องมี log หรือเมตริกจากเซิร์ฟเวอร์/ไคลเอนต์เกม
แหล่งอ้างอิง 3 รายการ
ID cg-anticheat · ผู้รับผิดชอบหลัก พัฒนาไคลเอนต์ (ทีมพัฒนาเกม) · ร่วมกับ พัฒนาเซิร์ฟเวอร์ (ทีมพัฒนาเกม)
โมดูลความปลอดภัยที่ทำงานคู่กับเกมเพื่อกันโปรโกงจะตรวจสอบเป็นระยะ ถ้าการตรวจหนัก หรือ heartbeat (สัญญาณยืนยันว่ายังทำงานอยู่ที่ส่งเป็นระยะ) ที่รับส่งกับเซิร์ฟเวอร์ความปลอดภัยมาช้า เกมจะกระตุกหรือหลุด
ทำไม โมดูลความปลอดภัยตรวจหน่วยความจำของเกม, โปรแกรมที่กำลังรัน และไดรเวอร์เป็นระยะ → ผลคือ ระหว่างตรวจ เธรดเกมหยุด หรือ heartbeat ส่งไปไม่ทันเวลา → บนหน้าจอ หยุดแวบเป็นจังหวะสม่ำเสมอ ถ้าหนักจะหลุดพร้อมข้อความแจ้งข้อผิดพลาดด้านความปลอดภัย
อาการ กระตุก , ค้าง , หลุด
ปัจจัย การหยุดชะงัก
ใครเจอ เราคนเดียว
เกิดเมื่อไร เป็นรอบสม่ำเสมอ, หลังล็อกอิน/หลังปิดปรับปรุง, สุ่มเป็นครั้งคราว
ผู้รับผิดชอบ ผู้รับผิดชอบหลัก พัฒนาไคลเอนต์ (ทีมพัฒนาเกม) · ร่วมกับ พัฒนาเซิร์ฟเวอร์ (ทีมพัฒนาเกม)
งานฝั่งทีมพัฒนาเกม ไคลเอนต์: ย้ายการตรวจที่หนักออกจากเธรดเกมและแบ่งรันทีละน้อย, เทียบสถิติอาการกระตุกและเกมเด้งแยกตามเวอร์ชันโมดูลความปลอดภัย (ถ้ากระจุกหลังอัปเดตให้ส่งต่อให้ผู้ผลิตโมดูล) เซิร์ฟเวอร์: ยอมให้ heartbeat มาช้าได้หนึ่งถึงสองครั้ง
ตัวเลขที่ควรรู้ การตรวจแบบเบาปกติใช้ไม่ถึง 1 ms แต่การตรวจแบบหนักที่รันบนเธรดเกมอาจกินเวลาครั้งละหลายสิบถึงหลายร้อย ms ขึ้นกับการ implement
บนกราฟ พุ่งเป็นรอบ · เฟรมไทม์, จำนวนครั้งที่ anti-cheat เตะผู้เล่นออก
จุดที่ต้องดู วัดช่วงห่างของจุดที่พุ่งในเฟรมไทม์จาก PresentMon และรวมสาเหตุที่ anti-cheat เตะผู้เล่นออกที่เซิร์ฟเวอร์ได้รับ (EOS คือ AuthenticationFailed / Authentication Timed Out ฯลฯ ใน ClientActionReason) แยกตามเวอร์ชันโมดูลความปลอดภัยและสเปก สัญญาณว่าใช่ หยุดสั้น ๆ ซ้ำเป็นจังหวะสม่ำเสมอโดยไม่เกี่ยวกับสถานการณ์ในเกม และหลังอัปเดตโมดูลความปลอดภัย บางสเปกมีอาการกระตุกและถูกเตะเพราะยืนยันตัวตนไม่ทันเวลาเพิ่มขึ้น สัญญาณว่าไม่ใช่ จังหวะเดียวกันทุกสเปกโดยไม่เกี่ยวกับเวอร์ชันโมดูลความปลอดภัย: น่าจะเป็น “GC ฝั่งไคลเอนต์” หรือ “โปรเซสเบื้องหลังแย่ง CPU” วิธีตรวจ ต้องมี log หรือเมตริกจากเซิร์ฟเวอร์/ไคลเอนต์เกม
รายละเอียดเพิ่มเติม โมดูลความปลอดภัยฝังลึกอยู่ใน OS ในรูปไดรเวอร์ จึงอาจชนกับแอนตี้ไวรัส, โอเวอร์เลย์ หรือโมดูลความปลอดภัยของเกมอื่นได้ ถ้าการแจ้งอาการกระตุกหรือเกมเด้งกระจุกอยู่ที่บางสเปกหลังอัปเดตโมดูลความปลอดภัย ให้สงสัยตัวนี้ก่อน
แหล่งอ้างอิง 2 รายการ
L2 OS และอุปกรณ์ฝั่งไคลเอนต์
15 สาเหตุ · บทในฉบับหลัก
ID co-background · ผู้รับผิดชอบหลัก ภายนอก (ภายนอก) · ร่วมกับ พัฒนาไคลเอนต์ (ทีมพัฒนาเกม)
เมื่อการสแกนของแอนตี้ไวรัส, Windows Update, โปรแกรมสตรีม หรือวิดีโอในเบราว์เซอร์ยึดคอร์ไว้ เธรดเกมจะไม่ได้รับ CPU และต้องรอ
ทำไม โปรแกรมอื่นยึดคอร์ CPU ไว้นาน → ผลคือ เธรดเกมต้องรอคิว CPU → บนหน้าจอ เฟรมช้า และการประมวลผลแพ็กเก็ตที่รับมาก็ช้าตาม
อาการ กระตุก , กรอเร็ว
ปัจจัย การหยุดชะงัก
ใครเจอ เราคนเดียว
เกิดเมื่อไร สุ่มเป็นครั้งคราว, เป็นรอบสม่ำเสมอ
ผู้รับผิดชอบ ผู้รับผิดชอบหลัก ภายนอก (ภายนอก) · ร่วมกับ พัฒนาไคลเอนต์ (ทีมพัฒนาเกม)
งานฝั่งทีมพัฒนาเกม ปรับ priority ของเธรดเกม, บันทึกอัตราการใช้ CPU ทั้งเครื่องไว้ใน log ตอนที่เกิดอาการกระตุกด้วย เพื่อแยกว่าเป็นเพราะโปรแกรมอื่นหรือไม่
งานฝั่งภายนอก แนะนำให้ผู้เล่นเปิด Game Mode ของ Windows และปิดโปรแกรมที่ไม่จำเป็นระหว่างเล่น (การสแกนของแอนตี้ไวรัส, Windows Update, โปรแกรมสตรีม และวิดีโอในเบราว์เซอร์)
ตัวเลขที่ควรรู้ ปกติ Windows จะให้แต่ละเธรดใช้คอร์ครั้งละหลักหน่วยถึงหลักสิบ ms แค่โดนเลื่อนคิว CPU ครั้งเดียวก็หายไปหนึ่งเฟรม
บนกราฟ พุ่งแบบสุ่มเป็นครั้งคราว · อัตราการใช้ CPU ทั้งเครื่อง, เฟรมไทม์
จุดที่ต้องดู บันทึกคอลัมน์ CPU ในแท็บ Processes ของ Task Manager และ Processor Information(_Total)\% Processor Time ใน Performance Monitor คู่กับเฟรมไทม์จาก PresentMon ถ้าสงสัยแอนตี้ไวรัส ให้อัดด้วย New-MpPerformanceRecording แล้วดูไฟล์และโปรเซสที่ใช้เวลาสแกนนานด้วย Get-MpPerformanceReport สัญญาณว่าใช่ ตอนที่กระตุก การใช้ CPU ของโปรแกรมอื่น (การสแกนของแอนตี้ไวรัส, อัปเดต, โปรแกรมสตรีม) พุ่งขึ้น หรือไฟล์ในโฟลเดอร์เกมขึ้นไปอยู่อันดับต้นของเวลาสแกน ปิดโปรแกรมนั้นหรือตั้งเป็นข้อยกเว้นแล้วหายไป สัญญาณว่าไม่ใช่ อัตราการใช้ CPU ต่ำแต่ทั้งจอหยุดแวบและเสียงแตกซ่า: น่าจะเป็น “โหมดประหยัดพลังงานของ NIC และปัญหาไดรเวอร์” (DPC latency) วิธีตรวจ ตรวจที่สภาพแวดล้อมฝั่งผู้เล่น
รายละเอียดเพิ่มเติม Windows ให้ priority กับโปรแกรมของหน้าต่างที่อยู่ด้านหน้า (foreground) มากขึ้นเล็กน้อย แต่ถ้ามีงานมากกว่าจำนวนคอร์ เกมก็ต้องรอ แอนตี้ไวรัสเข้ามาแทรกผ่าน “การตรวจแบบเรียลไทม์” บ่อยกว่าการใช้ CPU เสียอีก เพราะจะสแกนทุกครั้งที่เกมเปิดไฟล์ ทำให้การหยุดตอนอ่านแอสเซ็ตนานขึ้น
แหล่งอ้างอิง 6 รายการ
ID co-power · ผู้รับผิดชอบหลัก ภายนอก (ภายนอก) · ร่วมกับ พัฒนาไคลเอนต์ (ทีมพัฒนาเกม)
โหมดแบตเตอรี่ของโน้ตบุ๊ก, โหมดประหยัดพลังงานของมือถือ และความร้อนของเครื่อง ทำให้ CPU และ GPU ช้าลง จุดสังเกตของความร้อนคือช่วงแรกปกติดี แล้วค่อยช้าลงหลังเล่นไปสักพัก
ทำไม อยู่ในโหมดแบตเตอรี่หรือประหยัดพลังงาน หรือเครื่องร้อน → ผลคือ ลดคล็อกของ CPU และ GPU ลง 30–50% แล้วแต่เครื่อง → บนหน้าจอ โหมดประหยัดพลังงานเป็นตั้งแต่เปิดเกม ส่วนความร้อนจะเริ่มหลังเล่นไปไม่กี่นาทีถึงราว 20 นาที FPS ตกและกระตุก
อาการ กระตุก , อินพุตดีเลย์
ปัจจัย การหยุดชะงัก
ใครเจอ เราคนเดียว
เกิดเมื่อไร ยิ่งเปิดไว้นานยิ่งเป็น, ตลอดเวลา
ผู้รับผิดชอบ ผู้รับผิดชอบหลัก ภายนอก (ภายนอก) · ร่วมกับ พัฒนาไคลเอนต์ (ทีมพัฒนาเกม)
งานฝั่งทีมพัฒนาเกม ปรับกราฟิกอัตโนมัติ, คุมความร้อนด้วยการจำกัดเฟรมเรต, ดูระดับความร้อนที่ OS แจ้ง (thermalState ของ iOS และ thermal API ของ Android) แล้วลดตัวเลือกกราฟิกล่วงหน้า, บนโน้ตบุ๊กที่มีชิปกราฟิกสองตัว ระบุในไฟล์ executable ให้ใช้การ์ดจอแยก (export NvOptimusEnablement และ AmdPowerXpressRequestHighPerformance)
งานฝั่งภายนอก แนะนำให้ผู้เล่นปิดโหมดประหยัดพลังงาน และเสียบสายชาร์จเมื่อเล่นบนโน้ตบุ๊ก, ถ้าแจ้งมาว่า “โน้ตบุ๊กสเปกดีแต่ FPS ต่ำ” ให้ตรวจว่าเกมรันบนชิปกราฟิกตัวไหน แล้วแนะนำให้ตั้งเกมให้ใช้ GPU ประสิทธิภาพสูงในการตั้งค่ากราฟิกของ Windows
บนกราฟ ค่อย ๆ สูงขึ้น · FPS, คล็อก CPU/GPU
จุดที่ต้องดู บันทึก CPUFrequency, GPUFrequency, CPUTemperature และ GPUTemperature ของ PresentMon คู่กับเฟรมไทม์ 20–30 นาที แล้วดูคอลัมน์ GPU engine ในแท็บ Processes ของ Task Manager ว่าเกมรันบนชิปกราฟิกตัวไหน บนมือถือบันทึก thermal API ของ Android (getThermalHeadroom, thermal status) และ thermalState ของ iOS คู่กับ FPS สัญญาณว่าใช่ FPS ตกตั้งแต่จังหวะที่อุณหภูมิขึ้นแล้วคล็อกลดลง หรือคล็อกต่ำเฉพาะในโหมดแบตเตอรี่หรือประหยัดพลังงาน หรือเกมกำลังรันบนกราฟิกออนบอร์ด สัญญาณว่าไม่ใช่ คล็อกและอุณหภูมิคงที่แต่ FPS ตก: น่าจะเป็น “โปรเซสเบื้องหลังแย่ง CPU” หรือ “หน่วยความจำรั่วฝั่งไคลเอนต์” วิธีตรวจ ตรวจที่สภาพแวดล้อมฝั่งผู้เล่น
รายละเอียดเพิ่มเติม โน้ตบุ๊กที่มีชิปกราฟิกสองตัว บางครั้งก็รันเกมบนกราฟิกออนบอร์ดที่ช้ากว่าเพื่อประหยัดไฟ ถ้าการแจ้งปัญหาเป็นแบบ “โน้ตบุ๊กสเปกดีแต่ FPS ต่ำ” ให้ตรวจก่อนว่าเกมรันบนชิปกราฟิกตัวไหน
แหล่งอ้างอิง 5 รายการ
ID co-timer · ผู้รับผิดชอบหลัก พัฒนาไคลเอนต์ (ทีมพัฒนาเกม)
ตัวจับเวลาเริ่มต้นของ Windows ทำงานเป็นหน่วย 15.6 ms การ “พักแค่ 1 ms” จึงกลายเป็นการรอจนถึงรอบตัวจับเวลาถัดไป นานสุดถึง 15.6 ms
ทำไม เขียนการจำกัดเฟรมและการส่งแพ็กเก็ตด้วยวิธี Sleep (รอสักครู่) → ผลคือ OS ปลุกให้ได้เป็นหน่วย 15.6 ms เท่านั้น → บนหน้าจอ ช่วงห่างระหว่างเฟรมและช่วงห่างการส่งอินพุตไม่สม่ำเสมอ
อาการ กระตุก
ปัจจัย จิตเตอร์
ใครเจอ เราคนเดียว
เกิดเมื่อไร ตลอดเวลา
ผู้รับผิดชอบ ผู้รับผิดชอบหลัก พัฒนาไคลเอนต์ (ทีมพัฒนาเกม)
งานฝั่งทีมพัฒนาเกม ใช้ high-resolution timer, ทำ pacing ด้วย event หรือ V-Sync แทนการรอ
ตัวเลขที่ควรรู้ หน่วย 15.6 ms ทำให้ได้ช่วงห่าง 16.7 ms พอดีไม่ได้ ช่วงห่างระหว่างเฟรมจึงสลับไปมาระหว่าง 15.6 ms กับ 31.2 ms
บนกราฟ สูงตลอดตั้งแต่แรก · การกระจายของช่วงห่างระหว่างเฟรม
จุดที่ต้องดู ดูการกระจายของ MsBetweenPresents (ช่วงห่างระหว่างเฟรม) จาก PresentMon และหัวข้อ “Platform Timer Resolution” ในรายงาน powercfg /energy (โปรเซสที่เปลี่ยนความละเอียดของตัวจับเวลา) สัญญาณว่าใช่ ช่วงห่างระหว่างเฟรมกระจุกอยู่ที่ผลคูณของ 15.6 ms เช่น 15.6 ms และ 31.2 ms และเกมไม่ได้ขอความละเอียดของตัวจับเวลาที่สูงขึ้น สัญญาณว่าไม่ใช่ ช่วงห่างกระจายไปทั่ว ไม่กระจุกที่ค่าใดค่าหนึ่ง: น่าจะเป็น “โปรเซสเบื้องหลังแย่ง CPU” หรือภาระของเฟรม มากกว่าตัวจับเวลา วิธีตรวจ ตรวจที่สภาพแวดล้อมฝั่งผู้เล่น
รายละเอียดเพิ่มเติม ใน Windows รุ่นเก่า ถ้าโปรแกรมหนึ่งเปลี่ยนตัวจับเวลาเป็น 1 ms จะมีผลกับทุกโปรแกรม จึงเคยมีคำพูดว่า “เปิดเบราว์เซอร์ทิ้งไว้แล้วเกมลื่นขึ้น” ตั้งแต่ Windows 10 เวอร์ชัน 2004 จะมีผลเฉพาะโปรแกรมที่ร้องขอ และ Windows 11 อาจไม่ใช้คำขอของหน้าต่างที่ถูกย่อหรือถูกบังจนมองไม่เห็นและไม่มีเสียง
แหล่งอ้างอิง 6 รายการ
ID co-mobile-bg · ผู้รับผิดชอบหลัก พัฒนาไคลเอนต์ (ทีมพัฒนาเกม) · ร่วมกับ พัฒนาเซิร์ฟเวอร์ (ทีมพัฒนาเกม)
ถ้าย่อแอปลงไปแป๊บเดียวเพื่อดูแจ้งเตือน OS จะพักการทำงาน (suspend) ของแอปภายในไม่กี่วินาที และระหว่างนั้นเซิร์ฟเวอร์จะตัดการเชื่อมต่อของเรา
ทำไม ย่อเกมลงเพื่อเช็กข้อความหรือรับสาย → ผลคือ เอนจินเกมหยุดการทำงานของเกม และอีกไม่นาน OS ก็หยุดแอปและเครือข่ายด้วย → บนหน้าจอ กลับมาก็หลุดไปแล้ว ต้องเชื่อมต่อใหม่
อาการ หลุด
ปัจจัย การหยุดชะงัก, แพ็กเก็ตหาย
ใครเจอ เราคนเดียว
เกิดเมื่อไร หลังอยู่เฉย ๆ สักพัก, ตอนทำแอ็กชันบางอย่าง
ผู้รับผิดชอบ ผู้รับผิดชอบหลัก พัฒนาไคลเอนต์ (ทีมพัฒนาเกม) · ร่วมกับ พัฒนาเซิร์ฟเวอร์ (ทีมพัฒนาเกม)
งานฝั่งทีมพัฒนาเกม ไคลเอนต์: เมื่อกลับมาให้เชื่อมต่อใหม่อัตโนมัติด้วย session token ทันทีโดยไม่ต้องรอการเชื่อมต่อที่ขาดไป (ต่อเซสชันเดิมโดยไม่ต้องล็อกอินใหม่), รับสถานะล่าสุดครั้งเดียวแล้วปรับให้ตรงกัน เซิร์ฟเวอร์: เมื่อ heartbeat ขาด ให้ปิดการเชื่อมต่อแต่เก็บเซสชันของตัวละครไว้ในช่วงผ่อนผันสั้น ๆ (ไม่เตะออกทันที), ถ้าเชื่อมต่อใหม่ภายในช่วงนั้นให้รับช่วงต่อด้วย session token
ตัวเลขที่ควรรู้ ปกติเอนจินเกมจะหยุดทันทีที่ย่อแอป iOS จะพักการทำงานของแอปภายในไม่กี่วินาที แม้ขอเวลาเพิ่มได้ก็มักไม่เกินหลายสิบวินาที ส่วน Android 14 ขึ้นไปจะแช่แข็ง (freeze) แอปที่ออกจากหน้าจอหลังผ่านไปราว 10 วินาที
บนกราฟ การเชื่อมต่อหลุดพร้อมกัน · จำนวนครั้งที่หลุด (heartbeat timeout), บันทึกการพักแอป
จุดที่ต้องดู จับคู่เวลาที่แอปพักและกลับมาใน log ของไคลเอนต์ (Unity คือ OnApplicationPause) กับสาเหตุและเวลาที่หลุดฝั่งเซิร์ฟเวอร์ด้วย session ID บน Android ดูสาเหตุการปิดโปรเซสที่บันทึกใน ApplicationExitInfo (REASON_LOW_MEMORY ฯลฯ) ประกอบด้วย สัญญาณว่าใช่ ก่อนเซิร์ฟเวอร์ตัดการเชื่อมต่อเพราะ heartbeat timeout ไคลเอนต์เข้าสู่การพักการทำงาน และเชื่อมต่อใหม่ทันทีหลังกลับมา สัญญาณว่าไม่ใช่ หลุดระหว่างที่แอปเปิดอยู่บนหน้าจอ: น่าจะเป็น “NAT mapping หมดอายุ”, “IP ที่ ISP ให้ใช้ร่วมกัน (CGNAT)” หรือ “สลับ Wi-Fi ↔ LTE/5G” วิธีตรวจ ต้องมี log หรือเมตริกจากเซิร์ฟเวอร์/ไคลเอนต์เกม
รายละเอียดเพิ่มเติม ถ้าหน่วยความจำไม่พอ มือถือบางครั้งก็ปิดเกมที่ย่อไว้ไปเลย นี่คือเหตุผลที่สลับไปแอปกล้องหรือแอปชำระเงิน/ยืนยันตัวตนแล้วกลับมา เกมต้องเริ่มใหม่ตั้งแต่ต้น เครื่องสเปกต่ำยิ่งเจอบ่อย
แหล่งอ้างอิง 5 รายการ Extending your app’s background execution time Apple เมื่อแอปไปอยู่เบื้องหลังจะได้เวลา 5 วินาทีใน applicationDidEnterBackground แล้วถูกพักการทำงานในไม่ช้า ถ้าต้องการเวลาเพิ่มให้ขอด้วย beginBackgroundTask (เวลาที่เหลือดูได้จาก backgroundTimeRemaining) Cached apps freezer Android (Google) Android 14 ขึ้นไปจะแช่แข็งโปรเซสของแอปที่เข้าสู่สถานะ cached หลังผ่านไป 10 วินาที เมื่อถูกแช่แข็ง ทุกเธรดจะหยุด Application.runInBackground Unity ค่าเริ่มต้นเป็น false จึงหยุดเมื่ออยู่เบื้องหลัง Android จะหยุดเมื่ออยู่เบื้องหลังไม่ว่าจะตั้งค่าอย่างไร ส่วน iOS ไม่สนใจการตั้งค่านี้ MonoBehaviour.OnApplicationPause(bool) Unity เมื่อแอปถูกพักหรือกลับมาทำงาน จะส่ง OnApplicationPause(true/false) ไปยัง MonoBehaviour ทุกตัว ApplicationExitInfo Android (Google) REASON_LOW_MEMORY: low memory killer ของระบบปิดโปรเซสของแอป (เครื่องที่ไม่รองรับจะรายงานเป็น REASON_SIGNALED/SIGKILL)
ID co-netswitch · ผู้รับผิดชอบหลัก พัฒนาเซิร์ฟเวอร์ (ทีมพัฒนาเกม) · ร่วมกับ พัฒนาไคลเอนต์ (ทีมพัฒนาเกม), อินฟราเครือข่าย (ทีมอินฟรา)
เมื่อเดินออกจากบ้านแล้ว Wi-Fi หลุดและเปลี่ยนไปใช้ LTE หรือ 5G IP address ของเราจะเปลี่ยน การเชื่อมต่อเดิมจึงใช้ไม่ได้
ทำไม สัญญาณ Wi-Fi อ่อนลงจนสลับไปใช้เครือข่ายมือถือ → ผลคือ IP address ของเราเปลี่ยน การเชื่อมต่อที่สร้างด้วยที่อยู่เดิมจึงรับส่งต่อไม่ได้ → บนหน้าจอ ค้างไปครู่หนึ่ง แล้วหลุดหรือเชื่อมต่อใหม่
อาการ ค้าง , หลุด
ปัจจัย แพ็กเก็ตหาย
ใครเจอ เราคนเดียว
เกิดเมื่อไร ระหว่างเดินทาง/ย้ายแมพ
ผู้รับผิดชอบ ผู้รับผิดชอบหลัก พัฒนาเซิร์ฟเวอร์ (ทีมพัฒนาเกม) · ร่วมกับ พัฒนาไคลเอนต์ (ทีมพัฒนาเกม), อินฟราเครือข่าย (ทีมอินฟรา)
งานฝั่งทีมพัฒนาเกม เซิร์ฟเวอร์: ใช้ session token รับช่วงเป็นผู้เล่นคนเดิมแม้ที่อยู่เปลี่ยน และปิดการเชื่อมต่อของที่อยู่เดิมทันที, พิจารณาโปรโตคอลที่การเชื่อมต่อยังอยู่ได้แม้ที่อยู่เปลี่ยน (เช่น connection migration ของ QUIC) ไคลเอนต์: เมื่อตรวจพบการสลับเครือข่าย ให้เชื่อมต่อใหม่ด้วย session token ทันทีโดยไม่ต้องรอ heartbeat timeout
งานฝั่งทีมอินฟรา ถ้าใช้ connection migration ของ QUIC ให้ตั้งโหลดบาลานเซอร์ให้เลือกเซิร์ฟเวอร์ด้วย connection ID แทนที่อยู่และพอร์ต (ถ้าเลือกด้วยที่อยู่และพอร์ต แพ็กเก็ตที่มาจากที่อยู่ใหม่จะไปลงเซิร์ฟเวอร์อื่น)
บนกราฟ การเชื่อมต่อหลุดพร้อมกัน · จำนวนครั้งที่หลุดและเชื่อมต่อใหม่, IP ที่เปลี่ยนตอนเชื่อมต่อใหม่
จุดที่ต้องดู หาบันทึกใน log การเชื่อมต่อของเซิร์ฟเวอร์ที่ session token เดียวกันเชื่อมต่อใหม่ด้วย IP อื่น แล้วเทียบกับเวลาของ callback การเปลี่ยน default network ฝั่งไคลเอนต์ (registerDefaultNetworkCallback) สัญญาณว่าใช่ หลังหลุดแล้วเชื่อมต่อใหม่ IP เปลี่ยนจากช่วง IP ของ Wi-Fi (เน็ตบ้าน) ไปเป็นช่วง IP ของค่ายมือถือ หรือกลับกัน และก่อนหน้านั้นมี callback การสลับเครือข่ายเข้ามา สัญญาณว่าไม่ใช่ IP เดิมแต่หลุด: น่าจะเป็น “handover ระหว่างเสาสัญญาณ (ขณะเดินทาง)” หรือ “สัญญาณมือถืออ่อนหรืออยู่ในจุดอับสัญญาณ” วิธีตรวจ ต้องมี log หรือเมตริกจากเซิร์ฟเวอร์/ไคลเอนต์เกม
แหล่งอ้างอิง 3 รายการ
ID co-security · ผู้รับผิดชอบหลัก ภายนอก (ภายนอก) · ร่วมกับ พัฒนาไคลเอนต์ (ทีมพัฒนาเกม)
ถ้าแอนตี้ไวรัสหรือไฟร์วอลล์ตรวจทุกแพ็กเก็ต ความหน่วงจะเพิ่มขึ้น และถ้าตรวจเข้มเกินไปก็อาจเข้าใจผิดว่าเกมเป็นการโจมตีแล้วบล็อก
ทำไม โปรแกรมความปลอดภัยตรวจแพ็กเก็ตขาเข้าและขาออกทีละแพ็กเก็ต → ผลคือ ทุกแพ็กเก็ตมีดีเลย์เพิ่ม และถ้าตรวจไม่ทันก็ถูกทิ้ง → บนหน้าจอ ปิงพุ่งแบบไม่สม่ำเสมอ หรือการเชื่อมต่อถูกบล็อก
อาการ กระตุก , เข้าเกมไม่ได้/โหลดไม่จบ
ปัจจัย จิตเตอร์, แพ็กเก็ตหาย
ใครเจอ เราคนเดียว
เกิดเมื่อไร ตลอดเวลา, หลังล็อกอิน/หลังปิดปรับปรุง
ผู้รับผิดชอบ ผู้รับผิดชอบหลัก ภายนอก (ภายนอก) · ร่วมกับ พัฒนาไคลเอนต์ (ทีมพัฒนาเกม)
งานฝั่งทีมพัฒนาเกม ดูแลรายการความเข้ากันได้กับโปรแกรมความปลอดภัย, ลงทะเบียนเกมเป็นข้อยกเว้นใน Windows Firewall ตอนติดตั้ง
งานฝั่งภายนอก แนะนำให้ผู้เล่นตั้งเกมเป็นข้อยกเว้นในโปรแกรมความปลอดภัย, ถ้าโปรแกรมเข้าใจผิดว่าเกมเป็นการโจมตี ให้แจ้งผู้ผลิตโปรแกรมความปลอดภัยให้แก้ false positive
ตัวเลขที่ควรรู้ ในภาวะปกติ เวลาที่ใช้ตรวจแพ็กเก็ตมักไม่ถึง 1 ms ปัญหาอยู่ที่ตอนโมดูลตรวจทำงานไม่ทันหรือมีบั๊ก และตอนที่เข้าใจผิดว่าการสื่อสารของเกมเป็นการโจมตี
บนกราฟ สูงเฉพาะบางกลุ่ม · RTT และการเชื่อมต่อล้มเหลว (แยกตามผู้เล่น)
จุดที่ต้องดู ปิดโปรแกรมความปลอดภัยชั่วคราวหรือตั้งเกมเป็นข้อยกเว้นแล้วเทียบ บน Windows ถ้าเปิด Audit Filtering Platform Connection และ Audit Filtering Platform Packet Drop ใน audit policy จะมี 5157 (บล็อกการเชื่อมต่อ) และ 5152 (บล็อกแพ็กเก็ต) ใน Security log และดูจำนวนแพ็กเก็ตที่ถูกทิ้งได้จาก WFPv4\Packets Discarded/sec ใน Performance Monitor สัญญาณว่าใช่ มีบันทึกการบล็อกการเชื่อมต่อหรือแพ็กเก็ตที่ไปยังที่อยู่ของเซิร์ฟเวอร์เกม หรือปิดโปรแกรมความปลอดภัยแล้วอาการปิงพุ่งและเข้าเกมไม่ได้หายไป สัญญาณว่าไม่ใช่ อุปกรณ์อื่นในบ้านเดียวกันก็เป็นเหมือนกันโดยไม่เกี่ยวกับโปรแกรมความปลอดภัย: ให้ดูเราเตอร์และเน็ต วิธีตรวจ ตรวจที่สภาพแวดล้อมฝั่งผู้เล่น
แหล่งอ้างอิง 6 รายการ
ID co-rcvbuf · ผู้รับผิดชอบหลัก พัฒนาไคลเอนต์ (ทีมพัฒนาเกม)
ถ้าเกมยุ่งจนดึงแพ็กเก็ตออกจากซ็อกเก็ต (อินเทอร์เฟซรับส่งข้อมูลเครือข่ายที่ OS จัดให้) ช้า บัฟเฟอร์ของ OS จะล้น
ทำไม เฟรมช้าจนเกมอ่านซ็อกเก็ตไม่ทัน → ผลคือ receive buffer ของ OS เต็ม UDP จะถูกทิ้ง ส่วน TCP จะลด receive window ให้ฝั่งส่งหยุดส่ง → บนหน้าจอ วาร์ป (UDP) หรือกรอเร็ว (TCP)
อาการ วาร์ป , กรอเร็ว
ปัจจัย แพ็กเก็ตหาย, การหยุดชะงัก
ใครเจอ เราคนเดียว
เกิดเมื่อไร ตอนคนแห่มารวมกัน
ผู้รับผิดชอบ ผู้รับผิดชอบหลัก พัฒนาไคลเอนต์ (ทีมพัฒนาเกม)
งานฝั่งทีมพัฒนาเกม แยกเธรดสำหรับรับข้อมูลโดยเฉพาะ, ปรับขนาดบัฟเฟอร์ (SO_RCVBUF)
ตัวเลขที่ควรรู้ receive buffer เริ่มต้นมีขนาดหลายสิบถึงหลายร้อย KB ขึ้นกับ OS และการตั้งค่า อัปเดตในที่ที่คนเยอะอาจสูงถึงหลายร้อย KB ใน 1 วินาที
บนกราฟ สูงตามจำนวนคนและโหลด · จำนวน UDP ที่ถูกทิ้งที่ receive buffer, เฟรมไทม์
จุดที่ต้องดู บันทึก Microsoft Winsock BSP\Dropped Datagrams (จำนวน UDP ที่ถูกทิ้งเพราะ receive buffer ของซ็อกเก็ตไม่พอ) และ UDPv4\Datagrams Received Errors ใน Performance Monitor ของ Windows คู่กับเฟรมไทม์ ฝั่งเกมนับช่องว่างของหมายเลขลำดับแพ็กเก็ตที่ได้รับ สัญญาณว่าใช่ ในที่ที่คนเยอะหรือทันทีหลังเฟรมยาว Dropped Datagrams เพิ่มขึ้น และในจังหวะเดียวกันหมายเลขลำดับในเกมมีช่องว่าง ขณะที่ช่วงเวลาเดียวกันไม่มีแพ็กเก็ตหายฝั่งเน็ต สัญญาณว่าไม่ใช่ Dropped Datagrams เท่าเดิมแต่หมายเลขลำดับขาดหาย: แพ็กเก็ตหายระหว่างทาง วิธีตรวจ ตรวจที่สภาพแวดล้อมฝั่งผู้เล่น
แหล่งอ้างอิง 5 รายการ
ID co-swap · ผู้รับผิดชอบหลัก ภายนอก (ภายนอก) · ร่วมกับ พัฒนาไคลเอนต์ (ทีมพัฒนาเกม)
ถ้าเปิดแท็บเบราว์เซอร์หลายสิบแท็บพร้อมกับเกม OS จะย้ายหน่วยความจำบางส่วนของเกมไปไว้บนดิสก์
ทำไม RAM ทั้งเครื่องไม่พอ → ผลคือ OS ย้ายหน่วยความจำของเกมที่ยังไม่ได้ใช้ตอนนี้ไปไว้บนดิสก์ → บนหน้าจอ จังหวะที่กลับมาใช้ส่วนนั้นอีก เกมค้างหลายสิบถึงหลายร้อย ms ขึ้นกับสตอเรจ
อาการ ค้าง , กระตุก
ปัจจัย การหยุดชะงัก
ใครเจอ เราคนเดียว
เกิดเมื่อไร ระหว่างเดินทาง/ย้ายแมพ, สุ่มเป็นครั้งคราว
ผู้รับผิดชอบ ผู้รับผิดชอบหลัก ภายนอก (ภายนอก) · ร่วมกับ พัฒนาไคลเอนต์ (ทีมพัฒนาเกม)
งานฝั่งทีมพัฒนาเกม ลดการใช้หน่วยความจำ, แสดงคำเตือนเมื่อหน่วยความจำเหลือน้อย
งานฝั่งภายนอก แจ้งสเปกขั้นต่ำให้ผู้เล่น, แนะนำให้ปิดโปรแกรมอื่น (เช่น แท็บเบราว์เซอร์) ระหว่างเล่น
บนกราฟ พุ่งแบบสุ่มเป็นครั้งคราว · hard page fault, ปริมาณการใช้หน่วยความจำ
จุดที่ต้องดู บันทึก Memory\Pages Input/sec (จำนวนเพจที่อ่านจากดิสก์เพื่อแก้ hard page fault) ใน Performance Monitor และปริมาณการใช้หน่วยความจำและ commit ในแท็บ Performance ของ Task Manager คู่กับเฟรมไทม์ สัญญาณว่าใช่ ตอนที่ค้าง Pages Input/sec พุ่งขึ้นและหน่วยความจำเกือบเต็ม ปิดโปรแกรมอื่นเช่นเบราว์เซอร์แล้วหายไป สัญญาณว่าไม่ใช่ หน่วยความจำยังเหลือและ Pages Input/sec นิ่ง: น่าจะเป็น “โหลดแบบ synchronous และคอมไพล์ shader บนเมนเธรด” หรือ “สตอเรจช้าจนสตรีมแอสเซ็ตไม่ทัน” วิธีตรวจ ตรวจที่สภาพแวดล้อมฝั่งผู้เล่น
แหล่งอ้างอิง 3 รายการ
ID co-vram · ผู้รับผิดชอบหลัก พัฒนาไคลเอนต์ (ทีมพัฒนาเกม) · ร่วมกับ ภายนอก (ภายนอก)
ถ้าหน่วยความจำที่ตัวเลือกกราฟิกต้องการมากกว่าหน่วยความจำของการ์ดจอ OS จะย้าย texture ไปไว้ในหน่วยความจำของ PC แล้วดึงกลับมาใหม่ ภาพจึงกระตุก
ทำไม ตัวเลือก texture สูง และอุปกรณ์สวมใส่กับเอฟเฟกต์สารพัดในที่ที่คนเยอะ ทำให้หน่วยความจำการ์ดจอเต็ม → ผลคือ OS ย้าย texture ที่ยังไม่ได้ใช้ตอนนี้ไปไว้ในหน่วยความจำของ PC แล้วดึงกลับผ่านบัส PCIe ที่ช้ากว่าเมื่อต้องใช้ → บนหน้าจอ หยุดแวบทุกครั้งที่เห็นฉากใหม่หรือตัวละครใหม่ texture เบลออยู่พักหนึ่ง
อาการ กระตุก , ค้าง
ปัจจัย การหยุดชะงัก
ใครเจอ เราคนเดียว
เกิดเมื่อไร ตอนคนแห่มารวมกัน, ระหว่างเดินทาง/ย้ายแมพ
ผู้รับผิดชอบ ผู้รับผิดชอบหลัก พัฒนาไคลเอนต์ (ทีมพัฒนาเกม) · ร่วมกับ ภายนอก (ภายนอก)
งานฝั่งทีมพัฒนาเกม ตั้งค่าเริ่มต้นของตัวเลือกให้เหมาะกับขนาดหน่วยความจำการ์ดจอ, ลดคุณภาพ texture อัตโนมัติเมื่อเกินงบหน่วยความจำ, ลดรายละเอียด texture ตัวละครในที่ที่คนเยอะ
งานฝั่งภายนอก แนะนำให้ผู้เล่นลดตัวเลือก texture, ถ้าเปิดไคลเอนต์สองจอ แนะนำให้ลดตัวเลือกลงอีก
ตัวเลขที่ควรรู้ หน่วยความจำการ์ดจออ่านได้หลายร้อย GB ใน 1 วินาที แต่บัส PCIe ที่รับส่งกับหน่วยความจำของ PC ทำได้ราว 16–64 GB ใน 1 วินาทีตามรุ่น จึงช้ากว่าเกินสิบเท่า
บนกราฟ ชนเพดานแล้วแบนราบ · หน่วยความจำ GPU เฉพาะ, หน่วยความจำ GPU ที่ใช้ร่วมกัน
จุดที่ต้องดู ดูกราฟหน่วยความจำ GPU เฉพาะและหน่วยความจำ GPU ที่ใช้ร่วมกันในหัวข้อ GPU ของแท็บ Performance ใน Task Manager (เพิ่มคอลัมน์รายโปรเซสในแท็บ Details ได้) คู่กับเฟรมไทม์จาก PresentMon สัญญาณว่าใช่ ช่วงที่หน่วยความจำ GPU เฉพาะชนเพดานจนแบนราบและหน่วยความจำ GPU ที่ใช้ร่วมกันเพิ่มขึ้น มีอาการหยุดแวบบ่อย และลดตัวเลือก texture แล้วหายไป สัญญาณว่าไม่ใช่ หน่วยความจำ GPU เฉพาะยังเหลือ: น่าจะเป็น “สตอเรจช้าจนสตรีมแอสเซ็ตไม่ทัน” หรือ “โหลดแบบ synchronous และคอมไพล์ shader บนเมนเธรด” วิธีตรวจ ตรวจที่สภาพแวดล้อมฝั่งผู้เล่น
รายละเอียดเพิ่มเติม ถ้าในหัวข้อ GPU ของ Task Manager บน Windows “หน่วยความจำ GPU เฉพาะ (Dedicated GPU memory)” เต็มและ “หน่วยความจำ GPU ที่ใช้ร่วมกัน (Shared GPU memory)” เพิ่มขึ้น คือภาวะนี้ ถ้าเปิดไคลเอนต์สองจอบน PC เครื่องเดียวกันจะเต็มเร็วขึ้น (ดูรายการ “หน่วยความจำ/VRAM ไม่พอจนสตรีมล้มเหลว”)
แหล่งอ้างอิง 4 รายการ Residency Microsoft แต่ละโปรเซสมีงบหน่วยความจำกราฟิกที่ใช้ได้ ถ้าเกิน เคอร์เนลจะย้าย heap บางส่วนของ GPU แยกไปไว้ในหน่วยความจำของ PC (เป็นทางเลือกสุดท้าย จึงแนะนำให้จัดการงบเอง) GPUs in the task manager Microsoft หน่วยความจำ GPU เฉพาะใน Task Manager คือ VRAM ของการ์ดจอ ส่วนหน่วยความจำ GPU ที่ใช้ร่วมกันคือหน่วยความจำของ PC ที่ GPU และ CPU ใช้ร่วมกัน CUDA C++ Best Practices Guide NVIDIA แบนด์วิดท์หน่วยความจำกราฟิก (V100 898 GB/s) สูงกว่า PCIe x16 รุ่นที่ 3 (16 GB/s) มาก จึงแนะนำให้ลดการรับส่งกับหน่วยความจำของ PC PresentMon Capture Application (README-CaptureApplication.md) Intel อัดเวลาของแต่ละเฟรมด้วย FrameTime (เวลา CPU ระหว่างเฟรม)
ID co-wifi-scan · ผู้รับผิดชอบหลัก ภายนอก (ภายนอก) · ร่วมกับ พัฒนาไคลเอนต์ (ทีมพัฒนาเกม)
ระหว่างที่ OS สลับช่องสัญญาณไปมาเป็นระยะเพื่อหา Wi-Fi รอบตัว การรับส่งข้อมูลจะหยุดไปครู่หนึ่ง
ทำไม OS หรือไดรเวอร์ค้นหา Wi-Fi รอบตัวเป็นรอบ → ผลคือ ระหว่างค้นหา การรับส่งข้อมูลหยุดไปครู่หนึ่ง → บนหน้าจอ ปิงพุ่งเป็นจังหวะที่ห่างเท่ากันเป๊ะ (เช่น ทุก 60 วินาที)
อาการ กระตุก , วาร์ป
ปัจจัย จิตเตอร์
ใครเจอ เราคนเดียว
เกิดเมื่อไร เป็นรอบสม่ำเสมอ
ผู้รับผิดชอบ ผู้รับผิดชอบหลัก ภายนอก (ภายนอก) · ร่วมกับ พัฒนาไคลเอนต์ (ทีมพัฒนาเกม)
งานฝั่งทีมพัฒนาเกม ขอโหมดที่ลดการค้นหาไร้สายระหว่างเล่น (Android คือโหมด Wi-Fi low latency WIFI_MODE_FULL_LOW_LATENCY, Windows คือโหมด media streaming ของ WlanSetInterface ซึ่งบางเครื่องหรือบางไดรเวอร์อาจไม่ได้ผล)
งานฝั่งภายนอก แนะนำให้ผู้เล่นใช้สาย LAN, ปรับการตั้งค่าบริการตำแหน่งและการค้นหา Wi-Fi อัตโนมัติ, อัปเดตไดรเวอร์ไร้สาย
ตัวเลขที่ควรรู้ ปกติครั้งละหลายสิบถึงหลายร้อย ms ถ้าเป็นจังหวะสม่ำเสมอเกินไป ให้สงสัยสาเหตุนี้ก่อน
บนกราฟ พุ่งเป็นรอบ · RTT ถึงเราเตอร์
จุดที่ต้องดู ระหว่างเล่น ใช้ ping /t วัดไปที่อยู่ของเราเตอร์ (default gateway จาก ipconfig) สักหลายนาที แล้ววัดช่วงห่างของจุดที่พุ่ง จากนั้นเปลี่ยนเป็นสาย LAN แล้ววัดแบบเดียวกัน สัญญาณว่าใช่ ปิงถึงเราเตอร์พุ่งหลายสิบถึงหลายร้อย ms เป็นจังหวะห่างเท่ากันเป๊ะ (เช่น 60 วินาที) และหายไปเมื่อใช้สาย LAN สัญญาณว่าไม่ใช่ ช่วงห่างของจุดที่พุ่งไม่สม่ำเสมอ: น่าจะเป็น “Wi-Fi ถูกรบกวนหรือสัญญาณอ่อน” ถ้าถึงเราเตอร์ปกติแต่พุ่งเฉพาะช่วงที่เลยออกไป ให้ดูเน็ตและช่วงของ ISP วิธีตรวจ ตรวจที่สภาพแวดล้อมฝั่งผู้เล่น
แหล่งอ้างอิง 5 รายการ WDI low latency connection quality Microsoft การค้นหาและ roaming ย้ายชิปไร้สายออกนอกช่องสัญญาณที่เชื่อมต่ออยู่ โหมด low latency จึงจำกัดเวลาที่ออกนอกช่องสัญญาณและการค้นหา WlanSetInterface function (wlanapi.h) Microsoft API สำหรับเปิดปิดการค้นหาเบื้องหลัง (wlan_intf_opcode_background_scan_enabled) และโหมด media streaming บน Windows Wi-Fi low-latency mode Android (Google) โหมด low latency จะปิดการประหยัดพลังงานของ Wi-Fi ส่วนการปรับแต่งการค้นหาและ roaming ขึ้นกับการ implement ของผู้ผลิตเครื่อง ping Microsoft /t: ส่ง echo request ต่อไปเรื่อย ๆ จนกว่าจะสั่งหยุด ipconfig Microsoft ถ้ารันโดยไม่ใส่พารามิเตอร์ จะแสดงที่อยู่ IPv4/IPv6 และ default gateway ของแต่ละอะแดปเตอร์
ID co-driver · ผู้รับผิดชอบหลัก ภายนอก (ภายนอก) · ร่วมกับ พัฒนาไคลเอนต์ (ทีมพัฒนาเกม)
ถ้าการ์ด LAN หรือชิป Wi-Fi เข้าสู่โหมดประหยัดพลังงานระหว่างแพ็กเก็ต จะต้องใช้เวลากว่าจะกลับมาทำงาน
ทำไม เปิดฟีเจอร์ประหยัดพลังงานของอุปกรณ์เครือข่ายไว้ หรือไดรเวอร์เก่า → ผลคือ ดีเลย์จากการตื่นจากโหมดประหยัดพลังงาน (wake-up) บางครั้งอุปกรณ์รีสตาร์ต → บนหน้าจอ ดีเลย์ไม่สม่ำเสมอ นาน ๆ ครั้งค้างไปหลายวินาที
อาการ กระตุก , ค้าง
ปัจจัย จิตเตอร์, แพ็กเก็ตหาย
ใครเจอ เราคนเดียว
เกิดเมื่อไร หลังอยู่เฉย ๆ สักพัก, สุ่มเป็นครั้งคราว
ผู้รับผิดชอบ ผู้รับผิดชอบหลัก ภายนอก (ภายนอก) · ร่วมกับ พัฒนาไคลเอนต์ (ทีมพัฒนาเกม)
งานฝั่งทีมพัฒนาเกม ไคลเอนต์ Android ขอโหมด Wi-Fi low latency (WIFI_MODE_FULL_LOW_LATENCY) ระหว่างเล่นเพื่อปิดการประหยัดพลังงานของ Wi-Fi
งานฝั่งภายนอก แนะนำให้ผู้เล่นอัปเดตไดรเวอร์เครือข่าย และปิดการประหยัดพลังงานของอุปกรณ์เครือข่ายใน Device Manager, ถ้าทั้งจอหยุดแวบและเสียงแตกซ่า แนะนำให้ใช้ LatencyMon หาไดรเวอร์ต้นเหตุ
บนกราฟ พุ่งแบบสุ่มเป็นครั้งคราว · เวลา DPC/ISR, RTT ถึงเราเตอร์
จุดที่ต้องดู อัดด้วย Windows Performance Recorder (WPR) แล้วหาไดรเวอร์ที่ทำงานนาน (คอลัมน์ Module) ในกราฟ DPC/ISR ของ Windows Performance Analyzer (WPA) และตรวจการตั้งค่า power management (ประหยัดพลังงาน) ของ network adapter ใน Device Manager สัญญาณว่าใช่ ตอนที่หยุดแวบ DPC/ISR ของไดรเวอร์เครือข่ายทำงานต่อเนื่องครั้งละหลาย ms หรือปิดการประหยัดพลังงานแล้วดีเลย์ที่ไม่สม่ำเสมอหายไป สัญญาณว่าไม่ใช่ DPC สั้น และปิดการประหยัดพลังงานแล้วก็ยังเหมือนเดิม: น่าจะเป็น “Wi-Fi ถูกรบกวนหรือสัญญาณอ่อน” หรือ “การสแกน Wi-Fi เบื้องหลัง” วิธีตรวจ ตรวจที่สภาพแวดล้อมฝั่งผู้เล่น
รายละเอียดเพิ่มเติม ถ้าไดรเวอร์ใช้ CPU นานเพื่อจัดการอินเทอร์รัปต์ (บน Windows เรียกว่า DPC latency) ระหว่างนั้นเธรดเกมก็ใช้คอร์นั้นไม่ได้ อาการคือทั้งจอหยุดแวบและเสียงแตกซ่าทั้งที่อัตราการใช้ CPU ต่ำ หาได้ว่าเป็นไดรเวอร์ตัวไหนด้วยเครื่องมืออย่าง LatencyMon ต้นเหตุที่พบบ่อยคือไดรเวอร์ Wi-Fi และ LAN
แหล่งอ้างอิง 4 รายการ
ID co-other-apps · ผู้รับผิดชอบหลัก ภายนอก (ภายนอก) · ร่วมกับ พัฒนาไคลเอนต์ (ทีมพัฒนาเกม)
ถ้าการซิงก์ไฟล์ขึ้นคลาวด์, การดาวน์โหลดไฟล์ใหญ่ หรือแพตช์เกมกำลังทำงานบน PC เครื่องเดียวกัน แพ็กเก็ตเกมจะต้องรอในคิว
ทำไม แอปอื่นใช้อัปโหลดหรือดาวน์โหลดเต็มที่ → ผลคือ แพ็กเก็ตเกมกองรอในคิวของ PC และเราเตอร์ → บนหน้าจอ ปิงพุ่งสูงมาก, อินพุตดีเลย์, กรอเร็ว
อาการ อินพุตดีเลย์ , กรอเร็ว
ปัจจัย ความหน่วง, จิตเตอร์
ใครเจอ เราคนเดียว, คนในบ้านเดียวกัน
เกิดเมื่อไร สุ่มเป็นครั้งคราว
ผู้รับผิดชอบ ผู้รับผิดชอบหลัก ภายนอก (ภายนอก) · ร่วมกับ พัฒนาไคลเอนต์ (ทีมพัฒนาเกม)
งานฝั่งทีมพัฒนาเกม ให้ launcher และ patcher ของเราหยุดหรือจำกัดความเร็วการดาวน์โหลดเบื้องหลังระหว่างเล่น
งานฝั่งภายนอก แนะนำให้ผู้เล่นจำกัดความเร็วดาวน์โหลด และปิดการอัปเดตอัตโนมัติระหว่างเล่น
บนกราฟ สูงตามจำนวนคนและโหลด · RTT, ปริมาณรับส่งของ PC
จุดที่ต้องดู บันทึก Network Interface\Bytes Sent/sec และ Bytes Received/sec ใน Performance Monitor คู่กับปิง วิธีเดียวกับการทดสอบ bufferbloat ที่เปิดปิงทิ้งไว้แล้วจงใจส่งข้อมูลจำนวนมาก สัญญาณว่าใช่ ระหว่างที่ดาวน์โหลดหรืออัปโหลดเกือบเต็มความเร็วเน็ต ปิงขึ้นไปหลายสิบถึงหลายร้อย ms และกลับมาทันทีเมื่อหยุดส่ง สัญญาณว่าไม่ใช่ ปริมาณรับส่งของ PC ต่ำแต่ปิงขึ้น: น่าจะเป็น “bufferbloat (คิวในเราเตอร์)” จากอุปกรณ์อื่นในบ้านเดียวกัน หรือช่วงของ ISP วิธีตรวจ ตรวจที่สภาพแวดล้อมฝั่งผู้เล่น
แหล่งอ้างอิง 4 รายการ Introduction Bufferbloat.net ถ้าอุปกรณ์เครือข่ายอย่างเราเตอร์เก็บข้อมูลไว้มากเกินไป ดีเลย์จะพุ่งสูงมาก (bufferbloat) Delivery Optimization reference Microsoft ค่าเริ่มต้นของการดาวน์โหลด Windows Update (Delivery Optimization) จะปรับตามแบนด์วิดท์ที่ใช้ได้แบบไดนามิก และตั้งเพดานแบนด์วิดท์การดาวน์โหลดเบื้องหลังและเบื้องหน้าได้ Network-Related Performance Counters Microsoft ตัวนับ Network Interface: Bytes Received/sec และ Bytes Sent/sec Tests for Bufferbloat Bufferbloat.net ถ้าเปิดปิงทิ้งไว้แล้วใช้การทดสอบความเร็วทำให้เน็ตเต็ม แล้วปิงขึ้น คือ bufferbloat
ID co-unfocused · ผู้รับผิดชอบหลัก พัฒนาไคลเอนต์ (ทีมพัฒนาเกม)
เมื่อไปดูหน้าต่างอื่นหรือย่อเกม ตัวเกมและ Windows จะลดความเร็วการทำงานของเกมเพื่อประหยัดไฟ พอกลับมา แพ็กเก็ตที่กองรอจะทะลักเข้ามา หรือหลุดไปแล้ว
ทำไม กด Alt+Tab ไปดูหน้าต่างอื่น หรือย่อเกม → ผลคือ ระหว่างที่มองไม่เห็นเกม เกมลด FPS ลงมากหรือหยุด และ Windows ก็ลด priority ของโปรแกรมที่มองไม่เห็นด้วย → บนหน้าจอ ทันทีที่กลับมาเกิดอาการกรอเร็ว ถ้าย่อไว้นานจะหลุด
อาการ กรอเร็ว , กระตุก , หลุด
ปัจจัย การหยุดชะงัก
ใครเจอ เราคนเดียว
เกิดเมื่อไร ตอนทำแอ็กชันบางอย่าง, หลังอยู่เฉย ๆ สักพัก
ผู้รับผิดชอบ ผู้รับผิดชอบหลัก พัฒนาไคลเอนต์ (ทีมพัฒนาเกม)
งานฝั่งทีมพัฒนาเกม ให้การรับแพ็กเก็ตและ heartbeat ทำงานต่อในเธรดแยกแม้มองไม่เห็นหน้าต่าง, ตรวจการตั้งค่า “Run In Background” ของเอนจิน, ตอนกลับมาให้ปรับเป็นสถานะล่าสุดในครั้งเดียว
ตัวเลขที่ควรรู้ ถ้าลด FPS เหลือ 5–10 ตอนที่มองไม่เห็นหน้าต่าง หนึ่งเฟรมจะยาว 100–200 ms เกมที่ประมวลผลแพ็กเก็ตทุกเฟรมก็จะอ่านแพ็กเก็ตช้าลงเท่านั้น
บนกราฟ ขาดช่วงแล้วมารวดเดียว · ช่วงห่างระหว่างเฟรม (ก่อนและหลังสลับหน้าต่าง), จำนวนแพ็กเก็ตที่ประมวลผล
จุดที่ต้องดู เปิด PresentMon ไว้แล้วลองกด Alt+Tab หรือย่อหน้าต่าง ดูช่วงห่างระหว่างเฟรมตอนที่มองไม่เห็นหน้าต่าง บันทึกเวลาที่โฟกัสหน้าต่างเปลี่ยนลง log ของเกม แล้วเทียบกับสาเหตุที่หลุด สัญญาณว่าใช่ ระหว่างที่มองไม่เห็นหน้าต่าง ช่วงห่างระหว่างเฟรมยาวขึ้นเกิน 100 ms หรือบันทึกขาดหาย และทันทีที่กลับมา เกมประมวลผลแพ็กเก็ตที่กองรอรวดเดียวจนเกิดอาการกรอเร็ว ถ้าย่อไว้นานจะหลุดเพราะ heartbeat timeout สัญญาณว่าไม่ใช่ เปิดหน้าต่างไว้ก็ยังเป็นเหมือนกัน: น่าจะเป็น “โปรเซสเบื้องหลังแย่ง CPU” หรือฝั่งเครือข่าย วิธีตรวจ ตรวจที่สภาพแวดล้อมฝั่งผู้เล่น
รายละเอียดเพิ่มเติม Windows 11 ไม่รับประกันตัวจับเวลา 1 ms ให้โปรแกรมของหน้าต่างที่ถูกย่อหรือถูกบังมิดและไม่มีเสียง บนโน้ตบุ๊กที่ใช้แบตเตอรี่ Windows จะลดความเร็วของโปรแกรมแบบนี้ลงไปที่ระดับที่ใช้ไฟน้อยที่สุด และถ้าเป็น CPU ที่มีคอร์หลายแบบผสมกัน ก็อาจย้ายไปรันบน efficiency core ที่ช้ากว่า ถ้าไคลเอนต์สองตัวใน PC เครื่องเดียวกันผิดปกติเฉพาะตัวที่อยู่เบื้องหลัง ให้ดูรายการ “จำกัดการประมวลผลของหน้าต่างเบื้องหลัง” ประกอบด้วย
แหล่งอ้างอิง 4 รายการ
ID co-overlay · ผู้รับผิดชอบหลัก ภายนอก (ภายนอก) · ร่วมกับ พัฒนาไคลเอนต์ (ทีมพัฒนาเกม)
โปรแกรมแชต, launcher, โปรแกรมอัดจอ และโปรแกรมแสดง FPS จะแทรกเข้าไปในขั้นตอนการเรนเดอร์ของเกม (hooking) เพื่อวาด UI ของตัวเองทับบนจอเกม งานในแต่ละเฟรมจึงเพิ่มขึ้น และบางครั้งก็ชนกับเกมจนภาพหยุดแวบหรือเกมถูกบังคับปิด
ทำไม เปิดโอเวอร์เลย์ของโปรแกรมแชต, game launcher, เครื่องมือของการ์ดจอ หรือโปรแกรมอัดจอไว้ → ผลคือ ทุกครั้งที่ส่งเฟรมออกจอ โอเวอร์เลย์จะแทรกเข้ามาวาด UI ของตัวเองทับ → บนหน้าจอ เฟรมช้าลงทีละนิด และตอนที่แจ้งเตือนโผล่ขึ้นมา ภาพหยุดแวบ กราฟิกเพี้ยน หรือเกมถูกบังคับปิด (ผู้เล่นเห็นเหมือนหลุด)
อาการ กระตุก , ค้าง , หลุด
ปัจจัย การหยุดชะงัก
ใครเจอ เราคนเดียว
เกิดเมื่อไร ตลอดเวลา, สุ่มเป็นครั้งคราว
ผู้รับผิดชอบ ผู้รับผิดชอบหลัก ภายนอก (ภายนอก) · ร่วมกับ พัฒนาไคลเอนต์ (ทีมพัฒนาเกม)
งานฝั่งทีมพัฒนาเกม รวบรวมรายการโอเวอร์เลย์ที่กำลังทำงานไปพร้อมกับรายงานการแครชและ log อาการกระตุก
งานฝั่งภายนอก เมื่อได้รับการแจ้งปัญหา แนะนำให้ผู้เล่นปิดโอเวอร์เลย์ทั้งหมดแล้วลองใหม่
บนกราฟ สูงเฉพาะบางกลุ่ม · เฟรมไทม์และจำนวนการแครช (ผู้เล่นที่เปิดโอเวอร์เลย์)
จุดที่ต้องดู ปิดโอเวอร์เลย์ทั้งหมดแล้วเทียบเฟรมไทม์จาก PresentMon ในฉากเดียวกัน ถ้ามีการแครช ดูชื่อโมดูลที่ผิดพลาด (Faulting module name) ใน Event ID 1000 ของ Event Viewer สัญญาณว่าใช่ ปิดโอเวอร์เลย์แล้วอาการหยุดแวบหรือกราฟิกเพี้ยนหายไป หรือโมดูลที่ผิดพลาดในการแครชคือ DLL ของโปรแกรมโอเวอร์เลย์ สัญญาณว่าไม่ใช่ ปิดโอเวอร์เลย์ทั้งหมดแล้วยังเหมือนเดิม: น่าจะเป็นไดรเวอร์กราฟิก หรือ “ไคลเอนต์แครช” วิธีตรวจ ตรวจที่สภาพแวดล้อมฝั่งผู้เล่น
รายละเอียดเพิ่มเติม ถ้ากระตุกหรือเกมปิดเองเฉพาะบางคน และอธิบายด้วยสเปกไม่ได้ ให้สงสัยการชนกันระหว่างโอเวอร์เลย์กับโมดูลความปลอดภัยของเกมก่อน
แหล่งอ้างอิง 3 รายการ
ID co-display-input · ผู้รับผิดชอบหลัก ภายนอก (ภายนอก) · ร่วมกับ พัฒนาไคลเอนต์ (ทีมพัฒนาเกม)
ถ้าปิงปกติแต่การควบคุมรู้สึกหนืด อาจเป็นเพราะการประมวลผลภาพของทีวี, คอนโทรลเลอร์ไร้สาย หรือ frame generation กำลังเพิ่มดีเลย์ระหว่างอินพุตกับภาพบนจอ
ทำไม ปิด Game Mode ของทีวีไว้, ใช้คอนโทรลเลอร์ Bluetooth หรือไร้สาย หรือเปิด frame generation (DLSS/FSR Frame Generation) → ผลคือ ทีวีส่งเฟรมออกช้าลงระหว่างประมวลผลคุณภาพภาพ, อินพุตไร้สายมาถึงช้าตามรอบการส่งและสัญญาณรบกวน และ frame generation ต้องรอเฟรมถัดไปก่อนจึงสร้างเฟรมคั่นกลางได้ → บนหน้าจอ ปิงและตัวเลข FPS ดี แต่กดแล้วกว่าจะเห็นผลบนจอช้า เป็นอาการอินพุตดีเลย์
อาการ อินพุตดีเลย์
ปัจจัย ความหน่วง
ใครเจอ เราคนเดียว
เกิดเมื่อไร ตลอดเวลา
ผู้รับผิดชอบ ผู้รับผิดชอบหลัก ภายนอก (ภายนอก) · ร่วมกับ พัฒนาไคลเอนต์ (ทีมพัฒนาเกม)
งานฝั่งทีมพัฒนาเกม ให้ frame generation เป็นตัวเลือก และแจ้งว่าเปิดแล้วอินพุตดีเลย์อาจเพิ่มขึ้น, เมื่อใช้ frame generation ให้เชื่อมกับฟีเจอร์ลดดีเลย์ของผู้ผลิตการ์ดจอ (NVIDIA Reflex, AMD Anti-Lag 2) ด้วย, แสดงดีเลย์จากอินพุตถึงจอฝั่ง PC ในเกม, บิลด์สำหรับ Android TV และ set-top box ใช้ Window.setPreferMinimalPostProcessing(true) เพื่อขอโหมด low latency (ALLM) จากทีวี
งานฝั่งภายนอก แนะนำให้ผู้เล่นเปิด Game Mode (ALLM) ของทีวีหรือจอ, ใช้คอนโทรลเลอร์แบบมีสายและปิด frame generation ในคอนเทนต์ที่แข่งขัน, วางอุปกรณ์ Bluetooth ไว้ใกล้ และใช้ Wi-Fi 5 GHz
ตัวเลขที่ควรรู้ จอ 60 Hz ใช้เวลาส่งหนึ่งเฟรมอย่างเดียวก็ 16.7 ms ส่วน 120 Hz ใช้ 8.3 ms คอนโทรลเลอร์ Xbox รุ่นเก่าอ่านและส่งอินพุตทุก 8 ms ดีเลย์ที่การประมวลผลภาพของทีวีเพิ่มขึ้นมาต่างกันไปตามรุ่นจนบอกเป็นตัวเลขเดียวได้ยาก และ Game Mode คือการตั้งค่าที่ลดการประมวลผลนี้ สำหรับ frame generation ทาง AMD แนะนำให้ใช้เมื่อเฟรมเรตก่อนสร้างเฟรมอยู่ที่ 60 FPS ขึ้นไป
บนกราฟ สูงตลอดตั้งแต่แรก · ดีเลย์จากอินพุตถึงจอ
จุดที่ต้องดู เทียบ MsAllInputToPhotonLatency (ตั้งแต่อินพุตคีย์บอร์ด/เมาส์จนส่งภาพออกจอ) ของ PresentMon ขณะเปิดและปิด frame generation และดูจาก FrameType (บันทึกเฉพาะเมื่อไดรเวอร์หรือ SDK แจ้งมา) ว่ามีเฟรมคั่นกลางที่สร้างขึ้นปนอยู่หรือไม่ ค่านี้ไม่รวมช่วงไร้สายของคอนโทรลเลอร์และการประมวลผลในทีวี ส่วนนั้นให้เทียบโดยสลับไปใช้ Game Mode ของทีวีหรือคอนโทรลเลอร์แบบมีสาย สัญญาณว่าใช่ ปิงปกติ แต่ปิด frame generation แล้วดีเลย์จากอินพุตถึงจอลดลง หรือเปลี่ยนเป็น Game Mode ของทีวีหรือคอนโทรลเลอร์แบบมีสายแล้วรู้สึกว่าดีเลย์หายไป สัญญาณว่าไม่ใช่ เปลี่ยนการตั้งค่าเหล่านี้ทั้งหมดแล้วยังเหมือนเดิม และปิงสูงหรือพุ่ง: ให้ดูฝั่งเครือข่าย ถ้าดีเลย์ฝั่ง PC สูงเพราะ V-Sync หรือคิวเฟรม น่าจะเป็น “V-Sync และคิวเรนเดอร์” วิธีตรวจ ตรวจที่สภาพแวดล้อมฝั่งผู้เล่น
รายละเอียดเพิ่มเติม ความหน่วงของเครือข่ายเห็นได้จากปิง แต่ดีเลย์นี้ไม่ปรากฏในปิง จึงเป็นจุดแรกที่ควรตรวจเมื่อมีการแจ้งว่า “ปิงต่ำแต่แลค” frame generation ทำให้ตัวเลข FPS บนจอสูงขึ้นราวสองเท่า แต่การสร้างเฟรมคั่นกลางต้องรอเฟรมจริงถัดไปก่อน เวลาที่อินพุตจะแสดงบนจอจึงยาวขึ้น (AMD ระบุว่าโดยการออกแบบแล้วดีเลย์จะเพิ่มขึ้น) อุปกรณ์ Bluetooth ใช้ย่าน 2.4 GHz เดียวกับ Wi-Fi ถ้าถูกรบกวน อินพุตอาจขาดหายหรือกระโดดได้ V-Sync และคิวเรนเดอร์ที่ทำให้ดีเลย์ใน PC เพิ่มขึ้น ดูได้ในรายการ “V-Sync และคิวเรนเดอร์”
แหล่งอ้างอิง 9 รายการ
L3 เครือข่ายในบ้าน
10 สาเหตุ · บทในฉบับหลัก
ID hn-wifi · ผู้รับผิดชอบหลัก ภายนอก (ภายนอก) · ร่วมกับ พัฒนาไคลเอนต์ (ทีมพัฒนาเกม)
ถ้าสัญญาณอ่อนหรือถูกรบกวน ช่วงไร้สายต้องส่งซ้ำหลายรอบ แพ็กเก็ตจึงมาถึงไม่สม่ำเสมอ
ทำไม คุณภาพสัญญาณแย่ลงเพราะผนัง, ระยะทาง, ไมโครเวฟ, Bluetooth และเราเตอร์ของเพื่อนบ้าน → ผลคือ ส่งในช่วงไร้สายไม่สำเร็จ → ส่งซ้ำหลายรอบ → บนหน้าจอ แพ็กเก็ตมาถึงไม่สม่ำเสมอ (จิตเตอร์) ตัวละครจึงหยุดแวบเป็นระยะ ถ้าหนักจะแพ็กเก็ตหายจนวาร์ป
อาการ กระตุก , วาร์ป , ดีดกลับ
ปัจจัย จิตเตอร์, แพ็กเก็ตหาย
ใครเจอ เราคนเดียว, คนในบ้านเดียวกัน
เกิดเมื่อไร สุ่มเป็นครั้งคราว, ตลอดเวลา
ผู้รับผิดชอบ ผู้รับผิดชอบหลัก ภายนอก (ภายนอก) · ร่วมกับ พัฒนาไคลเอนต์ (ทีมพัฒนาเกม)
งานฝั่งทีมพัฒนาเกม ปรับความยาว interpolation buffer อัตโนมัติตามสภาพเน็ต, ถ้าจิตเตอร์หรือแพ็กเก็ตหายสูงให้แสดงสถานะเครือข่ายบนจอ
งานฝั่งภายนอก แนะนำให้ผู้เล่นใช้สาย LAN, ใช้ 5 GHz หรือ 6 GHz, ย้ายตำแหน่งเราเตอร์
ตัวเลขที่ควรรู้ การส่งซ้ำหนึ่งครั้งเพิ่มเวลาราว 1–4 ms ถ้าสัญญาณอ่อน จะส่งซ้ำหลายรอบด้วยความเร็วต่ำ และต้องรอจนช่องสัญญาณว่างด้วย จึงอาจพุ่งครั้งละ 50–200 ms กับดักคือปิงเฉลี่ยดูปกติ
บนกราฟ พุ่งแบบสุ่มเป็นครั้งคราว · RTT ถึงเราเตอร์
จุดที่ต้องดู วัด ping /t ไปที่อยู่ของเราเตอร์ (default gateway จาก ipconfig) สักหลายนาที และดูความแรงสัญญาณกับช่องสัญญาณของเราเตอร์เราด้วย netsh wlan show networks mode=bssid แล้วเปลี่ยนเป็นสาย LAN ที่จุดเดิมเพื่อเทียบ สัญญาณว่าใช่ ตั้งแต่ปิงถึงเราเตอร์ก็พุ่งหลายสิบถึงหลายร้อย ms อย่างไม่สม่ำเสมอ มีแพ็กเก็ตหายบางครั้ง และสัญญาณอ่อน หายไปเมื่อใช้สาย LAN หรืออยู่ใกล้เราเตอร์ สัญญาณว่าไม่ใช่ ถึงเราเตอร์สม่ำเสมอแต่พุ่งเฉพาะช่วงที่เลยออกไป: ให้ดูเน็ตและช่วงของ ISP ถ้าพุ่งเป็นจังหวะเท่ากันอย่างเดียว น่าจะเป็น “การสแกน Wi-Fi เบื้องหลัง” วิธีตรวจ ตรวจที่สภาพแวดล้อมฝั่งผู้เล่น
รายละเอียดเพิ่มเติม ใน mesh Wi-Fi ถ้าเราเตอร์ (node) เชื่อมกันเองแบบไร้สาย (wireless backhaul) node ที่ทำหน้าที่ส่งต่อจะส่งไม่ได้ระหว่างที่กำลังรับ และต้องแบ่งโอกาสการส่งกับช่วงก่อนหน้าและถัดไปที่ใช้ช่องสัญญาณเดียวกัน เมื่อแออัด throughput จึงลดลงและดีเลย์เพิ่มขึ้นได้ ผลิตภัณฑ์ที่มีย่านไร้สายเฉพาะสำหรับ backhaul อาจเป็นน้อยกว่า และถ้าเชื่อม node ด้วยสาย (Ethernet) ช่วงนี้ก็จะไม่ผ่านไร้สายอีก อะแดปเตอร์ Powerline (PLC) ก็ใช้วิธีตรวจว่าตัวกลางว่างก่อนส่ง (CSMA/CA) เหมือน Wi-Fi และคุณภาพเปลี่ยนไปตลอดตามสัญญาณรบกวนจากเครื่องใช้ไฟฟ้าและการเปิดปิดเครื่องใช้ไฟฟ้า จึงเกิดการส่งซ้ำและจิตเตอร์ได้
กรณีจริง Square Enix 2021: FINAL FANTASY XIV แออัดช่วงเปิดตัวภาคเสริม และ error ในคิวล็อกอิน
แหล่งอ้างอิง 8 รายการ
ID hn-channel · ผู้รับผิดชอบหลัก ภายนอก (ภายนอก) · ร่วมกับ พัฒนาไคลเอนต์ (ทีมพัฒนาเกม)
ในที่ที่มีเราเตอร์หลายสิบตัวอย่างคอนโดหรืออพาร์ตเมนต์ ต้องแบ่งกันใช้ช่องสัญญาณเดียวกัน จึงต้องรอโอกาสส่ง
ทำไม เราเตอร์หลายสิบตัวใช้ช่องสัญญาณ 2.4 GHz เดียวกัน → ผลคือ จะส่งได้ต้องรอให้อุปกรณ์อื่นส่งเสร็จจนช่องสัญญาณว่าง → บนหน้าจอ ช่วงหัวค่ำที่คนกลับบ้าน จิตเตอร์ (ช่วงเวลาที่แพ็กเก็ตมาถึงไม่สม่ำเสมอ) เพิ่มขึ้นจนกระตุก
อาการ กระตุก , อินพุตดีเลย์
ปัจจัย จิตเตอร์, ความหน่วง
ใครเจอ คนในบ้านเดียวกัน
เกิดเมื่อไร ช่วงพีคหัวค่ำ
ผู้รับผิดชอบ ผู้รับผิดชอบหลัก ภายนอก (ภายนอก) · ร่วมกับ พัฒนาไคลเอนต์ (ทีมพัฒนาเกม)
งานฝั่งทีมพัฒนาเกม เมื่อจิตเตอร์เพิ่มขึ้น ให้ยืดความยาว interpolation buffer อัตโนมัติ
งานฝั่งภายนอก แนะนำให้ผู้เล่นใช้ 5 GHz หรือ 6 GHz, ช่องสัญญาณที่ไม่แออัด, สาย LAN
บนกราฟ สูงเฉพาะบางช่วงเวลา · RTT และจิตเตอร์ถึงเราเตอร์
จุดที่ต้องดู ดูช่องสัญญาณและความแรงสัญญาณของ Wi-Fi รอบตัวด้วย netsh wlan show networks mode=bssid แล้ววัดปิงถึงเราเตอร์ตอนหัวค่ำเทียบกับตอนกลางวัน สัญญาณว่าใช่ เห็นเราเตอร์รอบตัวจำนวนมากบนช่องสัญญาณ 2.4 GHz เดียวกัน และจิตเตอร์ถึงเราเตอร์สูงเฉพาะช่วงหัวค่ำ ย้ายไป 5 GHz/6 GHz หรือช่องสัญญาณที่ไม่แออัดแล้วลดลง สัญญาณว่าไม่ใช่ พุ่งโดยไม่เกี่ยวกับช่วงเวลา: น่าจะเป็น “Wi-Fi ถูกรบกวนหรือสัญญาณอ่อน” ถ้าถึงเราเตอร์ปกติแต่ตอนหัวค่ำช่วงที่เลยออกไปแย่ น่าจะเป็น “จุด peering แออัดช่วงพีค” วิธีตรวจ ตรวจที่สภาพแวดล้อมฝั่งผู้เล่น
แหล่งอ้างอิง 4 รายการ
ID hn-bufferbloat · ผู้รับผิดชอบหลัก ภายนอก (ภายนอก) · ร่วมกับ พัฒนาไคลเอนต์ (ทีมพัฒนาเกม)
เมื่อมีคนในบ้านอัปโหลดวิดีโอหรือดาวน์โหลดไฟล์ใหญ่ แพ็กเก็ตจะกองอยู่ในคิวของเราเตอร์ยาวเป็นหลายร้อย ms และแพ็กเก็ตเกมก็ต้องรอต่อท้าย
ทำไม คนในบ้านอัปโหลดวิดีโอหรือสำรองข้อมูลขึ้นคลาวด์, เราสตรีมออกอากาศ หรือดาวน์โหลดไฟล์ใหญ่ จนเน็ตเต็ม → ผลคือ เราเตอร์หรือโมเด็มเก็บแพ็กเก็ตที่ล้นไว้ในคิวขนาดใหญ่ → บนหน้าจอ แพ็กเก็ตเกมก็ต้องรอท้ายคิว ปิงพุ่งขึ้นไปหลายร้อย ms
อาการ อินพุตดีเลย์ , กรอเร็ว , วาร์ป
ปัจจัย ความหน่วง, จิตเตอร์
ใครเจอ คนในบ้านเดียวกัน, เราคนเดียว
เกิดเมื่อไร สุ่มเป็นครั้งคราว, ช่วงพีคหัวค่ำ
ผู้รับผิดชอบ ผู้รับผิดชอบหลัก ภายนอก (ภายนอก) · ร่วมกับ พัฒนาไคลเอนต์ (ทีมพัฒนาเกม)
งานฝั่งทีมพัฒนาเกม ถ้าปิงขึ้นไปหลายร้อย ms กะทันหัน ให้แสดงสถานะเครือข่ายบนจอ (บอกว่าอาจมีการรับส่งข้อมูลจำนวนมากบนเน็ตเดียวกัน)
งานฝั่งภายนอก แนะนำให้ผู้เล่นใช้เราเตอร์ที่มี SQM (fq_codel, CAKE) หรือ QoS, ตั้งความเร็ว SQM ไว้ที่ 90–95% ของความเร็วเน็ต (คิวจึงจะไปเกิดในเราเตอร์และได้ผล), จำกัดความเร็วอัปโหลด
ตัวเลขที่ควรรู้ เน็ตอัปโหลด 10 Mbps กับบัฟเฟอร์ 1 MB ทำให้คิวยาวได้ถึง 800 ms
บนกราฟ สูงตามจำนวนคนและโหลด · RTT, ปริมาณการใช้อัปโหลด/ดาวน์โหลดของเน็ต
จุดที่ต้องดู เปิดปิงทิ้งไว้แล้วใช้การทดสอบความเร็วทำให้เน็ตเต็ม หรือใช้เว็บทดสอบที่วัดดีเลย์ขณะมีโหลด (ตามคำแนะนำของ Bufferbloat.net) แล้วดูคู่กับปริมาณการใช้อัปโหลด/ดาวน์โหลดในหน้าจอของเราเตอร์ สัญญาณว่าใช่ ระหว่างที่อัปโหลดหรือดาวน์โหลดเต็มเน็ต ปิงขึ้นไปหลายร้อย ms และกลับมาเมื่อส่งเสร็จ (ถ้าดีเลย์ขณะมีโหลดเกิน 50 ms ให้สงสัย) เปิด SQM แล้วหายไป สัญญาณว่าไม่ใช่ เน็ตว่างแต่ปิงยังพุ่ง: น่าจะเป็น “Wi-Fi ถูกรบกวนหรือสัญญาณอ่อน” หรือ “คุณภาพสายเน็ตแย่” วิธีตรวจ ตรวจที่สภาพแวดล้อมฝั่งผู้เล่น
รายละเอียดเพิ่มเติม ฝั่งอัปโหลดตันง่ายเป็นพิเศษ เพราะเน็ตเคเบิลและเครือข่ายมือถือมักมีอัปโหลดแคบกว่าดาวน์โหลดมาก บ้านที่ใช้ไฟเบอร์ความเร็วเหลือเฟือ ช่วง Wi-Fi จะกลายเป็นคอขวดแทน และเกิดเรื่องเดียวกันในคิวไร้สายของเราเตอร์ แพ็กเก็ตเกมมีขนาดเล็กจึงแทบไม่ใช้แบนด์วิดท์ แต่ก็ต้องรอในคิวเหมือนกัน ถ้าตันเฉพาะทิศอัปโหลด อินพุตของเราจะช้าอย่างเดียว ส่วนการเคลื่อนไหวของคนอื่นปกติ บนมือถือ การสำรองรูปภาพหรืออัปเดตแอปในเครื่องเดียวกันจะทำให้คิวของโมเด็มในมือถือและเสาสัญญาณเต็มจนเกิดเรื่องเดียวกัน
แหล่งอ้างอิง 4 รายการ
ID hn-nat · ผู้รับผิดชอบหลัก พัฒนาไคลเอนต์ (ทีมพัฒนาเกม) · ร่วมกับ พัฒนาเซิร์ฟเวอร์ (ทีมพัฒนาเกม)
เราเตอร์จะลบการเชื่อมต่อที่ idle (ไม่มีแพ็กเก็ตวิ่งมาสักพัก) ออกจากตาราง NAT นี่คือสาเหตุที่พบบ่อยของอาการหลุดตอนที่เพิ่งขยับหลังจากอยู่เฉย ๆ
ทำไม เราเตอร์บันทึกการเชื่อมต่อ “อุปกรณ์ข้างใน ↔ เซิร์ฟเวอร์ข้างนอก” ไว้ในตาราง NAT (ตารางแปลงที่อยู่) → ผลคือ ถ้าไม่มีแพ็กเก็ตสักพัก จะลบออกจากตาราง (UDP มักอยู่ที่ 30–120 วินาที) → บนหน้าจอ แพ็กเก็ตจากเซิร์ฟเวอร์เข้ามาในบ้านไม่ได้ จึงหลุด
อาการ หลุด
ปัจจัย แพ็กเก็ตหาย
ใครเจอ เราคนเดียว, คนในบ้านเดียวกัน
เกิดเมื่อไร หลังอยู่เฉย ๆ สักพัก
ผู้รับผิดชอบ ผู้รับผิดชอบหลัก พัฒนาไคลเอนต์ (ทีมพัฒนาเกม) · ร่วมกับ พัฒนาเซิร์ฟเวอร์ (ทีมพัฒนาเกม)
งานฝั่งทีมพัฒนาเกม ไคลเอนต์: ส่ง heartbeat ทุกช่วงไม่เกินครึ่งหนึ่งของ idle timeout ที่สั้นที่สุด (UDP mapping จะต่ออายุได้แน่นอนก็ต่อเมื่อมีแพ็กเก็ตขาออกจากในบ้าน ไคลเอนต์จึงต้องเป็นฝ่ายส่ง), เชื่อมต่อใหม่อัตโนมัติเมื่อหลุด เซิร์ฟเวอร์: ตอบ heartbeat และถ้าไม่ได้รับนานเกินกำหนดให้ปิดการเชื่อมต่อก่อน, ถ้า mapping ถูกลบจนที่อยู่และพอร์ตภายนอกเปลี่ยน ให้ยืนยันว่าเป็นผู้เล่นคนเดิมด้วย session token (รหัสยืนยันที่ได้ตอนเชื่อมต่อ) แล้วรับช่วงต่อ
บนกราฟ การเชื่อมต่อหลุดพร้อมกัน · จำนวนครั้งที่หลุด (heartbeat timeout), เวลา idle ก่อนหลุด
จุดที่ต้องดู รวบรวมสาเหตุการหลุดที่เซิร์ฟเวอร์บันทึกไว้ และเวลาที่ผ่านไปตั้งแต่แพ็กเก็ตสุดท้ายบนการเชื่อมต่อนั้นจนหลุด (เวลา idle) แล้วดูเป็นการกระจาย สำหรับการทดสอบ ให้ยืดช่วงห่างของแพ็กเก็ต UDP เป็น 30, 60 และ 120 วินาที แล้ววัดว่าช่วงห่างเท่าไรที่การตอบกลับขาดไป สัญญาณว่าใช่ หลุดเฉพาะการเชื่อมต่อที่อยู่เฉย ๆ และเวลา idle กระจุกอยู่ถัดจากค่าหนึ่ง เช่น 30–120 วินาที ถ้าตั้งช่วงห่าง heartbeat ให้สั้นกว่านั้นแล้วหายไป สัญญาณว่าไม่ใช่ หลุดแม้ระหว่างกำลังขยับ: ให้ดูเน็ตและเส้นทาง ถ้ากระจุกที่ค่าสั้น ๆ เฉพาะบางค่ายมือถือ น่าจะเป็น “IP ที่ ISP ให้ใช้ร่วมกัน (CGNAT)” วิธีตรวจ ต้องมี log หรือเมตริกจากเซิร์ฟเวอร์/ไคลเอนต์เกม
แหล่งอ้างอิง 3 รายการ
ID hn-router · ผู้รับผิดชอบหลัก ภายนอก (ภายนอก)
เมื่ออุปกรณ์หลายสิบเครื่องและการเชื่อมต่อหลายพันรายการมารวมที่เราเตอร์ราคาถูก ตัวเราเตอร์เองจะประมวลผลไม่ไหว
ทำไม อุปกรณ์หลายสิบเครื่อง และ P2P/ทอร์เรนต์เปิดการเชื่อมต่อหลายพันรายการ → ผลคือ CPU และตารางเซสชันของเราเตอร์เต็ม → บนหน้าจอ ประมวลผลแพ็กเก็ตช้าหรือแพ็กเก็ตหาย, เชื่อมต่อใหม่ไม่สำเร็จ
อาการ กระตุก , เข้าเกมไม่ได้/โหลดไม่จบ , หลุด
ปัจจัย แพ็กเก็ตหาย, จิตเตอร์
ใครเจอ คนในบ้านเดียวกัน
เกิดเมื่อไร ยิ่งเปิดไว้นานยิ่งเป็น, สุ่มเป็นครั้งคราว
ผู้รับผิดชอบ ผู้รับผิดชอบหลัก ภายนอก (ภายนอก)
งานฝั่งภายนอก แนะนำให้ผู้เล่นรีบูตเราเตอร์ (แก้ชั่วคราว), เปลี่ยนเราเตอร์, ปิดโปรแกรมที่เปิดการเชื่อมต่อจำนวนมาก (P2P, ทอร์เรนต์)
บนกราฟ ชนเพดานแล้วแบนราบ · CPU และจำนวนการเชื่อมต่อของเราเตอร์, RTT ถึงเราเตอร์
จุดที่ต้องดู ดูอัตราการใช้ CPU, จำนวนการเชื่อมต่อ (เซสชัน) และจำนวนอุปกรณ์ที่เชื่อมอยู่ในหน้าจัดการเราเตอร์ (ถ้ารุ่นนั้นรองรับ) แล้วเทียบปิงถึงตัวเราเตอร์ก่อนและหลังรีบูต สัญญาณว่าใช่ เมื่อการเชื่อมต่อมาก ปิงถึงเราเตอร์ก็เริ่มพุ่งหรือแพ็กเก็ตหาย และเชื่อมต่อใหม่ไม่สำเร็จ รีบูตแล้วดีอยู่พักหนึ่งก่อนกลับมาแย่อีก สัญญาณว่าไม่ใช่ ถึงเราเตอร์ปกติแต่ช่วงที่เลยออกไปแย่: ให้ดูเน็ตและช่วงของ ISP วิธีตรวจ ตรวจที่สภาพแวดล้อมฝั่งผู้เล่น
แหล่งอ้างอิง 2 รายการ
ID hn-handover · ผู้รับผิดชอบหลัก ภายนอก (ภายนอก) · ร่วมกับ พัฒนาไคลเอนต์ (ทีมพัฒนาเกม), พัฒนาเซิร์ฟเวอร์ (ทีมพัฒนาเกม)
เมื่อเดินทางด้วยรถเมล์หรือรถไฟใต้ดิน การสื่อสารจะขาดช่วงระหว่างที่เปลี่ยนเสาสัญญาณ
ทำไม เสาสัญญาณที่เชื่อมต่อเปลี่ยนไประหว่างเดินทาง → ผลคือ ปกติขาดไปหลายสิบ ms แต่ถ้าสัญญาณแย่จนสลับไม่สำเร็จ อาจขาดไปหลายร้อย ms ถึงหลายวินาที → บนหน้าจอ ค้างแล้ววาร์ป ถ้านานจะหลุด
อาการ ค้าง , วาร์ป , หลุด
ปัจจัย แพ็กเก็ตหาย
ใครเจอ เราคนเดียว
เกิดเมื่อไร ระหว่างเดินทาง/ย้ายแมพ
ผู้รับผิดชอบ ผู้รับผิดชอบหลัก ภายนอก (ภายนอก) · ร่วมกับ พัฒนาไคลเอนต์ (ทีมพัฒนาเกม), พัฒนาเซิร์ฟเวอร์ (ทีมพัฒนาเกม)
งานฝั่งทีมพัฒนาเกม ไคลเอนต์: ตั้งไทม์เอาต์ให้ทนการขาดช่วงสั้น ๆ ได้, เชื่อมต่อใหม่ให้เร็ว เซิร์ฟเวอร์: ตั้งไทม์เอาต์ที่ไม่เตะออกทันทีแม้ขาดไปไม่กี่วินาที, เมื่อเชื่อมต่อใหม่ให้ต่อเข้าเซสชันเดิม
งานฝั่งภายนอก แจ้งผู้เล่นว่าการหลุดระหว่างเดินทาง (รถเมล์, รถไฟใต้ดิน) เกิดจากการสลับเสาสัญญาณ
บนกราฟ ขาดช่วงแล้วมารวดเดียว · จำนวนแพ็กเก็ตที่ได้รับ, RTT
จุดที่ต้องดู ตรวจว่าตอนที่แจ้งว่าหลุดกำลังเดินทางอยู่หรือไม่ (รถเมล์, รถไฟใต้ดิน) และดูเวลาที่การรับข้อมูลขาดช่วงใน log ของไคลเอนต์คู่กับการเปลี่ยนชนิดเครือข่ายและสัญญาณ สัญญาณว่าใช่ เฉพาะระหว่างเดินทาง การรับข้อมูลว่างไปหลายร้อย ms ถึงหลายวินาทีแล้วมารวดเดียว และทำซ้ำไม่ได้ตอนอยู่กับที่ สัญญาณว่าไม่ใช่ อยู่กับที่ก็เป็นเหมือนกัน: น่าจะเป็น “สัญญาณมือถืออ่อนหรืออยู่ในจุดอับสัญญาณ” หรือ “สลับ 5G↔LTE บ่อย (บริเวณขอบพื้นที่ 5G)” วิธีตรวจ ตรวจที่สภาพแวดล้อมฝั่งผู้เล่น
แหล่งอ้างอิง 2 รายการ
ID hn-rrc · ผู้รับผิดชอบหลัก พัฒนาไคลเอนต์ (ทีมพัฒนาเกม)
ถ้าไม่มีการสื่อสารสักพัก มือถือจะลดการเชื่อมต่อวิทยุลงเป็นสถานะพลังงานต่ำ และเมื่อมีแพ็กเก็ตถัดไปต้องยกกลับขึ้นมาใหม่ จึงช้าลง
ทำไม ไม่มีการสื่อสารสักพัก มือถือจึงสลับการเชื่อมต่อวิทยุเป็นสถานะประหยัดพลังงาน → ผลคือ จะส่งแพ็กเก็ตถัดไปได้ต้องยกการเชื่อมต่อกลับขึ้นมาก่อน → บนหน้าจอ เฉพาะแอ็กชันแรกหลังอยู่เฉย ๆ ช้าเป็นพิเศษ
อาการ อินพุตดีเลย์
ปัจจัย ความหน่วง
ใครเจอ เราคนเดียว
เกิดเมื่อไร หลังอยู่เฉย ๆ สักพัก
ผู้รับผิดชอบ ผู้รับผิดชอบหลัก พัฒนาไคลเอนต์ (ทีมพัฒนาเกม)
งานฝั่งทีมพัฒนาเกม ส่งข้อมูลเบา ๆ เป็นระยะเพื่อคงสถานะ active (แลกกับแบตเตอรี่)
ตัวเลขที่ควรรู้ ปกติ LTE จะลงไปสถานะประหยัดพลังงานเมื่อไม่มีการสื่อสารราว 10 วินาที และใช้เวลาหลายสิบถึงหลายร้อย ms กว่าจะยกกลับขึ้นมา (ตัวอย่างที่วัดจริง: ราว 0.3–0.6 วินาที) ส่วน 3G นานกว่า 1 วินาที
บนกราฟ สูงเฉพาะบางกลุ่ม · RTT ของคำขอแรกหลัง idle (มือถือ)
จุดที่ต้องดู แยก RTT ในเกมตามช่วงห่างจากการสื่อสารครั้งก่อน เทียบ RTT ของแพ็กเก็ตแรกที่ส่งหลังพักเกิน 10 วินาทีบนมือถือ กับแพ็กเก็ตที่ส่งต่อเนื่องกัน สัญญาณว่าใช่ บนเครือข่ายมือถือ เฉพาะแพ็กเก็ตแรกหลังพักช้าไปหลายร้อย ms ส่วนแพ็กเก็ตที่ส่งตามติดกันปกติ บน Wi-Fi ไม่มีความต่าง สัญญาณว่าไม่ใช่ ส่งต่อเนื่องก็ยังช้า: ให้ดูสัญญาณ, เน็ต และเส้นทาง วิธีตรวจ ต้องมี log หรือเมตริกจากเซิร์ฟเวอร์/ไคลเอนต์เกม
แหล่งอ้างอิง 3 รายการ
ID hn-weak-cell · ผู้รับผิดชอบหลัก ภายนอก (ภายนอก) · ร่วมกับ พัฒนาไคลเอนต์ (ทีมพัฒนาเกม)
ในลิฟต์, ชั้นใต้ดิน หรือด้านในอาคาร การส่งซ้ำจะเพิ่มขึ้น ความเร็วลดลง และสุดท้ายก็หลุด
ทำไม เคลื่อนที่ไปยังจุดที่สัญญาณอ่อน → ผลคือ การส่งซ้ำทางวิทยุเพิ่มขึ้น, ความเร็วลดลง, การเชื่อมต่อขาดชั่วขณะ → บนหน้าจอ จิตเตอร์และแพ็กเก็ตหายทำให้กระตุกหรือวาร์ป สุดท้ายก็หลุด
อาการ กระตุก , วาร์ป , หลุด
ปัจจัย จิตเตอร์, แพ็กเก็ตหาย
ใครเจอ เราคนเดียว
เกิดเมื่อไร ระหว่างเดินทาง/ย้ายแมพ
ผู้รับผิดชอบ ผู้รับผิดชอบหลัก ภายนอก (ภายนอก) · ร่วมกับ พัฒนาไคลเอนต์ (ทีมพัฒนาเกม)
งานฝั่งทีมพัฒนาเกม ปรับปรุงขั้นตอนการเชื่อมต่อใหม่, แสดงคุณภาพเครือข่าย
งานฝั่งภายนอก แจ้งผู้เล่นว่าเป็นปัญหาที่เกิดในจุดที่สัญญาณอ่อน (ลิฟต์, ชั้นใต้ดิน, ด้านในอาคาร)
บนกราฟ สูงเฉพาะบางกลุ่ม · RTT และแพ็กเก็ตหาย (แยกตามผู้เล่นมือถือ)
จุดที่ต้องดู ตรวจสถานที่ตอนที่แจ้งว่าหลุด (ลิฟต์, ชั้นใต้ดิน, ในอาคาร) และขีดสัญญาณบนมือถือ แล้วลองทำแบบเดิมซ้ำในจุดที่สัญญาณดีเพื่อเทียบ สัญญาณว่าใช่ RTT และแพ็กเก็ตหายเพิ่มขึ้นจนหลุดเฉพาะในจุดที่สัญญาณอ่อน และหายไปเมื่อย้ายไปที่สัญญาณดี สัญญาณว่าไม่ใช่ สัญญาณดีแต่ยังเป็นเหมือนกัน: ให้ดูช่วงของ ISP หรือฝั่งเซิร์ฟเวอร์ วิธีตรวจ ตรวจที่สภาพแวดล้อมฝั่งผู้เล่น
แหล่งอ้างอิง 1 รายการ
ID hn-5g-flip · ผู้รับผิดชอบหลัก ภายนอก (ภายนอก) · ร่วมกับ พัฒนาไคลเอนต์ (ทีมพัฒนาเกม)
ในอาคารที่สัญญาณ 5G อ่อน หรือบริเวณขอบพื้นที่ 5G มือถือจะสลับไปมาระหว่าง 5G กับ LTE บ่อย และทุกครั้งที่สลับ ปิงจะพุ่งหรือการสื่อสารขาดไปครู่หนึ่ง
ทำไม อยู่ในจุดที่สัญญาณ 5G ไม่สม่ำเสมอ (ในอาคาร, ขอบพื้นที่ 5G) → ผลคือ มือถือสลับระหว่าง 5G กับ LTE อยู่เรื่อย ๆ และทุกครั้งเกิดช่องว่างสั้น ๆ → บนหน้าจอ แม้อยู่เฉย ๆ ปิงก็พุ่งแบบไม่มีแบบแผน บางครั้งค้างหรือวาร์ป
อาการ กระตุก , วาร์ป , ค้าง
ปัจจัย จิตเตอร์, แพ็กเก็ตหาย
ใครเจอ เราคนเดียว
เกิดเมื่อไร สุ่มเป็นครั้งคราว, ระหว่างเดินทาง/ย้ายแมพ
ผู้รับผิดชอบ ผู้รับผิดชอบหลัก ภายนอก (ภายนอก) · ร่วมกับ พัฒนาไคลเอนต์ (ทีมพัฒนาเกม)
งานฝั่งทีมพัฒนาเกม เมื่อจิตเตอร์เพิ่มขึ้น ให้ยืดความยาว interpolation buffer อัตโนมัติ, บันทึกการเปลี่ยนชนิดเครือข่าย (5G/LTE) ไว้ใน log ตอนที่เกิดแลคด้วยเพื่อแยกสาเหตุ
งานฝั่งภายนอก แนะนำให้ผู้เล่นลองเปลี่ยนเป็นโหมดใช้ LTE เป็นหลักในการตั้งค่าแล้วเทียบ, แนะนำให้ใช้ Wi-Fi
ตัวเลขที่ควรรู้ สลับหนึ่งครั้งใช้เวลาหลายสิบถึงหลายร้อย ms 5G ในเกาหลีส่วนใหญ่เป็นแบบที่ใช้ร่วมกับ LTE (NSA) ฝั่ง 5G จึงเชื่อมต่อแล้วขาดสลับไปมาได้ง่าย
บนกราฟ พุ่งแบบสุ่มเป็นครั้งคราว · RTT, การเปลี่ยนชนิดเครือข่าย (5G/LTE)
จุดที่ต้องดู ตั้งมือถือเป็นโหมดใช้ LTE เป็นหลักแล้วเทียบที่จุดเดิม ถ้าไคลเอนต์บันทึกการเปลี่ยนสัญลักษณ์เครือข่ายจาก TelephonyDisplayInfo ของ Android (OVERRIDE_NETWORK_TYPE_NR_NSA ฯลฯ) คู่กับ RTT จะยืนยันได้ชัดขึ้น สัญญาณว่าใช่ เวลาที่ RTT พุ่งตรงกับเวลาที่สัญลักษณ์ 5G↔LTE เปลี่ยน และในโหมดใช้ LTE เป็นหลักไม่พุ่งอีก สัญญาณว่าไม่ใช่ สัญลักษณ์เครือข่ายไม่เปลี่ยนแต่ยังพุ่ง: น่าจะเป็น “สัญญาณมือถืออ่อนหรืออยู่ในจุดอับสัญญาณ” หรือฝั่งเน็ต วิธีตรวจ ตรวจที่สภาพแวดล้อมฝั่งผู้เล่น
แหล่งอ้างอิง 3 รายการ
ID hn-captive · ผู้รับผิดชอบหลัก ภายนอก (ภายนอก) · ร่วมกับ พัฒนาไคลเอนต์ (ทีมพัฒนาเกม), พัฒนาเซิร์ฟเวอร์ (ทีมพัฒนาเกม)
หน้าล็อกอิน Wi-Fi ของร้านกาแฟหรือไฟร์วอลล์ของบริษัทบล็อกการเชื่อมต่อของเกม
ทำไม ยังไม่ได้ยืนยันตัวตนในหน้าล็อกอิน หรือไฟร์วอลล์บล็อกพอร์ตเกมหรือ UDP → ผลคือ ความพยายามเชื่อมต่อถูกบล็อกทั้งหมด หรือผ่านได้แค่บางส่วน → บนหน้าจอ เข้าเกมไม่ได้ หรือล็อกอินได้แต่เข้าไปในเกมไม่สำเร็จ
อาการ เข้าเกมไม่ได้/โหลดไม่จบ
ปัจจัย แพ็กเก็ตหาย
ใครเจอ เราคนเดียว
เกิดเมื่อไร หลังล็อกอิน/หลังปิดปรับปรุง
ผู้รับผิดชอบ ผู้รับผิดชอบหลัก ภายนอก (ภายนอก) · ร่วมกับ พัฒนาไคลเอนต์ (ทีมพัฒนาเกม), พัฒนาเซิร์ฟเวอร์ (ทีมพัฒนาเกม)
งานฝั่งทีมพัฒนาเกม ไคลเอนต์: แสดงเหตุผลเมื่อถูกบล็อก (ยังไม่ได้ยืนยันตัวตนในหน้าล็อกอิน, UDP ถูกบล็อก ฯลฯ), ถ้า UDP ถูกบล็อกให้สลับไปใช้เส้นทางสำรองอัตโนมัติ เซิร์ฟเวอร์: มีเส้นทางสำรอง เช่น TCP 443
งานฝั่งภายนอก แนะนำผู้เล่นว่า Wi-Fi สาธารณะต้องยืนยันตัวตนในหน้าล็อกอินก่อน และในเครือข่ายที่ถูกบล็อกอย่างเครือข่ายบริษัทให้ใช้เครือข่ายอื่น
บนกราฟ สูงเฉพาะบางกลุ่ม · จำนวนการเชื่อมต่อล้มเหลว (แยกตามเครือข่าย)
จุดที่ต้องดู ให้ผู้เล่นที่เชื่อมต่อไม่สำเร็จลองเปลี่ยนไปใช้เครือข่ายอื่น เช่น เน็ตมือถือ แล้วดูใน log การเชื่อมต่อของเซิร์ฟเวอร์ว่าแพ็กเก็ต UDP แรกมาถึงหรือไม่ และเชื่อมต่อผ่านเส้นทางสำรอง TCP 443 ได้หรือไม่ สัญญาณว่าใช่ ล้มเหลวเฉพาะบาง Wi-Fi (ร้านกาแฟ, บริษัท) และเชื่อมต่อได้ทันทีบนเครือข่ายอื่น ยังไม่ได้ยืนยันตัวตนในหน้าล็อกอิน หรือมีแต่ UDP ที่มาไม่ถึงเซิร์ฟเวอร์ สัญญาณว่าไม่ใช่ ล้มเหลวทุกเครือข่าย: ให้ดูบัญชี, เซิร์ฟเวอร์ หรือ “DNS ขัดข้อง/ช้า” ถ้าล้มเหลวทั้งประเทศหรือทั้ง ISP น่าจะเป็น “การจำกัด UDP และตรวจแพ็กเก็ตระดับประเทศหรือ ISP” วิธีตรวจ ตรวจที่สภาพแวดล้อมฝั่งผู้เล่น
แหล่งอ้างอิง 2 รายการ
L4 เส้นทางอินเทอร์เน็ต
14 สาเหตุ · บทในฉบับหลัก
ID isp-distance · ผู้รับผิดชอบหลัก อินฟราเซิร์ฟเวอร์ (ทีมอินฟรา) · ร่วมกับ อินฟราเครือข่าย (ทีมอินฟรา), พัฒนาเซิร์ฟเวอร์ (ทีมพัฒนาเกม)
แม้แต่แสงในสายไฟเบอร์ก็เดินทางได้แค่ประมาณ 200,000 กิโลเมตรใน 1 วินาที เซิร์ฟเวอร์ที่อยู่ไกลจะดีแค่ไหนก็ยังช้า
ทำไม เซิร์ฟเวอร์อยู่ไกล (เซิร์ฟเวอร์ต่างประเทศ, อีกทวีป) → ผลคือ เวลาไปกลับเพิ่มขึ้นตามระยะทาง (อย่างน้อย 10 ms ต่อ 1,000 กิโลเมตร) → บนหน้าจอ ทุกการกระทำมีอินพุตดีเลย์คงที่ และเสียเปรียบในการตัดสินผล
อาการ อินพุตดีเลย์
ปัจจัย ความหน่วง
ใครเจอ บางพื้นที่/บาง ISP
เกิดเมื่อไร ตลอดเวลา
ผู้รับผิดชอบ ผู้รับผิดชอบหลัก อินฟราเซิร์ฟเวอร์ (ทีมอินฟรา) · ร่วมกับ อินฟราเครือข่าย (ทีมอินฟรา), พัฒนาเซิร์ฟเวอร์ (ทีมพัฒนาเกม)
งานฝั่งทีมพัฒนาเกม แก้กฎฟิสิกส์ด้วยโค้ดไม่ได้ จึงทำได้แค่บรรเทา, ทำระบบเลือกภูมิภาคให้ผู้เล่นเลือกเซิร์ฟเวอร์ที่ใกล้, ใช้ lag compensation (การย้อนเวลา) ลดความเสียเปรียบในการตัดสินผล
งานฝั่งทีมอินฟรา เครื่องเซิร์ฟเวอร์/OS: ตั้งเซิร์ฟเวอร์แยกตามภูมิภาคในพื้นที่ที่มีผู้เล่นมาก เครือข่าย: ตั้งจุดเชื่อมต่อ (edge) ไว้ใกล้ผู้เล่น, เลือกวงจรและเส้นทางที่อ้อมน้อย
ตัวเลขที่ควรรู้ โซล–โตเกียว ประมาณ 30 ms, โซล–สิงคโปร์ ประมาณ 75 ms, โซล–สหรัฐฯ ฝั่งตะวันตก ประมาณ 140 ms, โซล–ยุโรป ประมาณ 230–270 ms (ไปกลับ ตามเส้นทางจริง) เส้นทางไปยุโรปแทบไม่มีเคเบิลใหญ่ที่วิ่งตามแนวเส้นตรง จึงต้องอ้อมผ่านเอเชียตะวันออกเฉียงใต้และสุเอซ หรืออ้อมผ่านสหรัฐฯ ทำให้นานกว่าที่ระยะทางบอกไว้มาก
บนกราฟ สูงตลอดตั้งแต่แรก · RTT (แยกตามประเทศ/ภูมิภาค)
จุดที่ต้องดู ระบุประเทศจาก IP ที่เชื่อมต่อแล้วดูการกระจายของ RTT แยกตามประเทศ และวัดด้วย ping กับ traceroute ไปยังเซิร์ฟเวอร์จาก VM ในคลาวด์รีเจียนของพื้นที่นั้น หรือจาก probe ของ RIPE Atlas (เลือกตามประเทศหรือ ASN) สัญญาณว่าใช่ RTT ของประเทศที่อยู่ไกลสูงตลอดไม่ว่าช่วงเวลาไหน และใกล้กับความหน่วงขั้นต่ำที่คำนวณจากระยะทาง (ไปกลับ 10 ms ต่อ 1,000 กิโลเมตร) และสถิติความหน่วงที่เปิดเผยต่อสาธารณะ สัญญาณว่าไม่ใช่ ถ้าสูงกว่าที่ระยะทางอธิบายได้มาก น่าจะเป็น “เส้นทางวิ่งอ้อม” ถ้าสูงเฉพาะหัวค่ำ น่าจะเป็น “จุด peering แออัดช่วงพีค” วิธีตรวจ ใช้เครื่องมือฝั่งอินฟรา (ไม่ต้องใช้โค้ดเกม)
กรณีจริง Riot Games 2015: ทราฟฟิก League of Legends ที่วิ่งอ้อมไปไกล และ Riot Direct
แหล่งอ้างอิง 4 รายการ
ID isp-satellite · ผู้รับผิดชอบหลัก ภายนอก (ภายนอก) · ร่วมกับ พัฒนาไคลเอนต์ (ทีมพัฒนาเกม), พัฒนาเซิร์ฟเวอร์ (ทีมพัฒนาเกม)
อินเทอร์เน็ตดาวเทียมต้องส่งสัญญาณขึ้นไปในอวกาศแล้วกลับลงมา ดาวเทียมวงโคจรค้างฟ้าแค่ช่วงขึ้นลงนี้ก็ใช้เวลาไปกลับเกิน 0.5 วินาทีแล้ว ส่วนดาวเทียมวงโคจรต่ำอย่าง Starlink ปกติเร็ว แต่ตอนที่ระบบจัดเส้นทางใหม่ ความหน่วงจะแกว่งและบางครั้งขาดไปชั่วครู่
ทำไม เชื่อมต่อจากบ้าน เรือ หรือเครื่องบิน ผ่านอินเทอร์เน็ตดาวเทียมวงโคจรค้างฟ้าหรือวงโคจรต่ำ หรือผ่าน Wi-Fi บนเครื่องบินที่ใช้ดาวเทียม → ผลคือ วงโคจรค้างฟ้าอยู่สูงประมาณ 36,000 กิโลเมตร ระยะทางขึ้นลงจึงยาวอยู่แล้ว ส่วนวงโคจรต่ำจัดเส้นทางระหว่างอุปกรณ์ผู้ใช้ ดาวเทียม และสถานีภาคพื้นดินใหม่เป็นรอบสั้น ๆ และตอนนั้นจะเกิดความหน่วงหรือแพ็กเก็ตหายชั่วครู่ → บนหน้าจอ วงโคจรค้างฟ้ามีอินพุตดีเลย์มากในทุกการกระทำ ส่วนวงโคจรต่ำปกติดี แต่กระตุกหรือวาร์ปเป็นช่วงห่างเท่า ๆ กัน
อาการ อินพุตดีเลย์ , กระตุก , วาร์ป
ปัจจัย ความหน่วง, จิตเตอร์, แพ็กเก็ตหาย
ใครเจอ เราคนเดียว, คนในบ้านเดียวกัน, บางพื้นที่/บาง ISP
เกิดเมื่อไร ตลอดเวลา, เป็นรอบสม่ำเสมอ
ผู้รับผิดชอบ ผู้รับผิดชอบหลัก ภายนอก (ภายนอก) · ร่วมกับ พัฒนาไคลเอนต์ (ทีมพัฒนาเกม), พัฒนาเซิร์ฟเวอร์ (ทีมพัฒนาเกม)
งานฝั่งทีมพัฒนาเกม ไคลเอนต์: ขยาย interpolation buffer อัตโนมัติตามจิตเตอร์, ส่งอินพุตซ้ำเพื่อให้ทนแพ็กเก็ตหายช่วงสั้น, แสดงคุณภาพการเชื่อมต่อ เซิร์ฟเวอร์: คำนึงถึงความหน่วงของเน็ตดาวเทียมเมื่อกำหนดช่วงเวลาตัดสินและเพดานของ lag compensation, ตั้งไทม์เอาต์ที่ไม่ตัดผู้เล่นออกทันทีเมื่อขาดช่วงราว 1 วินาที
งานฝั่งภายนอก แนะนำผู้เล่นว่าอินเทอร์เน็ตดาวเทียมอาจมีความหน่วงสูงหรือพุ่งเป็นรอบ, แนะนำให้ใช้เน็ตแบบมีสายภาคพื้นดินกับคอนเทนต์แข่งขันถ้าทำได้
ตัวเลขที่ควรรู้ วงโคจรค้างฟ้า (สูง 36,000 กิโลเมตร) สัญญาณใช้เวลาผ่านอวกาศทางเดียว 260 ms ไปกลับจึงเกิน 520 ms (ITU-T G.114) ส่วน Starlink ซึ่งเป็นวงโคจรต่ำ ตามข้อมูลทางการ (ค่าเฉลี่ยทุก 15 วินาที) มีค่ามัธยฐานช่วงพีคในสหรัฐฯ 33 ms และแม้ 1% ที่แย่ที่สุด (p99) ก็ต่ำกว่า 65 ms (ปี 2024) งานวิจัยที่วัดจริงพบว่าความหน่วงเปลี่ยนทุกครั้งที่จัดเส้นทางใหม่ทุก 15 วินาที และมีช่วงขาดสั้น ๆ ไม่ถึง 1 วินาที การวัดอินเทอร์เน็ตบนเครื่องบินในปี 2018 พบว่าแบบดาวเทียมมีเวลาไปกลับเฉลี่ย 750 ms
บนกราฟ สูงเฉพาะบางกลุ่ม · RTT/จิตเตอร์ (แยกตาม ASN ของผู้ให้บริการอินเทอร์เน็ตดาวเทียม)
จุดที่ต้องดู ดูว่า ASN ของ IP ที่เชื่อมต่อเป็นผู้ให้บริการอินเทอร์เน็ตดาวเทียมหรือไม่ แล้วพล็อตการกระจายและอนุกรมเวลาของ RTT ของผู้เล่นค่ายนั้นแยกไว้ วัด ping ต่อเนื่องหลายนาทีจาก probe ของ RIPE Atlas ใน ASN นั้นไปยังเซิร์ฟเวอร์ หรือให้ผู้เล่นเปิด ping ทิ้งไว้แล้ววัดระยะห่างระหว่างครั้งที่พุ่ง สัญญาณว่าใช่ ผู้ให้บริการวงโคจรค้างฟ้ามี RTT เกิน 500 ms ตลอด ส่วนผู้ให้บริการวงโคจรต่ำปกติอยู่ที่หลายสิบ ms แต่ RTT เปลี่ยนหรือขาดสั้น ๆ ทุกประมาณ 15 วินาที สัญญาณว่าไม่ใช่ ถ้าไม่ใช่ผู้ให้บริการดาวเทียมแต่ RTT สูงตลอด น่าจะเป็น “ความหน่วงในการแพร่สัญญาณ (ระยะทางจริง)” หรือ “เส้นทางวิ่งอ้อม” ถ้าพุ่งแบบไม่เป็นจังหวะ ให้ดูสัญญาณ Wi-Fi หรือมือถือ วิธีตรวจ ใช้เครื่องมือฝั่งอินฟรา (ไม่ต้องใช้โค้ดเกม)
รายละเอียดเพิ่มเติม ดาวเทียมวงโคจรต่ำอยู่ไม่ไกล (Starlink ช่วงเดียว 1.8–3.6 ms) ความหน่วงตามปกติจึงอาจใกล้เคียงกับเน็ตภาคพื้นดิน แต่ถ้าจุดที่สถานีภาคพื้นดินออกสู่อินเทอร์เน็ต (PoP) อยู่ไกลจากเซิร์ฟเวอร์เกม เส้นทางก็ยาวขึ้นตามนั้น และถ้าอ้อมผ่านลิงก์เลเซอร์ระหว่างดาวเทียม ความหน่วงก็เพิ่มอีก งานวิจัยที่วัดจริงมองว่าการแกว่งทุก 15 วินาทีมาจากการจัดเส้นทางใหม่ที่เกิดพร้อมกันทั่วโลกในเวลาเดียวกัน และไม่เกี่ยวกับการสลับดาวเทียม Wi-Fi บนเครื่องบินมีความหน่วงต่างกันมากตามวิธีเชื่อมต่อ (ดาวเทียมหรือสถานีฐานภาคพื้นดิน) ถ้าเป็นแบบที่ใช้ดาวเทียมวงโคจรค้างฟ้า ก็จะมีเวลาไปกลับยาวแบบข้างต้น
แหล่งอ้างอิง 5 รายการ ITU-T G.114: One-way transmission time ITU ค่าที่ใช้วางแผนสำหรับความหน่วงทางเดียวในช่วงดาวเทียม: ความสูง 400 กิโลเมตร 12 ms, 14,000 กิโลเมตร 110 ms, 36,000 กิโลเมตร (วงโคจรค้างฟ้า) 260 ms Improving Starlink’s Latency Starlink ค่ามัธยฐานช่วงพีคในสหรัฐฯ 48.5 ms→33 ms, 1% ที่ช้าที่สุด (p99) จากเกิน 150 ms→ต่ำกว่า 65 ms (ปี 2024), สัญญาณเดินทางช่วงดาวเทียมหนึ่งช่วง 1.8–3.6 ms, ถ้าอ้อมผ่านลิงก์เลเซอร์ความหน่วงจะเพิ่ม และระยะจากสถานีภาคพื้นดินถึงจุดเชื่อมต่ออินเทอร์เน็ต (PoP) ก็เป็นปัจจัยของความหน่วงด้วย A Multifaceted Look at Starlink Performance (WWW 2024) ACM Starlink จัดเส้นทางใหม่พร้อมกันทั่วโลกทุก 15 วินาที ช่วงรอยต่อนั้นความหน่วงและ throughput แกว่ง และมีช่วงขาดสั้น ๆ ไม่ถึง 1 วินาที (ไม่ได้เกิดจากการสลับดาวเทียม), ความหน่วงช่วงอุปกรณ์ผู้ใช้↔ดาวเทียม↔สถานีภาคพื้นดิน ประมาณ 40 ms Mile High WiFi: A First Look at In-Flight Internet Connectivity (WWW 2018) ACM วัดอินเทอร์เน็ตบนเครื่องบิน 45 ชั่วโมง: เวลาไปกลับเฉลี่ยแบบสถานีฐานภาคพื้นดิน 200 ms แบบดาวเทียม 750 ms, ค่ามัธยฐานอัตราแพ็กเก็ตหายของแบบดาวเทียม 7% Probe Selection (RIPE Atlas REST API) RIPE NCC เลือก probe ของ RIPE Atlas ตามประเทศ, ภูมิภาค, ASN หรือช่วง IP แล้วรัน ping และ traceroute
ID isp-routing · ผู้รับผิดชอบหลัก อินฟราเครือข่าย (ทีมอินฟรา) · ร่วมกับ ภายนอก (ภายนอก)
เพราะสัญญาการเชื่อมต่อระหว่าง ISP แม้เซิร์ฟเวอร์จะอยู่ใกล้ แพ็กเก็ตก็ยังวิ่งอ้อมไปทางไกล
ทำไม ISP ของเรากับ ISP ฝั่งเซิร์ฟเวอร์ไม่ได้เชื่อมต่อกันโดยตรง → ผลคือ วิ่งผ่านประเทศอื่นหรือเมืองอื่น ระยะทางและจำนวนอุปกรณ์ที่ผ่านจึงเพิ่มขึ้น → บนหน้าจอ เฉพาะผู้เล่นของ ISP บางค่ายที่ปิงสูงผิดปกติ
อาการ อินพุตดีเลย์
ปัจจัย ความหน่วง
ใครเจอ บางพื้นที่/บาง ISP
เกิดเมื่อไร ตลอดเวลา
ผู้รับผิดชอบ ผู้รับผิดชอบหลัก อินฟราเครือข่าย (ทีมอินฟรา) · ร่วมกับ ภายนอก (ภายนอก)
งานฝั่งทีมอินฟรา เชื่อมต่อกับ ISP หลายค่าย (multihoming), มอนิเตอร์ปิงแยกตาม ISP เพื่อหาค่ายที่วิ่งอ้อม, เจรจาปรับเส้นทางกับ ISP
งานฝั่งภายนอก ร้องขอให้ ISP ค่ายนั้นปรับเส้นทาง
ตัวเลขที่ควรรู้ แม้อยู่ในประเทศเดียวกัน ปิงก็อาจต่างกันสองสามเท่าตามเส้นทาง
บนกราฟ สูงตลอดตั้งแต่แรก · RTT (แยกตาม ISP/ASN)
จุดที่ต้องดู เทียบ RTT แยกตาม ISP (ASN) แล้วดูว่าเส้นทางผ่านประเทศหรือเมืองใด จาก probe ของ RIPE Atlas ใน ISP ที่ช้า หรือจาก traceroute หรือ mtr ที่ได้จากผู้เล่น วัด IPv4 และ IPv6 แยกกัน (mtr -4, -6) สัญญาณว่าใช่ ภูมิภาคเดียวกันแต่ ISP บางค่ายสูงตลอด และเส้นทางมีช่วงที่ผ่านประเทศอื่นหรือเมืองที่อยู่ไกล หรือสูงเฉพาะ IP เวอร์ชันเดียว (IPv4 หรือ IPv6) สัญญาณว่าไม่ใช่ ถ้าทุก ISP สูงพอ ๆ กัน น่าจะเป็น “ความหน่วงในการแพร่สัญญาณ (ระยะทางจริง)” ถ้าสูงเฉพาะหัวค่ำ น่าจะเป็น “จุด peering แออัดช่วงพีค” วิธีตรวจ ใช้เครื่องมือฝั่งอินฟรา (ไม่ต้องใช้โค้ดเกม)
รายละเอียดเพิ่มเติม IPv4 และ IPv6 กำหนดเส้นทางแยกกัน แม้เป็นเซิร์ฟเวอร์เดียวกันก็อาจมีฝั่งเดียวที่อ้อมไกลจนช้า (การวัดของ APNIC ปี 2016: ภายใน ISP เดียวกันพบกลุ่มผู้ใช้ที่ IPv6 ช้ากว่า IPv4 อยู่ 15 ms, 25 ms และ 75 ms แยกกันเป็นกลุ่ม) แอปที่ใช้วิธี Happy Eyeballs (RFC 8305) ซึ่งเลือกใช้ฝั่งที่เชื่อมต่อได้ก่อนระหว่าง IPv6 กับ IPv4 จะลอง IPv6 ก่อน และถ้า IPv6 เชื่อมต่อได้ภายในค่าแนะนำ 250 ms ก็จะไม่ลอง IPv4 ดังนั้นแม้ฝั่ง IPv6 จะช้ากว่านิดหน่อย ก็มักจะเชื่อมต่อผ่านเส้นทางนั้น ถ้าปิงสูงเฉพาะบาง ISP ให้ลองวัด IPv4 และ IPv6 แยกกัน
กรณีจริง Riot Games 2015: ทราฟฟิก League of Legends ที่วิ่งอ้อมไปไกล และ Riot Direct
แหล่งอ้างอิง 6 รายการ
ID isp-peak · ผู้รับผิดชอบหลัก อินฟราเครือข่าย (ทีมอินฟรา) · ร่วมกับ ภายนอก (ภายนอก)
ช่วงหัวค่ำราว 21:00–23:00 ทราฟฟิกวิดีโอพุ่งขึ้นมาก จุดเชื่อมต่อระหว่าง ISP (peering) จึงมักแออัด
ทำไม ช่วงหัวค่ำมีการสตรีมและดาวน์โหลดพร้อมกันจำนวนมาก → ผลคือ เกิดคิวและแพ็กเก็ตหายที่จุด peering → บนหน้าจอ เฉพาะช่วงหัวค่ำที่ผู้เล่นของ ISP บางค่ายกระตุกหรือวาร์ป
อาการ กระตุก , วาร์ป , ดีดกลับ
ปัจจัย จิตเตอร์, แพ็กเก็ตหาย, ความหน่วง
ใครเจอ บางพื้นที่/บาง ISP
เกิดเมื่อไร ช่วงพีคหัวค่ำ
ผู้รับผิดชอบ ผู้รับผิดชอบหลัก อินฟราเครือข่าย (ทีมอินฟรา) · ร่วมกับ ภายนอก (ภายนอก)
งานฝั่งทีมอินฟรา เพิ่มการเชื่อมต่อตรงกับ ISP ค่ายนั้น, เลี่ยงเส้นทางที่แออัด, มอนิเตอร์แพ็กเก็ตหายและปิงช่วงหัวค่ำแยกตาม ISP
งานฝั่งภายนอก ร้องขอให้ ISP ค่ายนั้นขยายความจุของจุด peering
บนกราฟ สูงเฉพาะบางช่วงเวลา · RTT/แพ็กเก็ตหาย (แยกตาม ISP)
จุดที่ต้องดู พล็อต RTT และแพ็กเก็ตหายแยกตาม ISP (ASN) ตามช่วงเวลา แล้วเก็บ mtr ทั้งช่วงหัวค่ำและกลางวันจาก probe ของ RIPE Atlas ใน ISP นั้นหรือจากผู้เล่น เพื่อดูว่าแพ็กเก็ตเริ่มหายที่ช่วงไหน สัญญาณว่าใช่ เฉพาะ ISP บางค่ายที่ RTT และแพ็กเก็ตหายสูงขึ้นทุกวันช่วงราว 21:00–23:00 และใน mtr แพ็กเก็ตหายและความหน่วงต่อเนื่องตั้งแต่จุดเชื่อมต่อระหว่าง ISP ไปจนถึงปลายทาง สัญญาณว่าไม่ใช่ ถ้าทุก ISP สูงขึ้นพร้อมกัน น่าจะเป็นฝั่งวงจรหรือเซิร์ฟเวอร์ของเรา ถ้าแย่เฉพาะคนในบ้านเดียวกันช่วงหัวค่ำ น่าจะเป็น “ช่องสัญญาณ Wi-Fi แออัด” วิธีตรวจ ใช้เครื่องมือฝั่งอินฟรา (ไม่ต้องใช้โค้ดเกม)
แหล่งอ้างอิง 2 รายการ
ID isp-cable · ผู้รับผิดชอบหลัก ภายนอก (ภายนอก) · ร่วมกับ อินฟราเครือข่าย (ทีมอินฟรา)
เมื่อเคเบิลใต้น้ำขาด ทราฟฟิกต้องอ้อมไปเส้นทางไกลหลายสัปดาห์ (นานสุดหลายเดือน) จนกว่าจะซ่อมเสร็จ และวงจรที่เหลืออยู่ก็แออัด
ทำไม เคเบิลขาดหรืออุปกรณ์เสีย → ผลคือ ทราฟฟิกไปกองที่เส้นทางอ้อมที่ไกลและวงจรที่เหลืออยู่ → บนหน้าจอ ผู้เล่นที่เชื่อมต่อจากต่างประเทศปิงพุ่งและแพ็กเก็ตหาย ต่อเนื่องหลายวันถึงหลายสัปดาห์
อาการ อินพุตดีเลย์ , วาร์ป
ปัจจัย ความหน่วง, แพ็กเก็ตหาย
ใครเจอ บางพื้นที่/บาง ISP
เกิดเมื่อไร ตลอดเวลา
ผู้รับผิดชอบ ผู้รับผิดชอบหลัก ภายนอก (ภายนอก) · ร่วมกับ อินฟราเครือข่าย (ทีมอินฟรา)
งานฝั่งทีมอินฟรา จัดหาวงจรที่ใช้เส้นทางอื่นไว้, ย้ายทราฟฟิกไปเส้นทางนั้นเมื่อเกิดเหตุขัดข้อง
งานฝั่งภายนอก แจ้งผู้เล่นต่างประเทศถึงสาเหตุและเวลาที่คาดว่าจะกลับมาปกติ, ขอให้ผู้ให้บริการวงจรยืนยันกำหนดการซ่อม
บนกราฟ ขึ้นเป็นขั้นบันไดจากจุดหนึ่ง · RTT (แยกตามประเทศของผู้เล่นต่างประเทศ)
จุดที่ต้องดู หาเวลาที่เริ่มสูงขึ้นในกราฟ RTT และแพ็กเก็ตหายแยกตามประเทศ แล้วเทียบกับสรุปเหตุขัดข้องอินเทอร์เน็ตของ Cloudflare Radar และประกาศของผู้ให้บริการเคเบิลใต้น้ำ และใช้ traceroute ดูว่าเส้นทางอ้อมไปอีกทวีปหรือไม่ สัญญาณว่าใช่ ตั้งแต่จุดหนึ่ง RTT ของบางภูมิภาคในต่างประเทศขึ้นไปหนึ่งขั้นและอยู่ระดับนั้นหลายวันถึงหลายสัปดาห์ และช่วงเดียวกันมีรายงานเคเบิลขัดข้อง เส้นทางเปลี่ยนไปเป็นทางอ้อมที่ไกลกว่าปกติ สัญญาณว่าไม่ใช่ ถ้ากลับมาปกติภายในไม่กี่วันและไม่มีรายงานเหตุขัดข้อง น่าจะเป็น “เส้นทาง BGP เปลี่ยนและ converge ใหม่” หรือช่วงเครือข่ายของ ISP วิธีตรวจ ใช้เครื่องมือฝั่งอินฟรา (ไม่ต้องใช้โค้ดเกม)
แหล่งอ้างอิง 3 รายการ
ID isp-bgp · ผู้รับผิดชอบหลัก อินฟราเครือข่าย (ทีมอินฟรา) · ร่วมกับ พัฒนาเซิร์ฟเวอร์ (ทีมพัฒนาเกม), ภายนอก (ภายนอก)
เมื่อข้อมูลเส้นทางของอินเทอร์เน็ตเปลี่ยน แพ็กเก็ตจะหายในช่วงไม่กี่วินาทีถึงหลายสิบวินาที (บางกรณีหลายนาที) ที่เส้นทางกำลัง converge ใหม่
ทำไม ข้อมูลเส้นทางในช่วงเครือข่ายของ ISP รายใดรายหนึ่งเปลี่ยน → ผลคือ แพ็กเก็ตหายไปไม่กี่วินาทีถึงหลายสิบวินาที หรือสลับไปใช้เส้นทางใหม่ → บนหน้าจอ จู่ ๆ ก็ค้างไปไม่กี่วินาที แล้วค่าปิงเปลี่ยนไป (เช่น 40 → 70 ms)
อาการ ค้าง , วาร์ป
ปัจจัย แพ็กเก็ตหาย, ความหน่วง
ใครเจอ บางพื้นที่/บาง ISP
เกิดเมื่อไร สุ่มเป็นครั้งคราว
ผู้รับผิดชอบ ผู้รับผิดชอบหลัก อินฟราเครือข่าย (ทีมอินฟรา) · ร่วมกับ พัฒนาเซิร์ฟเวอร์ (ทีมพัฒนาเกม), ภายนอก (ภายนอก)
งานฝั่งทีมพัฒนาเกม ตั้งไทม์เอาต์ให้ทนการขาดช่วงสั้น ๆ ได้ (ไม่ตัดการเชื่อมต่อที่หยุดไปไม่กี่วินาทีทันที)
งานฝั่งทีมอินฟรา มอนิเตอร์เส้นทาง (เฝ้าดูการเปลี่ยนแปลงของเส้นทางและปิงของช่วง IP ของเรา), ใช้ BFD ตรวจจับวงจรของเราที่ขัดข้องภายใน 1 วินาทีแล้วสลับเส้นทาง (hold time ค่าเริ่มต้นของ BGP คือ 90–180 วินาที), ถ้าเส้นทางเปลี่ยนไปทางไกลแล้วไม่กลับมา ให้ย้ายทราฟฟิกไปวงจรอื่น
งานฝั่งภายนอก ขอให้ ISP ที่เส้นทางในช่วงเครือข่ายของตนเปลี่ยนบ่อยตรวจหาสาเหตุ
บนกราฟ ขึ้นเป็นขั้นบันไดจากจุดหนึ่ง · RTT, เส้นทางจาก traceroute
จุดที่ต้องดู เทียบเส้นทางจาก traceroute และ mtr ก่อนและหลังเวลาที่ RTT เปลี่ยน และดูประวัติการเปลี่ยนเส้นทาง BGP ของช่วง IP ของเรา (prefix) ด้วย RIPEstat BGPlay สัญญาณว่าใช่ หยุดไปไม่กี่วินาทีพร้อมกับที่ RTT ย้ายไปอยู่อีกค่าหนึ่ง และในเวลาเดียวกันมี BGP update และ AS path เปลี่ยน สัญญาณว่าไม่ใช่ ถ้าไม่มีประวัติการเปลี่ยนเส้นทางแต่สูงเฉพาะหัวค่ำ น่าจะเป็น “จุด peering แออัดช่วงพีค” ถ้าแย่เฉพาะบางการเชื่อมต่อ น่าจะเป็น “เส้นทาง ECMP เส้นหนึ่งเสีย” วิธีตรวจ ใช้เครื่องมือฝั่งอินฟรา (ไม่ต้องใช้โค้ดเกม)
กรณีจริง Cloudflare 2020: คอนฟิกแบ็กโบนของ Cloudflare ผิดพลาด ทำให้ทราฟฟิกบางเมืองหายไป Meta 2021: คำสั่งเดียวบนแบ็กโบนของ Facebook ทำให้ DNS หายไปด้วย Cloudflare 2025: DNS สาธารณะ 1.1.1.1 ของ Cloudflare ขัดข้อง
แหล่งอ้างอิง 4 รายการ
ID isp-ecmp · ผู้รับผิดชอบหลัก อินฟราเครือข่าย (ทีมอินฟรา) · ร่วมกับ พัฒนาเซิร์ฟเวอร์ (ทีมพัฒนาเกม), ภายนอก (ภายนอก)
ISP และดาต้าเซ็นเตอร์มีหลายเส้นทางไปยังปลายทางเดียวกัน และกำหนดเส้นทางหนึ่งเส้นให้แต่ละการเชื่อมต่อ ถ้าเสียแค่เส้นเดียว คนที่ถูกจัดให้ใช้เส้นนั้นจะแลคอยู่ตลอด
ทำไม ในช่วงที่รวมหลายลิงก์เข้าด้วยกัน มีลิงก์หรืออุปกรณ์ตัวหนึ่งเสียหรือแออัด → ผลคือ เส้นทางถูกกำหนดจากค่า hash ของ IP และพอร์ต การเชื่อมต่อที่ถูกจัดให้ใช้เส้นนั้นเท่านั้นที่เจอแพ็กเก็ตหายและความหน่วง → บนหน้าจอ ภูมิภาคเดียวกัน ISP เดียวกัน แต่บางคนวาร์ปอยู่เรื่อย ๆ บางครั้งเชื่อมต่อใหม่แล้วกลับมาปกติ
อาการ วาร์ป , ดีดกลับ , กระตุก
ปัจจัย แพ็กเก็ตหาย, จิตเตอร์
ใครเจอ เราคนเดียว, บางพื้นที่/บาง ISP
เกิดเมื่อไร ตลอดเวลา
ผู้รับผิดชอบ ผู้รับผิดชอบหลัก อินฟราเครือข่าย (ทีมอินฟรา) · ร่วมกับ พัฒนาเซิร์ฟเวอร์ (ทีมพัฒนาเกม), ภายนอก (ภายนอก)
งานฝั่งทีมพัฒนาเกม เก็บสถิติแพ็กเก็ตหายและการส่งซ้ำแยกตามการเชื่อมต่อ ให้ดึง IP, พอร์ต และเวลาของคนที่เจอปัญหาได้ (TCP ใช้จำนวนการส่งซ้ำจาก TCP_INFO, UDP คำนวณจาก sequence number ที่ขาดหาย)
งานฝั่งทีมอินฟรา รวบรวม IP, พอร์ต และเวลาของคนที่เจอปัญหาส่งให้ ISP หรือดาต้าเซ็นเตอร์, มอนิเตอร์แพ็กเก็ตหายแยกตามเส้นทาง, วัดเส้นทางด้วยโปรโตคอลและพอร์ตเดียวกับเกม (mtr --tcp หรือ --udp กับ --port), ถ้าเป็นเส้นทางในอุปกรณ์ของเรา ให้ถอดลิงก์หรืออุปกรณ์ที่เสียออกจากกลุ่ม
งานฝั่งภายนอก ขอให้ ISP ตรวจและเปลี่ยนเส้นทางที่เสีย, แนะนำผู้เล่นให้เชื่อมต่อใหม่เพื่อเลี่ยงไปก่อน (กรณีที่เชื่อมต่อใหม่แล้วพอร์ตเปลี่ยน)
ตัวเลขที่ควรรู้ ถ้ามี 4 เส้นทาง จะมีผู้เล่นประมาณ 1 ใน 4 ที่เจอปัญหา แพ็กเก็ตที่ใช้วัดปิงบางครั้งวิ่งคนละเส้นกับเกม ผลจึงออกมาปกติ
บนกราฟ สูงเฉพาะบางกลุ่ม · แพ็กเก็ตหาย/การส่งซ้ำแยกตามการเชื่อมต่อ (แยกตาม IP/พอร์ต)
จุดที่ต้องดู ดูแพ็กเก็ตหายและการส่งซ้ำแยกตามการเชื่อมต่อโดยแบ่งตาม IP และพอร์ตต้นทาง แล้ววัดด้วย mtr แบบ UDP (-u) ไปที่พอร์ตเกม (-P) โดยกำหนดพอร์ตต้นทาง (-L) และทำซ้ำหลายรอบโดยเปลี่ยนพอร์ตต้นทาง ถ้าใส่แค่ -P โดยไม่มี -L พอร์ตต้นทางจะเปลี่ยนทุกคำขอ ทำให้หลายเส้นทางปนกัน สัญญาณว่าใช่ ในภูมิภาคและ ISP เดียวกัน เฉพาะชุดพอร์ตต้นทาง (หรือ IP) บางชุดที่แพ็กเก็ตหายตลอด และเมื่อเชื่อมต่อใหม่จนพอร์ตเปลี่ยนก็กลับมาปกติ สัญญาณว่าไม่ใช่ ถ้าเปลี่ยนพอร์ตแล้วยังแย่ทั้งหมด น่าจะเป็นความแออัดหรือเหตุขัดข้องของทั้งช่วงเครือข่าย วิธีตรวจ ใช้เครื่องมือฝั่งอินฟรา (ไม่ต้องใช้โค้ดเกม)
รายละเอียดเพิ่มเติม อุปกรณ์ (ECMP, LAG) จะล็อกเส้นทางให้แต่ละการเชื่อมต่อตามค่าที่คำนวณจาก IP และพอร์ต (บางอุปกรณ์ตั้งให้ใช้แค่ IP) เพื่อไม่ให้ลำดับแพ็กเก็ตในการเชื่อมต่อเดียวกันสลับกัน ในที่ที่ใช้แค่ IP แม้เชื่อมต่อใหม่ก็ยังได้เส้นทางเดิม อาการจึงไม่ดีขึ้น ดังนั้นถ้ามีรายงานอย่าง “ปิงปกติแต่เกมแลค” หรือ “เชื่อมต่อใหม่แล้วดีขึ้น” เข้ามาพร้อมกัน ให้สงสัยสาเหตุนี้
แหล่งอ้างอิง 3 รายการ
ID isp-shaping · ผู้รับผิดชอบหลัก ภายนอก (ภายนอก) · ร่วมกับ พัฒนาเซิร์ฟเวอร์ (ทีมพัฒนาเกม), อินฟราเครือข่าย (ทีมอินฟรา)
ในแพ็กเกจที่ใช้ดาต้าเกินโควตาแล้ว หรือแพ็กเกจที่มีการจัดการทราฟฟิกบางประเภท แพ็กเก็ตจะถูกหน่วงหรือถูกทิ้ง
ทำไม ถูกจำกัดความเร็วหลังดาต้าในแพ็กเกจหมด หรือถูกจำกัดทราฟฟิกบางประเภท → ผลคือ แพ็กเก็ตต้องรอคิวหรือถูกทิ้ง → บนหน้าจอ แลคหลังใช้งานไปถึงปริมาณหนึ่ง โดยเฉพาะบนมือถือ
อาการ อินพุตดีเลย์ , วาร์ป
ปัจจัย ความหน่วง, แพ็กเก็ตหาย
ใครเจอ เราคนเดียว, บางพื้นที่/บาง ISP
เกิดเมื่อไร ตลอดเวลา, ช่วงพีคหัวค่ำ
ผู้รับผิดชอบ ผู้รับผิดชอบหลัก ภายนอก (ภายนอก) · ร่วมกับ พัฒนาเซิร์ฟเวอร์ (ทีมพัฒนาเกม), อินฟราเครือข่าย (ทีมอินฟรา)
งานฝั่งทีมพัฒนาเกม ลดทราฟฟิกของเกม (บีบอัด, ส่งเฉพาะที่จำเป็น)
งานฝั่งทีมอินฟรา ถ้าทราฟฟิกเกมถูกหน่วงหรือถูกทิ้งเฉพาะบาง ISP ให้รวบรวมข้อมูลแล้ว escalate ไปยัง ISP
งานฝั่งภายนอก แนะนำผู้เล่นให้ตรวจว่าดาต้าในแพ็กเกจหมดหรือถูกจำกัดความเร็วหรือไม่ และมีแอปอื่นในมือถือเครื่องเดียวกันใช้เน็ตอยู่หรือไม่, ขอให้ ISP ยืนยันว่ามีการจำกัดทราฟฟิกเกมหรือไม่
ตัวเลขที่ควรรู้ แพ็กเกจมือถือในเกาหลี เมื่อใช้ดาต้าหมดมักถูกจำกัดเหลือ 1–5 Mbps ส่วนแพ็กเกจราคาถูกเหลือหลายร้อย kbps แม้เกมจะใช้ดาต้าน้อย แต่ถ้าแอปอื่นในมือถือเครื่องเดียวกันใช้เน็ตไปด้วย ก็จะเกิดคิวหน้าอุปกรณ์จำกัดความเร็ว
บนกราฟ ชนเพดานแล้วแบนราบ · throughput, RTT
จุดที่ต้องดู ให้ผู้เล่นเช็กดาต้าที่เหลือและสถานะการจำกัดความเร็วในแอปของค่ายมือถือ แล้วทดสอบความเร็วเพื่อดูความเร็วสูงสุด ฝั่งเซิร์ฟเวอร์ให้เทียบแพ็กเก็ตหายและ RTT แยกตาม ISP สัญญาณว่าใช่ throughput ไม่ขึ้นเกินค่าหนึ่ง เช่น 1–5 Mbps หรือหลายร้อย kbps และตั้งแต่นั้น ถ้าแอปอื่นในมือถือเครื่องเดียวกันใช้เน็ต RTT และแพ็กเก็ตหายจะเพิ่มขึ้น อาการหายไปเมื่อเติมดาต้าหรือเปลี่ยนไปใช้ Wi-Fi สัญญาณว่าไม่ใช่ ถ้าไม่ถูกจำกัดความเร็วแต่แย่เฉพาะบาง ISP น่าจะเป็น “จุด peering แออัดช่วงพีค” หรือ “เส้นทางวิ่งอ้อม” วิธีตรวจ ตรวจที่สภาพแวดล้อมฝั่งผู้เล่น
แหล่งอ้างอิง 2 รายการ SKT, 고객 선택권과 혜택 강화한 신규 5G 요금제 출시 SK텔레콤 ตัวอย่างการควบคุมความเร็วหลังดาต้าพื้นฐานของแพ็กเกจ 5G หมด: สูงสุด 400 kbps, 1 Mbps, 3 Mbps SKT, 요금제 개편 SK텔레콤 ใช้งานต่อได้ที่ความเร็วสูงสุด 400 kbps แม้ใช้ดาต้าพื้นฐานหมดแล้ว (โครงการดาต้าอุ่นใจสำหรับคนทั้งประเทศ)
ID isp-udp-block · ผู้รับผิดชอบหลัก ภายนอก (ภายนอก) · ร่วมกับ พัฒนาไคลเอนต์ (ทีมพัฒนาเกม), พัฒนาเซิร์ฟเวอร์ (ทีมพัฒนาเกม), อินฟราเครือข่าย (ทีมอินฟรา)
บางเครือข่ายบล็อก IP หรือพอร์ต UDP บางตัว หรือจำกัดความเร็ว UDP และอุปกรณ์ตรวจแพ็กเก็ตจะกรองโปรโตคอลที่ไม่รู้จักทิ้ง เกมที่สื่อสารด้วย UDP จึงเชื่อมต่อในเครือข่ายนั้นไม่ได้หรือหลุดบ่อย
ทำไม เชื่อมต่อจากเครือข่าย ISP บางรายที่จำกัดความเร็ว UDP หรือจากเครือข่ายที่มีอุปกรณ์ตรวจทราฟฟิก (เพื่อเซ็นเซอร์) ระดับประเทศหรือ ISP → ผลคือ บล็อก IP หรือพอร์ต UDP บางตัว, จำกัดความเร็ว UDP ในช่วงที่แออัด, กรองพอร์ตหรือโปรโตคอลที่ไม่อยู่ในรายการอนุญาตทิ้ง หรือปล่อยผ่านแค่ไม่กี่แพ็กเก็ตแรกแล้วบล็อก → บนหน้าจอ เฉพาะผู้เล่นในบางประเทศหรือบาง ISP ที่เข้าเกมไม่ได้หรือโหลดไม่จบ, เข้าได้แล้วหลุดในไม่ช้า, วาร์ปเพราะแพ็กเก็ตหายในช่วงที่แออัด
อาการ เข้าเกมไม่ได้/โหลดไม่จบ , หลุด , วาร์ป
ปัจจัย แพ็กเก็ตหาย
ใครเจอ บางพื้นที่/บาง ISP
เกิดเมื่อไร หลังล็อกอิน/หลังปิดปรับปรุง, ตลอดเวลา, ช่วงพีคหัวค่ำ
ผู้รับผิดชอบ ผู้รับผิดชอบหลัก ภายนอก (ภายนอก) · ร่วมกับ พัฒนาไคลเอนต์ (ทีมพัฒนาเกม), พัฒนาเซิร์ฟเวอร์ (ทีมพัฒนาเกม), อินฟราเครือข่าย (ทีมอินฟรา)
งานฝั่งทีมพัฒนาเกม ไคลเอนต์: ถ้า UDP เชื่อมต่อไม่ได้ภายในไม่กี่วินาที ให้สลับไปเส้นทางสำรอง TCP/TLS 443 อัตโนมัติ, ตรวจจับกรณีที่เชื่อมต่อได้ตอนแรกแล้วหลุดในไม่ช้าด้วย แล้วลองใหม่ผ่านเส้นทางสำรอง, บันทึกลง log ว่าเชื่อมต่อผ่านเส้นทางไหน เซิร์ฟเวอร์: รับโปรโตคอลเกมเดียวกันผ่าน TCP 443 (TLS) ด้วย, ปรับไทม์เอาต์เพราะเส้นทางสำรองอาจมีความหน่วงเพิ่มขึ้น
งานฝั่งทีมอินฟรา ก่อนขยายบริการไปประเทศใหม่ ให้วัดในเครือข่าย ISP ท้องถิ่นว่า UDP ไปถึงได้หรือไม่และแพ็กเก็ตหายช่วงพีคเท่าไร, ตั้ง relay หรือเกตเวย์ที่รับเส้นทางสำรอง TCP 443 ไว้ใกล้ประเทศนั้น, เฝ้าดูอัตราการเชื่อมต่อสำเร็จของ UDP และ TCP แยกตามประเทศและ ASN, ถ้ายืนยันได้ว่า ISP ใดจำกัดความเร็ว UDP ให้รวบรวมข้อมูลแล้ว escalate
งานฝั่งภายนอก สอบถาม ISP หรือหน่วยงานนั้นถึงเกณฑ์การจำกัด UDP และขอให้ผ่อนปรน, แนะนำผู้เล่นให้ลองเชื่อมต่อจากเครือข่ายอื่นเพื่อเปรียบเทียบ
ตัวเลขที่ควรรู้ ตามการวัดที่เอกสาร IETF อ้างถึง 3–5% ของเครือข่ายบล็อก UDP ทั้งหมด เมื่อ Google ดูผลการใช้ QUIC (ที่ทำงานบน UDP) ในปี 2016 พบว่าไคลเอนต์ 4.4% ใช้ไม่ได้เพราะ UDP หรือ QUIC ถูกบล็อก หรือ path MTU เล็กเกินไป ส่วนใหญ่อยู่หลังไฟร์วอลล์ขององค์กร และไม่พบกรณีที่ ISP บล็อกทั้งเครือข่าย อีก 0.3% อยู่ในเครือข่ายที่แพ็กเก็ตหายเพิ่มขึ้นมากในช่วงพีค ซึ่งดูเหมือนจำกัดความเร็ว UDP และหลังจากขอให้ ISP แก้ไข สัดส่วนนี้ก็ลดลงจาก 1% ในปี 2015
บนกราฟ สูงเฉพาะบางกลุ่ม · อัตราการเชื่อมต่อ UDP สำเร็จ (แยกตามประเทศ/ASN)
จุดที่ต้องดู ดูอัตราการเชื่อมต่อสำเร็จของ UDP และของเส้นทางสำรอง TCP 443 แยกกันตามประเทศและ ASN ทดสอบเชื่อมต่อไปที่พอร์ต UDP ของเกมและ TCP 443 แยกกันจาก VM บนคลาวด์ในเครือข่าย ISP นั้นหรือจาก PC ของผู้เล่น แล้วใช้ mtr -u -P (พอร์ตเกม) และ mtr -T -P 443 เทียบว่าการตอบกลับหายไปตั้งแต่ช่วงไหน สัญญาณว่าใช่ เฉพาะบางประเทศหรือบาง ASN ที่ UDP ไม่ได้รับการตอบกลับครั้งแรก หรือหลุดภายในไม่กี่วินาที ขณะที่ TCP 443 จากที่เดียวกันปกติ ถ้าเป็นการจำกัดความเร็ว แพ็กเก็ตหายของ UDP จะเพิ่มชัดเจนเฉพาะช่วงพีค และ TCP ได้รับผลกระทบน้อยกว่า สัญญาณว่าไม่ใช่ ถ้า TCP ล้มเหลวด้วย น่าจะเป็นเส้นทางขัดข้อง, IP ถูกบล็อก หรือ “DNS ขัดข้อง/ช้า” ถ้าเป็นเหมือนกันทุกประเทศ น่าจะเป็นการตั้งค่าเซิร์ฟเวอร์หรือไฟร์วอลล์ของเรา ถ้าแพ็กเก็ตหายเฉพาะตอนที่ส่งข้อมูลปริมาณมากในชั่วขณะ ไม่ว่าจะเป็น UDP หรือ TCP น่าจะเป็น “policer ทิ้งส่วนที่เกิน” วิธีตรวจ ใช้เครื่องมือฝั่งอินฟรา (ไม่ต้องใช้โค้ดเกม)
รายละเอียดเพิ่มเติม เอกสารสำรวจของ IRTF ระบุว่าอุปกรณ์ตรวจแพ็กเก็ตอาจเลือกบล็อก flow ของ UDP ตาม IP, พอร์ต และโปรโตคอล หรือบล็อกทุกอย่างที่ไม่ใช่โปรโตคอลที่อนุญาต (allowlist) ถ้าอุปกรณ์ตัดสินจากฟิลด์บางส่วนของแพ็กเก็ตเท่านั้น แค่เปลี่ยนโปรโตคอลเล็กน้อยก็อาจถูกบล็อกได้ ในช่วงแรกของ QUIC มีไฟร์วอลล์ตัวหนึ่งที่หลังจาก 1 บิตในเฮดเดอร์เปลี่ยน ก็ปล่อยให้ไม่กี่แพ็กเก็ตแรกผ่านแล้วบล็อกแพ็กเก็ตหลังจากนั้น ทำให้ลอจิกที่ให้ไคลเอนต์สลับไปเชื่อมต่อด้วย TCP ทำงานไม่ได้ ปัญหานี้อาจโผล่มาตอนขยายบริการไปประเทศใหม่ ในรูปของรายงานว่า “ในเกาหลีปกติดี แต่ ISP บางรายในประเทศนั้นเข้าเกมไม่ได้” ถ้าถูกบล็อกเฉพาะในเครือข่ายของสถานที่หนึ่ง เช่น ร้านกาแฟหรือบริษัท ให้ดูสาเหตุ “ข้อจำกัดของ Wi-Fi สาธารณะและเครือข่ายบริษัท”
แหล่งอ้างอิง 4 รายการ RFC 9308: Applicability of the QUIC Transport Protocol IETF ตามงานวิจัยที่วัดจริง 3–5% ของเครือข่ายบล็อก UDP ทั้งหมด แอปที่ใช้ UDP จึงต้องยอมรับว่าอาจเชื่อมต่อไม่สำเร็จ หรือมีเส้นทางสำรองผ่าน TCP (TLS), ไฟร์วอลล์อาจบล็อกพอร์ตที่ไม่ได้ผูกกับบริการที่ลงทะเบียนไว้ The QUIC Transport Protocol: Design and Internet-Scale Deployment (SIGCOMM 2017) ACM ปี 2016: ไคลเอนต์ 4.4% ใช้ QUIC (UDP) ไม่ได้ (UDP หรือ QUIC ถูกบล็อก หรือ path MTU เล็ก ส่วนใหญ่อยู่หลังไฟร์วอลล์ขององค์กร และไม่พบ ISP ที่บล็อกทั้งเครือข่าย), 0.3% อยู่ในเครือข่ายที่ดูเหมือนจำกัดความเร็ว UDP (แพ็กเก็ตหายเพิ่มในช่วงพีค หลังขอให้ ISP แก้ไขก็ลดลงจาก 1% ในปี 2015), กรณีไฟร์วอลล์ที่หลัง 1 บิตในเฮดเดอร์เปลี่ยน ก็ปล่อยผ่านแค่ไม่กี่แพ็กเก็ตแรกแล้วบล็อกที่เหลือ ทำให้ลอจิกสำรองไปใช้ TCP ใช้การไม่ได้ RFC 9505: A Survey of Worldwide Censorship Techniques IRTF อุปกรณ์ตรวจในเครือข่ายอาจเลือกบล็อก flow ของ TCP หรือ UDP ตาม IP, พอร์ต และโปรโตคอล (พบการบล็อก endpoint UDP ของ QUIC), วิธีบล็อกทุกอย่างที่ไม่ใช่โปรโตคอลที่อนุญาตทำให้บล็อกเกินจำเป็น และยังมีวิธีจำกัดความเร็วของทราฟฟิกบางประเภทด้วย mtr(8) manual page source mtr ใช้ -u ส่ง UDP, -T ส่ง TCP SYN และ -P กำหนดพอร์ตปลายทาง เพื่อวัดเส้นทางด้วยโปรโตคอลและพอร์ตเดียวกับเกม
ID isp-line · ผู้รับผิดชอบหลัก ภายนอก (ภายนอก)
ขั้วต่อหลวม สายเก่า หรือโมเด็มผิดปกติ ทำให้แพ็กเก็ตหายอย่างต่อเนื่องและเน็ตขาดเป็นระยะ
ทำไม สายเคเบิลเสียหาย, ขั้วต่อหลวม, โมเด็มหรืออุปกรณ์ไฟเบอร์ (ONU) ผิดปกติ → ผลคือ แพ็กเก็ตถูกทิ้งเพราะบิตผิดพลาด และบางครั้งเน็ตขาดไปหลายวินาทีถึงราว 1 นาทีระหว่างเชื่อมต่อใหม่ → บนหน้าจอ แพ็กเก็ตหายเล็กน้อยต่อเนื่อง บางครั้งค้างไปหลายวินาทีหรือหลุด
อาการ วาร์ป , ค้าง , หลุด
ปัจจัย แพ็กเก็ตหาย
ใครเจอ คนในบ้านเดียวกัน
เกิดเมื่อไร สุ่มเป็นครั้งคราว
ผู้รับผิดชอบ ผู้รับผิดชอบหลัก ภายนอก (ภายนอก)
งานฝั่งภายนอก แนะนำผู้เล่นให้ดูว่าเกมอื่นหรือวิดีโอคอลก็ขาดด้วยหรือไม่ ถ้าใช่ ให้แจ้ง ISP ให้มาตรวจสาย
บนกราฟ พุ่งแบบสุ่มเป็นครั้งคราว · อัตราแพ็กเก็ตหาย, ประวัติการเชื่อมต่อใหม่ของเน็ต
จุดที่ต้องดู ใช้ pathping (หรือ mtr) วัดแพ็กเก็ตหายถึง hop แรกของ ISP ต่อเนื่องหลายนาที และดูเวลาที่เชื่อมต่อใหม่จากประวัติการเชื่อมต่ออินเทอร์เน็ต (WAN) ในหน้าตั้งค่าเราเตอร์ สัญญาณว่าใช่ แม้เน็ตว่างก็มีแพ็กเก็ตหายต่อเนื่องตั้งแต่ hop แรกของ ISP และเวลาที่เน็ตเชื่อมต่อใหม่ในประวัติเราเตอร์ตรงกับเวลาที่เกมค้างหรือหลุด เกมอื่นและวิดีโอคอลก็ขาดไปด้วย สัญญาณว่าไม่ใช่ ถ้าแพ็กเก็ตเริ่มหายตั้งแต่ช่วงไร้สายระหว่างเครื่องกับเราเตอร์ น่าจะเป็น “Wi-Fi ถูกรบกวนหรือสัญญาณอ่อน” ถ้าเริ่มหายที่ช่วงไกลในเครือข่าย ISP ให้ดูเส้นทางของ ISP วิธีตรวจ ตรวจที่สภาพแวดล้อมฝั่งผู้เล่น
แหล่งอ้างอิง 3 รายการ
ID isp-dns · ผู้รับผิดชอบหลัก ภายนอก (ภายนอก) · ร่วมกับ พัฒนาไคลเอนต์ (ทีมพัฒนาเกม)
ถ้า DNS ซึ่งแปลงชื่อเซิร์ฟเวอร์เป็น IP ช้าหรือล้มเหลว เกมจะหาเซิร์ฟเวอร์ล็อกอินหรือเซิร์ฟเวอร์แพตช์ไม่เจอ
ทำไม DNS ของ ISP ขัดข้องหรือตั้งค่าผิด → ผลคือ หา IP ของเซิร์ฟเวอร์ล็อกอินหรือเซิร์ฟเวอร์แพตช์ไม่เจอ → บนหน้าจอ กดเชื่อมต่อแล้วรอนาน หรือเข้าเกมไม่ได้ คนที่เข้าเกมอยู่แล้วไม่เป็นอะไร
อาการ เข้าเกมไม่ได้/โหลดไม่จบ
ปัจจัย ความหน่วง, แพ็กเก็ตหาย
ใครเจอ บางพื้นที่/บาง ISP, เราคนเดียว
เกิดเมื่อไร หลังล็อกอิน/หลังปิดปรับปรุง
ผู้รับผิดชอบ ผู้รับผิดชอบหลัก ภายนอก (ภายนอก) · ร่วมกับ พัฒนาไคลเอนต์ (ทีมพัฒนาเกม)
งานฝั่งทีมพัฒนาเกม แคช IP (จำ IP เซิร์ฟเวอร์ที่เชื่อมต่อสำเร็จครั้งล่าสุด), เตรียม DNS หลายตัว (ถ้าตัวหนึ่งล้มเหลวให้ถาม DNS ตัวอื่นใหม่)
งานฝั่งภายนอก แนะนำผู้เล่นให้ลองเปลี่ยน DNS ไปใช้ตัวอื่น เช่น DNS สาธารณะ
บนกราฟ สูงเฉพาะบางกลุ่ม · จำนวนล็อกอินล้มเหลว (แยกตาม ISP), เวลาตอบกลับของ DNS
จุดที่ต้องดู ใช้ Resolve-DnsName -Server (หรือ nslookup) ถามชื่อเซิร์ฟเวอร์ล็อกอินกับ DNS ของ ISP และ DNS สาธารณะแยกกัน แล้วเทียบเวลาตอบกลับและผลลัพธ์ สัญญาณว่าใช่ เฉพาะ DNS ของ ISP ที่ไม่ตอบหรือตอบช้า และเมื่อเปลี่ยนไปใช้ DNS สาธารณะก็เข้าเกมได้ทันที ผู้เล่นที่เข้าเกมอยู่แล้วไม่เป็นอะไร สัญญาณว่าไม่ใช่ ถ้าได้ IP ทันทีไม่ว่าจะถาม DNS ตัวไหน แต่ยังเข้าเกมไม่ได้ ให้ดูเส้นทาง ไฟร์วอลล์ หรือเซิร์ฟเวอร์ วิธีตรวจ ตรวจที่สภาพแวดล้อมฝั่งผู้เล่น
กรณีจริง Meta 2021: คำสั่งเดียวบนแบ็กโบนของ Facebook ทำให้ DNS หายไปด้วย Cloudflare 2025: DNS สาธารณะ 1.1.1.1 ของ Cloudflare ขัดข้อง AWS 2025: DNS ของ DynamoDB ใน AWS us-east-1 ขัดข้อง และการกู้คืนที่ยืดเยื้อ
แหล่งอ้างอิง 4 รายการ
ID isp-ddos-path · ผู้รับผิดชอบหลัก อินฟราเครือข่าย (ทีมอินฟรา) · ร่วมกับ ภายนอก (ภายนอก)
การโจมตีปริมาณมหาศาลที่พุ่งเป้ามาที่บริษัทเกม หรือที่อื่นในเครือข่ายเดียวกัน ทำให้ลิงก์ที่ใช้ร่วมกันเต็ม
ทำไม มีทราฟฟิกโจมตีปริมาณมหาศาล → ผลคือ ทราฟฟิกปกติที่ใช้ลิงก์เดียวกันก็ถูกเบียดและถูกทิ้งไปด้วย → บนหน้าจอ หลายคนวาร์ป หลุด หรือเข้าเกมไม่ได้พร้อมกัน
อาการ วาร์ป , หลุด , เข้าเกมไม่ได้/โหลดไม่จบ
ปัจจัย แพ็กเก็ตหาย, ความหน่วง
ใครเจอ ทั้งเซิร์ฟเวอร์, บางพื้นที่/บาง ISP
เกิดเมื่อไร สุ่มเป็นครั้งคราว, ตอนคนแห่มารวมกัน
ผู้รับผิดชอบ ผู้รับผิดชอบหลัก อินฟราเครือข่าย (ทีมอินฟรา) · ร่วมกับ ภายนอก (ภายนอก)
งานฝั่งทีมอินฟรา ใช้บริการป้องกัน DDoS, เบี่ยงทราฟฟิกเมื่อถูกโจมตี, ซ่อน IP ของเซิร์ฟเวอร์ (วางไว้หลังอุปกรณ์ป้องกันและไม่เปิดเผย IP จริง)
งานฝั่งภายนอก ถ้าเป็นการโจมตีที่พุ่งเป้าไปที่อื่นในเครือข่ายเดียวกัน ให้ขอ ISP บล็อกที่ช่วงเครือข่ายต้นทาง (upstream)
บนกราฟ ชนเพดานแล้วแบนราบ · ปริมาณรับเข้าของลิงก์ (bps/pps), แพ็กเก็ตที่อินเทอร์เฟซทิ้ง (drop)
จุดที่ต้องดู ดูปริมาณรับเข้าและจำนวนแพ็กเก็ตที่ทิ้งบนอินเทอร์เฟซของวงจรและอุปกรณ์ของเรา และประวัติการตรวจพบการโจมตีของบริการป้องกัน DDoS เทียบกับช่วงที่มีคนหลุดจำนวนมาก สัญญาณว่าใช่ ปริมาณรับเข้าของลิงก์ชนความจุของลิงก์จนแบนราบและการ drop เพิ่มขึ้น ในเวลาเดียวกันผู้เล่นหลายภูมิภาคและหลาย ISP วาร์ปหรือหลุดพร้อมกัน สัญญาณว่าไม่ใช่ ถ้าลิงก์ยังมีที่ว่างแต่แย่เฉพาะบาง ISP น่าจะเป็นความแออัดหรือปัญหาเส้นทางในช่วงเครือข่ายของ ISP วิธีตรวจ ใช้เครื่องมือฝั่งอินฟรา (ไม่ต้องใช้โค้ดเกม)
แหล่งอ้างอิง 3 รายการ
ID isp-cgnat · ผู้รับผิดชอบหลัก พัฒนาไคลเอนต์ (ทีมพัฒนาเกม) · ร่วมกับ พัฒนาเซิร์ฟเวอร์ (ทีมพัฒนาเกม), อินฟราเครือข่าย (ทีมอินฟรา)
เครือข่ายมือถือและ ISP บางรายให้ผู้ใช้บริการหลายรายใช้ IP เดียวร่วมกัน และลบ mapping ของการเชื่อมต่อที่ idle ภายในเวลาสั้น ๆ
ทำไม อุปกรณ์ของ ISP ดูแลตารางเซสชันของผู้ใช้บริการจำนวนมหาศาล → ผลคือ ตารางเซสชันมีขีดจำกัด และ idle timeout สั้น → บนหน้าจอ อยู่เฉย ๆ แล้วหลุด, false positive ที่ทำให้คนที่ใช้ IP เดียวกันถูกบล็อกไปพร้อมกัน
อาการ หลุด , เข้าเกมไม่ได้/โหลดไม่จบ
ปัจจัย แพ็กเก็ตหาย
ใครเจอ บางพื้นที่/บาง ISP
เกิดเมื่อไร หลังอยู่เฉย ๆ สักพัก
ผู้รับผิดชอบ ผู้รับผิดชอบหลัก พัฒนาไคลเอนต์ (ทีมพัฒนาเกม) · ร่วมกับ พัฒนาเซิร์ฟเวอร์ (ทีมพัฒนาเกม), อินฟราเครือข่าย (ทีมอินฟรา)
งานฝั่งทีมพัฒนาเกม ไคลเอนต์: ส่ง heartbeat ทุกช่วงไม่เกินครึ่งหนึ่งของ idle timeout ที่สั้นที่สุด (เครือข่ายมือถือบางแห่งอยู่ราว 30 วินาที) โดยให้ไคลเอนต์เป็นฝ่ายส่ง เพราะ mapping ของ CGNAT ฝั่ง ISP จะต่ออายุแน่นอนก็ต่อเมื่อมีแพ็กเก็ตจากข้างในส่งออกไปเท่านั้น, เชื่อมต่อใหม่อัตโนมัติเมื่อหลุด เซิร์ฟเวอร์: ตอบ heartbeat และถ้าไม่ได้รับตามเวลาที่กำหนดให้เก็บกวาดการเชื่อมต่อก่อน, ถ้า mapping เปลี่ยนจน IP หรือพอร์ตเปลี่ยน ให้ใช้ session token รับต่อเป็นผู้เล่นคนเดิม, IP เดียวอาจมีหลายคนใช้ร่วมกัน จึงต้องระวังนโยบายบล็อกตาม IP (ตัดสินร่วมกับบัญชีและอุปกรณ์)
งานฝั่งทีมอินฟรา ปรับเกณฑ์จำนวนการเชื่อมต่อต่อ IP และจำนวนการเชื่อมต่อใหม่ต่อวินาทีของไฟร์วอลล์และอุปกรณ์ป้องกัน DDoS ให้เหมาะกับ IP ที่ ISP ให้ใช้ร่วมกัน (เพิ่มเกณฑ์หรือยกเว้นช่วง IP ของค่ายมือถือ)
ตัวเลขที่ควรรู้ idle timeout ของ UDP ในเครือข่ายมือถือบางแห่งอยู่ราว 30 วินาที
บนกราฟ การเชื่อมต่อหลุดพร้อมกัน · จำนวนครั้งที่หลุด (heartbeat timeout), ระยะเวลา idle ก่อนหลุด (แยกตาม ISP)
จุดที่ต้องดู ดูจำนวนบัญชีที่เชื่อมต่อพร้อมกันจาก IP เดียวและ ISP (ASN) จาก log การเชื่อมต่อ แล้วรวบรวมระยะเวลา idle ของการเชื่อมต่อที่หลุดหลังอยู่เฉย ๆ แยกตาม ISP ฝั่งผู้เล่นให้ดู IP อินเทอร์เน็ต (WAN) ในหน้าตั้งค่าเราเตอร์ สัญญาณว่าใช่ ในช่วง IP ของค่ายมือถือ มีหลายบัญชีเชื่อมต่อจาก IP เดียว และระยะเวลา idle ก่อนหลุดกระจุกอยู่ที่ราว 30–60 วินาที IP WAN ของเราเตอร์อยู่ใน 100.64.0.0/10 (ที่อยู่ร่วมสำหรับ NAT ของ ISP) หรือไม่ตรงกับ IP ที่เซิร์ฟเวอร์เห็น สัญญาณว่าไม่ใช่ ถ้าไม่เกี่ยวกับ ISP แต่กระจุกที่ผู้ที่ใช้เราเตอร์ในบ้าน น่าจะเป็น “NAT mapping หมดอายุ” วิธีตรวจ ต้องมี log หรือเมตริกจากเซิร์ฟเวอร์/ไคลเอนต์เกม
แหล่งอ้างอิง 4 รายการ
ID isp-vpn · ผู้รับผิดชอบหลัก ภายนอก (ภายนอก) · ร่วมกับ อินฟราเครือข่าย (ทีมอินฟรา), พัฒนาเซิร์ฟเวอร์ (ทีมพัฒนาเกม)
เมื่อเปิด VPN หรือโปรแกรมลดปิง แพ็กเก็ตจะวิ่งผ่านเซิร์ฟเวอร์ตัวกลาง (relay) ของบริษัทนั้น ถ้าเซิร์ฟเวอร์ตัวกลางอยู่ไกลหรือแออัด ก็กลับยิ่งช้าลง
ทำไม VPN หรือโปรแกรมลดปิงส่งแพ็กเก็ตเกมทั้งหมดอ้อมไปที่เซิร์ฟเวอร์ตัวกลาง → ผลคือ ระยะทางและความแออัดถึงเซิร์ฟเวอร์ตัวกลางเพิ่มเข้ามา และเฮดเดอร์ของ tunnel ทำให้ MTU (ขนาดแพ็กเก็ตที่ส่งได้ในครั้งเดียว) ลดลงด้วย → บนหน้าจอ ปิงสูงขึ้นและแพ็กเก็ตหาย, ถูกบล็อกไปพร้อมกับคนที่ใช้ IP ตัวกลางเดียวกันจนเข้าเกมไม่ได้
อาการ อินพุตดีเลย์ , วาร์ป , เข้าเกมไม่ได้/โหลดไม่จบ
ปัจจัย ความหน่วง, แพ็กเก็ตหาย
ใครเจอ เราคนเดียว
เกิดเมื่อไร ตลอดเวลา, หลังล็อกอิน/หลังปิดปรับปรุง
ผู้รับผิดชอบ ผู้รับผิดชอบหลัก ภายนอก (ภายนอก) · ร่วมกับ อินฟราเครือข่าย (ทีมอินฟรา), พัฒนาเซิร์ฟเวอร์ (ทีมพัฒนาเกม)
งานฝั่งทีมพัฒนาเกม รักษาขนาดแพ็กเก็ต UDP ไว้ไม่เกิน 1,200 ไบต์ (เพื่อไม่ให้เกิด fragmentation แม้ MTU จะลดลงเพราะเฮดเดอร์ของ tunnel), การบล็อกตาม IP ให้คำนึงถึง IP ตัวกลางที่ VPN และโปรแกรมลดปิงใช้ร่วมกัน และตัดสินร่วมกับบัญชีและอุปกรณ์
งานฝั่งทีมอินฟรา ถ้ามีผู้เล่นต่างประเทศมาก ให้ตั้งจุดเชื่อมต่อใกล้ผู้เล่นเอง, ตรวจเส้นทางของ ISP ที่มีรายงานว่า “เปิดโปรแกรมลดปิงแล้วดีขึ้น” เข้ามามาก
งานฝั่งภายนอก แนะนำผู้เล่นให้ลองปิด VPN หรือโปรแกรมลดปิงแล้วเปรียบเทียบ
ตัวเลขที่ควรรู้ ถ้าเซิร์ฟเวอร์ตัวกลางอยู่ใกล้ จะเพิ่มแค่ไม่กี่ ms แต่ถ้าอ้อมผ่านประเทศอื่น จะเพิ่มหลายสิบถึงเกิน 100 ms
บนกราฟ สูงเฉพาะบางกลุ่ม · RTT (แยกตามผู้เล่น), ผู้ให้บริการของ IP ที่เชื่อมต่อ
จุดที่ต้องดู ดูว่า ASN ของ IP ที่เชื่อมต่อเป็นผู้ให้บริการ VPN, โปรแกรมลดปิง หรือโฮสติ้งหรือไม่ แล้วให้ผู้เล่นปิด VPN หรือโปรแกรมลดปิงแล้วเทียบปิงและ traceroute สัญญาณว่าใช่ RTT และแพ็กเก็ตหายเพิ่มขึ้น หรือเชื่อมต่อไม่ได้เฉพาะตอนเปิด VPN หรือโปรแกรมลดปิง และใน traceroute เห็นช่วงที่ผ่านเซิร์ฟเวอร์ตัวกลาง สัญญาณว่าไม่ใช่ ถ้าเปิดหรือปิดก็เหมือนกัน น่าจะเป็นช่วงเน็ตหรือเครือข่ายของ ISP ถ้าเปิดแล้วดีขึ้น น่าจะเป็นปัญหาที่เส้นทางเดิมของ ISP (“เส้นทางวิ่งอ้อม”, “จุด peering แออัดช่วงพีค”) วิธีตรวจ ตรวจที่สภาพแวดล้อมฝั่งผู้เล่น
รายละเอียดเพิ่มเติม ในทางกลับกัน เมื่อเส้นทางของ ISP แย่ โปรแกรมลดปิงอาจอ้อมไปเส้นทางที่ดีกว่าจนปิงลดลง รายงานว่า “เปิดโปรแกรมลดปิงแล้วดีขึ้น” จึงเป็นเบาะแสของปัญหาเส้นทางของ ISP เช่น เส้นทางวิ่งอ้อมหรือความแออัดช่วงหัวค่ำ
แหล่งอ้างอิง 3 รายการ
L5 อุปกรณ์เครือข่ายในดาต้าเซ็นเตอร์
11 สาเหตุ · บทในฉบับหลัก
ID dc-firewall · ผู้รับผิดชอบหลัก อินฟราเครือข่าย (ทีมอินฟรา) · ร่วมกับ พัฒนาเซิร์ฟเวอร์ (ทีมพัฒนาเกม), พัฒนาไคลเอนต์ (ทีมพัฒนาเกม)
ไฟร์วอลล์บันทึกทุกการเชื่อมต่อที่ปล่อยผ่านไว้ในตารางเซสชันเพื่อติดตาม เมื่อตารางเต็มก็รับการเชื่อมต่อใหม่ไม่ได้
ทำไม จำนวนเซสชันชนขีดจำกัดเพราะการเชื่อมต่อทะลักหรือถูกโจมตี → ผลคือ ไม่มีช่องว่างให้บันทึกการเชื่อมต่อใหม่ จึงถูกปฏิเสธ → บนหน้าจอ คนที่พยายามเข้าใหม่เข้าเกมไม่ได้หรือโหลดไม่จบ และการเชื่อมต่อเดิมบางส่วนก็หลุด
อาการ เข้าเกมไม่ได้/โหลดไม่จบ , หลุด
ปัจจัย แพ็กเก็ตหาย
ใครเจอ ทั้งเซิร์ฟเวอร์
เกิดเมื่อไร หลังล็อกอิน/หลังปิดปรับปรุง, ตอนคนแห่มารวมกัน
ผู้รับผิดชอบ ผู้รับผิดชอบหลัก อินฟราเครือข่าย (ทีมอินฟรา) · ร่วมกับ พัฒนาเซิร์ฟเวอร์ (ทีมพัฒนาเกม), พัฒนาไคลเอนต์ (ทีมพัฒนาเกม)
งานฝั่งทีมพัฒนาเกม เซิร์ฟเวอร์: ใช้ระบบคิวล็อกอินคุมการเชื่อมต่อที่ทะลักเข้ามาพร้อมกัน, ใช้การเชื่อมต่อซ้ำเพื่อไม่ให้เปิดการเชื่อมต่อสั้น ๆ ซ้ำไปมา, เก็บกวาดการเชื่อมต่อที่ heartbeat ขาดไปก่อน (เพื่อไม่ให้การเชื่อมต่อที่ตายแล้วกินที่ในตารางเซสชันนาน) ไคลเอนต์: ส่ง heartbeat ทุกช่วงไม่เกินครึ่งหนึ่งของ idle timeout ที่สั้นที่สุด, เชื่อมต่อใหม่อัตโนมัติเมื่อหลุด โดยค่อย ๆ เพิ่มช่วงห่างของการลองใหม่และกระจายแบบสุ่ม (เพื่อไม่ให้แห่กลับมาพร้อมกันอีก)
งานฝั่งทีมอินฟรา เพิ่มขนาดตารางเซสชัน, เก็บกวาดการเชื่อมต่อที่จบเร็วให้ไว (ลดไทม์เอาต์ของเซสชันที่ปิดแล้ว), ถ้าจะลด idle timeout ของเซสชัน ให้แจ้งค่านั้นแก่ทีมพัฒนาเกมเพื่อปรับช่วง heartbeat ให้ตรงกัน, บล็อกการโจมตี, ตั้ง alert อัตราการใช้งานของจำนวนเซสชัน
บนกราฟ ชนเพดานแล้วแบนราบ · จำนวนเซสชันของไฟร์วอลล์, จำนวนการเชื่อมต่อใหม่ที่ล้มเหลว
จุดที่ต้องดู ดูกราฟจำนวนเซสชันพร้อมกันของไฟร์วอลล์คู่กับขีดจำกัดเซสชัน และหาใน log ของอุปกรณ์ว่ามีการทิ้งเพราะสร้างเซสชันไม่ได้หรือไม่ ถ้าเป็นไฟร์วอลล์ Linux ให้เทียบ nf_conntrack_count กับ nf_conntrack_max และดู “nf_conntrack: table full, dropping packet” ใน dmesg ถ้าเป็นอินสแตนซ์ AWS ให้ดู conntrack_allowance_exceeded ใน ethtool -S สัญญาณว่าใช่ ตั้งแต่จำนวนเซสชันแบนราบที่ขีดจำกัด การเชื่อมต่อใหม่ที่ล้มเหลวก็เพิ่มขึ้น พร้อมกับ log ที่สร้างเซสชันไม่สำเร็จหรือตัวนับการทิ้งที่เพิ่มขึ้น สัญญาณว่าไม่ใช่ ถ้าจำนวนเซสชันยังห่างจากขีดจำกัดมากแต่เข้าเกมไม่ได้ น่าจะเป็น “คิวรอเชื่อมต่อ (backlog) ล้น” หรือฝั่งเซิร์ฟเวอร์ล็อกอิน ถ้าหลุดเฉพาะการเชื่อมต่อที่ idle น่าจะเป็น “connection tracking ของ security group บนคลาวด์หมดอายุ” วิธีตรวจ ใช้เครื่องมือฝั่งอินฟรา (ไม่ต้องใช้โค้ดเกม)
แหล่งอ้างอิง 5 รายการ
ID dc-ddos · ผู้รับผิดชอบหลัก อินฟราเครือข่าย (ทีมอินฟรา) · ร่วมกับ พัฒนาเซิร์ฟเวอร์ (ทีมพัฒนาเกม)
เมื่อเบี่ยงทราฟฟิกไป scrubbing center เพื่อกันการโจมตี เส้นทางจะยาวขึ้น และบางครั้งระบบเข้าใจผิดว่าผู้เล่นปกติเป็นการโจมตีแล้วบล็อก
ทำไม หลังตรวจพบการโจมตี (หรือตลอดเวลา) ทราฟฟิกขาเข้าถูกเบี่ยงไป scrubbing center → ผลคือ เส้นทางยาวขึ้น และแพ็กเก็ตปกติบางส่วนถูกตัดสินว่าเป็นการโจมตี → บนหน้าจอ ปิงสูงขึ้นทั้งหมด, เฉพาะบางพื้นที่หรือบาง ISP ที่เข้าเกมไม่ได้
อาการ อินพุตดีเลย์ , เข้าเกมไม่ได้/โหลดไม่จบ , วาร์ป
ปัจจัย ความหน่วง, แพ็กเก็ตหาย
ใครเจอ ทั้งเซิร์ฟเวอร์, บางพื้นที่/บาง ISP
เกิดเมื่อไร ตอนคนแห่มารวมกัน, สุ่มเป็นครั้งคราว
ผู้รับผิดชอบ ผู้รับผิดชอบหลัก อินฟราเครือข่าย (ทีมอินฟรา) · ร่วมกับ พัฒนาเซิร์ฟเวอร์ (ทีมพัฒนาเกม)
งานฝั่งทีมพัฒนาเกม สรุปรูปแบบทราฟฟิกของเกม (พอร์ต, ขนาดแพ็กเก็ต, จำนวนแพ็กเก็ตต่อวินาที) แชร์ให้ทีมอินฟรา, รักษาขนาดแพ็กเก็ต UDP ไว้ไม่เกิน 1,200 ไบต์
งานฝั่งทีมอินฟรา ตั้งกฎป้องกันให้ตรงกับรูปแบบทราฟฟิกของเกม, มีจุด scrubbing แยกตามภูมิภาค, ลดขนาดแพ็กเก็ต TCP ในช่วง tunnel (ปรับ MSS), ตรวจ false positive จากอัตราการเชื่อมต่อล้มเหลวแยกตามพื้นที่และ ISP
ตัวเลขที่ควรรู้ ถ้าจุด scrubbing อยู่ในประเทศเดียวกัน จะเพิ่มไม่กี่ ms ถ้าผ่านจุดในประเทศอื่น จะเพิ่ม 30–100 ms ขึ้นไป ปกติเฉพาะขาเข้าที่อ้อม ส่วนการตอบกลับของเซิร์ฟเวอร์ออกไปตรง ๆ ถ้ารับทราฟฟิกที่กรองแล้วกลับมาทาง tunnel ขนาดที่ส่งได้ในครั้งเดียว (MTU) ก็ลดลง และอาจกลายเป็นปัญหาที่เฉพาะแพ็กเก็ตใหญ่หายไป
บนกราฟ ขึ้นเป็นขั้นบันไดจากจุดหนึ่ง · RTT (ปิง), อัตราการเชื่อมต่อล้มเหลวแยกตามพื้นที่/ISP
จุดที่ต้องดู วางประวัติการเริ่มและหยุดเบี่ยงทราฟฟิก (scrubbing) และ log การบล็อกของอุปกรณ์หรือบริการป้องกัน ไว้บนแกนเวลาเดียวกับกราฟ RTT และอัตราการเชื่อมต่อล้มเหลวแยกตามพื้นที่และ ISP แล้วใช้ mtr หรือ traceroute จากพื้นที่ที่มีปัญหาดูว่ามีจุด scrubbing แทรกอยู่ในเส้นทางหรือไม่ สัญญาณว่าใช่ เมื่อเปิดการเบี่ยงทราฟฟิก RTT ขึ้นไปหนึ่งขั้นและอยู่ระดับนั้น แล้วกลับมาเมื่อปิด หรือ log การบล็อกมี IP ของผู้เล่นปกติ และอัตราการเชื่อมต่อล้มเหลวสูงขึ้นเฉพาะพื้นที่หรือ ISP นั้น สัญญาณว่าไม่ใช่ ถ้า RTT สูงขึ้นในเวลาที่ไม่มีประวัติการเบี่ยงหรือบล็อก น่าจะเป็น “เส้นทางวิ่งอ้อม” หรือ “เส้นทาง BGP เปลี่ยนและ converge ใหม่” ถ้าหายเฉพาะแพ็กเก็ตใหญ่ น่าจะเป็น “MTU ไม่ตรงกัน (เฉพาะแพ็กเก็ตใหญ่ที่หาย)” วิธีตรวจ ใช้เครื่องมือฝั่งอินฟรา (ไม่ต้องใช้โค้ดเกม)
แหล่งอ้างอิง 2 รายการ
ID dc-lb-idle · ผู้รับผิดชอบหลัก อินฟราเครือข่าย (ทีมอินฟรา) · ร่วมกับ พัฒนาไคลเอนต์ (ทีมพัฒนาเกม), พัฒนาเซิร์ฟเวอร์ (ทีมพัฒนาเกม)
โหลดบาลานเซอร์ลบการเชื่อมต่อที่ idle ทิ้งหลังผ่านไประยะหนึ่ง ฝั่งเกมยังคิดว่าการเชื่อมต่อยังอยู่ จนกระทั่งหลุด
ทำไม ผู้เล่นไม่ส่งแพ็กเก็ตใด ๆ อยู่พักหนึ่ง (เปิดหน้าต่างสนทนา, ไม่อยู่หน้าจอ) → ผลคือ โหลดบาลานเซอร์เก็บกวาดการเชื่อมต่อที่ idle (ค่าเริ่มต้นที่พบบ่อย 60–350 วินาที) → บนหน้าจอ หลุดทันทีที่กลับมาขยับอีกครั้ง
อาการ หลุด
ปัจจัย แพ็กเก็ตหาย
ใครเจอ เราคนเดียว, ทั้งเซิร์ฟเวอร์
เกิดเมื่อไร หลังอยู่เฉย ๆ สักพัก
ผู้รับผิดชอบ ผู้รับผิดชอบหลัก อินฟราเครือข่าย (ทีมอินฟรา) · ร่วมกับ พัฒนาไคลเอนต์ (ทีมพัฒนาเกม), พัฒนาเซิร์ฟเวอร์ (ทีมพัฒนาเกม)
งานฝั่งทีมพัฒนาเกม ไคลเอนต์: ส่ง heartbeat ทุกช่วงไม่เกินครึ่งหนึ่งของ idle timeout ที่สั้นที่สุด (ถ้าอยู่หลัง ALB ที่ 60 วินาที ก็ไม่เกิน 30 วินาที), เชื่อมต่อใหม่อัตโนมัติเมื่อหลุด เซิร์ฟเวอร์: ตอบ heartbeat และถ้าไม่ได้รับตามเวลาที่กำหนดให้เก็บกวาดการเชื่อมต่อก่อน, ใช้ session token รับต่อ
งานฝั่งทีมอินฟรา ตรวจค่า idle timeout ของโหลดบาลานเซอร์ในเส้นทางแล้วแชร์ให้ทีมพัฒนาเกม และเพิ่มค่าถ้าจำเป็น
ตัวเลขที่ควรรู้ ค่าเริ่มต้นของ AWS ALB คือ 60 วินาที, NLB คือ TCP 350 วินาทีและ UDP 120 วินาที, Azure Load Balancer คือ TCP 4 นาที ค่า TCP ของ ALB และ NLB ปรับได้ แต่ UDP 120 วินาทีของ NLB ปรับไม่ได้ เมื่อครบเวลา ALB จะปิดการเชื่อมต่อฝั่งเซิร์ฟเวอร์ด้วย ส่วน NLB ลบทิ้งเงียบ ๆ การเชื่อมต่อจึงมักยังเหลืออยู่ฝั่งเซิร์ฟเวอร์โดยที่เซิร์ฟเวอร์ไม่รู้
บนกราฟ การเชื่อมต่อหลุดพร้อมกัน · จำนวนครั้งที่หลุด, ระยะเวลา idle ก่อนหลุด
จุดที่ต้องดู ตรวจค่า idle timeout ที่ตั้งไว้ของโหลดบาลานเซอร์ในเส้นทาง แล้วรวบรวมเวลาตั้งแต่แพ็กเก็ตสุดท้ายจนหลุดของแต่ละการเชื่อมต่อที่หลุด ถ้าเป็น AWS NLB ให้ดู TCP_ELB_Reset_Count (จำนวน RST ที่โหลดบาลานเซอร์ส่ง) ใน CloudWatch ด้วย สัญญาณว่าใช่ ระยะเวลา idle ของการเชื่อมต่อที่หลุดกระจุกอยู่หลังค่าที่ตั้งไว้พอดี (ALB 60 วินาที, NLB TCP 350 วินาที ฯลฯ) และทำซ้ำได้เมื่ออยู่เฉย ๆ นานกว่านั้นแล้วขยับ ถ้าเป็น NLB TCP_ELB_Reset_Count จะเพิ่มในเวลานั้น สัญญาณว่าไม่ใช่ ถ้าหลุดโดยไม่เกี่ยวกับระยะเวลา idle ก็ไม่ใช่สาเหตุนี้ ถ้าเซิร์ฟเวอร์ที่ผู้เล่นเชื่อมต่อตรงโดยไม่มีโหลดบาลานเซอร์หลุดกระจุกแถว 350 วินาที น่าจะเป็น “connection tracking ของ security group บนคลาวด์หมดอายุ” ถ้าเป็นฝั่งเราเตอร์ที่บ้านผู้เล่น น่าจะเป็น “NAT mapping หมดอายุ” วิธีตรวจ ใช้เครื่องมือฝั่งอินฟรา (ไม่ต้องใช้โค้ดเกม)
แหล่งอ้างอิง 4 รายการ
ID dc-cloud-conntrack · ผู้รับผิดชอบหลัก อินฟราเซิร์ฟเวอร์ (ทีมอินฟรา) · ร่วมกับ พัฒนาไคลเอนต์ (ทีมพัฒนาเกม), พัฒนาเซิร์ฟเวอร์ (ทีมพัฒนาเกม)
ไฟร์วอลล์ที่ผูกกับเซิร์ฟเวอร์บนคลาวด์ (security group) ก็ติดตามการเชื่อมต่อเช่นกัน และรายการที่ติดตามของการเชื่อมต่อที่ idle จะหมดอายุหลังเวลาที่กำหนด แม้เป็นเซิร์ฟเวอร์ที่ผู้เล่นเชื่อมต่อตรงโดยไม่มีโหลดบาลานเซอร์ ผู้เล่นที่อยู่เฉย ๆ ก็อาจหลุดได้
ทำไม security group ถูกตั้งค่าในแบบที่ติดตามการเชื่อมต่อของเกม (อนุญาตเฉพาะบาง IP, จำกัดกฎขาออก, ผ่าน NLB ฯลฯ) → ผลคือ รายการที่ติดตามของการเชื่อมต่อที่ idle อยู่พักหนึ่งหมดอายุ แล้ว security group ทิ้งแพ็กเก็ตที่มาหลังจากนั้นเงียบ ๆ → บนหน้าจอ กลับมาขยับหลังจากไม่อยู่หน้าจอ แล้วไม่มีการตอบสนองจนหลุด โปรแกรมเซิร์ฟเวอร์ไม่รู้ตัวอยู่นาน
อาการ หลุด
ปัจจัย แพ็กเก็ตหาย
ใครเจอ เราคนเดียว, ทั้งเซิร์ฟเวอร์
เกิดเมื่อไร หลังอยู่เฉย ๆ สักพัก
ผู้รับผิดชอบ ผู้รับผิดชอบหลัก อินฟราเซิร์ฟเวอร์ (ทีมอินฟรา) · ร่วมกับ พัฒนาไคลเอนต์ (ทีมพัฒนาเกม), พัฒนาเซิร์ฟเวอร์ (ทีมพัฒนาเกม)
งานฝั่งทีมพัฒนาเกม ไคลเอนต์: ส่ง heartbeat ทุกช่วงไม่เกินครึ่งหนึ่งของ idle timeout ที่สั้นที่สุด (ถ้า TCP 350 วินาที ก็ไม่เกิน 175 วินาที ถ้า UDP stream 180 วินาที ก็ไม่เกิน 90 วินาที), เชื่อมต่อใหม่อัตโนมัติเมื่อหลุด เซิร์ฟเวอร์: ตอบ heartbeat และถ้าไม่ได้รับตามเวลาที่กำหนดให้เก็บกวาดการเชื่อมต่อก่อน, ใช้ session token รับต่อ
งานฝั่งทีมอินฟรา ตรวจเวลา connection tracking ของอินสแตนซ์ (TcpEstablishedTimeout) และเพิ่มถ้าจำเป็น (UDP สูงสุด 180 วินาที จึงเพิ่มไม่ได้), ทบทวนการตั้ง security group แบบที่ไม่เกิดการติดตาม (พอร์ตเกมอนุญาตทุก IP, กฎขาออกอนุญาตทั้งหมด ส่วนการเชื่อมต่อที่ผ่าน NLB ยังถูกติดตามอยู่ดี), ทดสอบ idle เมื่อย้ายไปอินสแตนซ์รุ่นใหม่
ตัวเลขที่ควรรู้ สำหรับ AWS อินสแตนซ์ประเภท Nitro v6 จะลบรายการที่ติดตามของการเชื่อมต่อ TCP ที่ idle หลัง 350 วินาทีเป็นค่าเริ่มต้น (ประเภทอื่น 5 วัน) ส่วน UDP ค่าเริ่มต้นคือ 180 วินาทีสำหรับ flow ที่มีคำขอและการตอบกลับไปมาหลายครั้ง (stream) และ 30 วินาทีสำหรับ flow ที่ไปทางเดียวหรือมีคำขอและการตอบกลับแค่ครั้งเดียว
บนกราฟ การเชื่อมต่อหลุดพร้อมกัน · จำนวนครั้งที่หลุด, ระยะเวลา idle ก่อนหลุด
จุดที่ต้องดู ตรวจการตั้งเวลา connection tracking ของอินสแตนซ์และกฎของ security group (ว่าเป็นแบบที่เกิดการติดตามหรือไม่) แล้วรวบรวมระยะเวลา idle ของการเชื่อมต่อที่หลุด ทันทีหลังหลุด ใช้ ss -tnoi บนเซิร์ฟเวอร์ดูว่าการเชื่อมต่อนั้นยังเป็น ESTABLISHED ตัวจับเวลาส่งซ้ำ (timer:(on,…)) ทำงานอยู่ และ backoff เพิ่มขึ้นหรือไม่ สัญญาณว่าใช่ ระยะเวลา idle ของการเชื่อมต่อที่หลุดกระจุกอยู่หลัง TCP 350 วินาที, UDP stream 180 วินาที หรือ UDP ทางเดียว 30 วินาทีพอดี และซ็อกเก็ตฝั่งเซิร์ฟเวอร์ยังเป็น ESTABLISHED โดยไม่รู้ว่าการเชื่อมต่อขาดไปแล้ว (ถ้าเซิร์ฟเวอร์มีข้อมูลต้องส่ง ก็จะส่งซ้ำวนไปเรื่อย ๆ) สัญญาณว่าไม่ใช่ ถ้า security group ตั้งแบบที่ไม่ติดตาม (พอร์ตเกมอนุญาตทุก IP, กฎขาออกอนุญาตทั้งหมด, ไม่ผ่าน NLB) ก็ไม่ใช่สาเหตุนี้ ถ้าผ่าน NLB ให้เทียบค่ากับ “idle timeout ของโหลดบาลานเซอร์” วิธีตรวจ ใช้เครื่องมือฝั่งอินฟรา (ไม่ต้องใช้โค้ดเกม)
แหล่งอ้างอิง 3 รายการ
ID dc-nat-gateway · ผู้รับผิดชอบหลัก อินฟราเครือข่าย (ทีมอินฟรา) · ร่วมกับ พัฒนาเซิร์ฟเวอร์ (ทีมพัฒนาเกม)
การเชื่อมต่อที่เซิร์ฟเวอร์ใน private subnet ออกไปภายนอก (ระบบยืนยันตัวตนของแพลตฟอร์ม, ระบบชำระเงิน, API ภายนอก) จะผ่าน NAT gateway ซึ่งแปลง IP และพอร์ตก่อนส่งออก ถ้าการเชื่อมต่อพร้อมกันไปยังปลายทางเดียวกันเกินขีดจำกัดพอร์ตของ gateway การเชื่อมต่อใหม่จะล้มเหลว
ทำไม เซิร์ฟเวอร์เปิดการเชื่อมต่อสั้น ๆ จำนวนมากไปยัง IP ภายนอกเดียวกัน เช่น ระบบยืนยันตัวตนของแพลตฟอร์มหรือระบบชำระเงิน หรือเปิดการเชื่อมต่อทิ้งไว้นาน → ผลคือ NAT gateway จัดสรรพอร์ตต้นทางสำหรับปลายทางนั้นเพิ่มไม่ได้ การเชื่อมต่อใหม่จึงล้มเหลว → บนหน้าจอ ในเกมปกติดี แต่เฉพาะฟีเจอร์ที่เรียกภายนอก เช่น ล็อกอิน ชำระเงิน หรือแจกของรางวัล ที่ล้มเหลวหรือช้า (เข้าเกมไม่ได้/โหลดไม่จบ, กดไม่ติด/โรลแบ็ค)
อาการ เข้าเกมไม่ได้/โหลดไม่จบ , กดไม่ติด/โรลแบ็ค
ปัจจัย แพ็กเก็ตหาย, ความหน่วง
ใครเจอ เฉพาะบางฟีเจอร์, ทั้งเซิร์ฟเวอร์
เกิดเมื่อไร หลังล็อกอิน/หลังปิดปรับปรุง, ช่วงพีคหัวค่ำ, ตอนคนแห่มารวมกัน
ผู้รับผิดชอบ ผู้รับผิดชอบหลัก อินฟราเครือข่าย (ทีมอินฟรา) · ร่วมกับ พัฒนาเซิร์ฟเวอร์ (ทีมพัฒนาเกม)
งานฝั่งทีมพัฒนาเกม ใช้การเชื่อมต่อกับ API ภายนอกซ้ำ (HTTP keep-alive, connection pool) และไม่เปิดการเชื่อมต่อใหม่ทุกคำขอ, การเชื่อมต่อ idle ที่เก็บไว้ใน pool ให้ส่ง keepalive ถี่กว่า idle timeout ของ NAT (AWS 350 วินาที) หรือปิดก่อน, เมื่อล้มเหลวให้ค่อย ๆ เพิ่มช่วงห่างของการลองใหม่และกระจายแบบสุ่ม, บันทึกอัตราล้มเหลวและความหน่วงแยกตามการเรียกภายนอกแต่ละแบบ
งานฝั่งทีมอินฟรา เพิ่ม IP ให้ NAT gateway (AWS public NAT gateway ผูก Elastic IP ได้แค่ 2 ตัวเป็นค่าเริ่มต้น ถ้าต้องการมากกว่านั้นต้องขอเพิ่มโควตา), แยก gateway ตาม availability zone และ subnet, ตั้ง alert เมตริกการจัดสรรพอร์ตล้มเหลว (AWS ErrorPortAllocation, สถานะ Failed ของ Azure SNAT Connection Count, OUT_OF_RESOURCES ของ Google Cloud dropped_sent_packets_count), สำหรับ Google Cloud NAT ให้เพิ่มจำนวนพอร์ตขั้นต่ำต่อ VM หรือใช้ dynamic port allocation
ตัวเลขที่ควรรู้ AWS NAT gateway เปิดการเชื่อมต่อพร้อมกันไปยังปลายทางเดียวกัน (IP, พอร์ต, โปรโตคอล) ได้สูงสุด 55,000 การเชื่อมต่อต่อ IP หนึ่งตัว และเพิ่มได้ด้วยการผูก IP สูงสุด 8 ตัว การเชื่อมต่อที่เงียบไป 350 วินาทีจะถูกลบ และแพ็กเก็ตที่ส่งมาทางการเชื่อมต่อนั้นหลังจากนั้นจะได้ RST กลับไป Azure NAT Gateway มี SNAT port 64,512 พอร์ตต่อ public IP หนึ่งตัว (IP สูงสุด 16 ตัว) ส่วน Google Cloud NAT แบ่ง 64,512 พอร์ตต่อ NAT IP หนึ่งตัวให้แต่ละ VM และค่าเริ่มต้นของพอร์ตขั้นต่ำต่อ VM คือ 64 พอร์ต (static allocation) ถ้าใช้ค่าเริ่มต้น VM หนึ่งเครื่องจึงมักเปิดการเชื่อมต่อพร้อมกันไปยังปลายทางเดียวกันได้แค่ 64 การเชื่อมต่อ
บนกราฟ ชนเพดานแล้วแบนราบ · จำนวนการเชื่อมต่อพร้อมกันของ NAT gateway, จำนวนการจัดสรรพอร์ตล้มเหลว
จุดที่ต้องดู สำหรับ AWS ดูเมตริก NAT gateway ใน CloudWatch ได้แก่ ErrorPortAllocation, ActiveConnectionCount และ PacketsDropCount (Azure ดู SNAT Connection Count ที่กรองสถานะ Failed และ Dropped Packets, Google Cloud ดู dropped_sent_packets_count ที่ reason เป็น OUT_OF_RESOURCES) เทียบกับเวลาที่เซิร์ฟเวอร์เกมเรียกภายนอกล้มเหลว สัญญาณว่าใช่ ในเวลาที่เรียกภายนอกล้มเหลว ErrorPortAllocation (Azure คือ SNAT Connection Count สถานะ Failed, Google Cloud คือการทิ้งแบบ OUT_OF_RESOURCES) มีค่ามากกว่า 0 และความล้มเหลวกระจุกที่การเรียกไปยังปลายทางหนึ่งหรือสองแห่งที่มีการเชื่อมต่อมาก เช่น เซิร์ฟเวอร์ยืนยันตัวตนหรือชำระเงิน สัญญาณว่าไม่ใช่ ถ้าการจัดสรรพอร์ตล้มเหลวเป็น 0 แต่ connect ของเซิร์ฟเวอร์เกมล้มเหลวด้วย EADDRNOTAVAIL และ TIME_WAIT ใกล้เต็มช่วง ephemeral port น่าจะเป็น “ephemeral port หมดในการเชื่อมต่อระหว่างเซิร์ฟเวอร์” ถ้าเชื่อมต่อได้แต่ตอบช้า น่าจะเป็น “การพึ่งพาเซอร์วิสภายนอก” วิธีตรวจ ใช้เครื่องมือฝั่งอินฟรา (ไม่ต้องใช้โค้ดเกม)
รายละเอียดเพิ่มเติม ต่างจาก “ephemeral port หมดในการเชื่อมต่อระหว่างเซิร์ฟเวอร์” ที่ ephemeral port ของเซิร์ฟเวอร์เครื่องเดียวหมด ขีดจำกัดนี้อยู่ที่ NAT gateway และเซิร์ฟเวอร์ทุกเครื่องหลัง gateway ใช้ร่วมกัน (Google Cloud NAT แบ่งให้แต่ละ VM) ถ้า TIME_WAIT และช่วง ephemeral port ฝั่งเซิร์ฟเวอร์ยังเหลือ แต่เฉพาะการเรียกภายนอกที่ล้มเหลว ก็น่าจะเป็นสาเหตุนี้ พอร์ตของการเชื่อมต่อที่ปิดแล้วก็ไม่ถูกนำกลับมาใช้กับปลายทางเดียวกันทันที (Azure มี cooldown, Google Cloud ใช้ไม่ได้ระหว่าง TIME_WAIT) ยิ่งเปิดการเชื่อมต่อสั้น ๆ ซ้ำ ๆ ก็ยิ่งชนขีดจำกัดเร็ว
แหล่งอ้างอิง 7 รายการ NAT gateway basics AWS การเชื่อมต่อพร้อมกันไปยังปลายทางเดียวกัน (IP, พอร์ต, โปรโตคอลปลายทาง) 55,000 การเชื่อมต่อต่อ IPv4 หนึ่งตัว เพิ่มได้ด้วยการผูก IP สูงสุด 8 ตัว (Elastic IP ของ public NAT gateway ค่าเริ่มต้น 2 ตัว เพิ่มได้ด้วยการขอเพิ่มโควตา), แบนด์วิดท์ขยายเองจาก 5 Gbps ถึง 100 Gbps และปริมาณงานขยายเองจาก 1 ล้านถึง 10 ล้านแพ็กเก็ตต่อวินาที ถ้าเกินขีดนั้นแพ็กเก็ตจะถูกทิ้ง NAT gateway metrics and dimensions AWS ErrorPortAllocation: จำนวนครั้งที่จัดสรรพอร์ตต้นทางไม่ได้ (ถ้ามากกว่า 0 แปลว่าการเชื่อมต่อพร้อมกันมากเกินไป), ActiveConnectionCount, IdleTimeoutCount (การเชื่อมต่อที่ถูกเก็บกวาดเพราะ idle 350 วินาที), PacketsDropCount Troubleshoot NAT gateways AWS ถ้า idle 350 วินาที การเชื่อมต่อจะหมดอายุ และถ้าส่งต่อจะได้ RST กลับ, แนะนำ keepalive ที่สั้นกว่า 350 วินาที, ถ้าชนขีดจำกัดการเชื่อมต่อ ให้แยก gateway ตาม availability zone, เพิ่ม IP หรือลดจำนวนการเชื่อมต่อ Source Network Address Translation (SNAT) with Azure NAT Gateway Microsoft Azure SNAT port 64,512 พอร์ตต่อ public IP หนึ่งตัว (IP สูงสุด 16 ตัว), การเชื่อมต่อแต่ละรายการไปยังปลายทางเดียวกันต้องใช้พอร์ตต่างกัน, พอร์ตที่ปิดแล้วมี cooldown ก่อนนำกลับมาใช้กับปลายทางเดียวกัน Metrics and alerts for Azure NAT Gateway Microsoft Azure ถ้า SNAT Connection Count ที่กรองสถานะ Failed มากกว่า 0 อาจเป็นไปได้ว่า SNAT port หมด, Dropped Packets IP addresses and ports Google Cloud TCP และ UDP อย่างละ 64,512 พอร์ตต่อ NAT IP หนึ่งตัว, ค่าเริ่มต้นของพอร์ตขั้นต่ำต่อ VM คือ 64 (static allocation) และ 32 (dynamic allocation), จำนวนพอร์ตที่จองให้ VM จำกัดจำนวนการเชื่อมต่อพร้อมกันไปยังปลายทางเดียวกัน, การเชื่อมต่อที่ปิดแล้วใช้ไม่ได้ระหว่าง TIME_WAIT Logs and metrics Google Cloud reason OUT_OF_RESOURCES ของ dropped_sent_packets_count: แพ็กเก็ตที่ถูกทิ้งเพราะ NAT IP หรือพอร์ตไม่พอ
ID dc-lb-imbalance · ผู้รับผิดชอบหลัก อินฟราเครือข่าย (ทีมอินฟรา) · ร่วมกับ พัฒนาเซิร์ฟเวอร์ (ทีมพัฒนาเกม)
การเชื่อมต่อไปกองที่เซิร์ฟเวอร์เครื่องเดียว หรือยังส่งคนไปเซิร์ฟเวอร์ที่ตายแล้วอยู่เรื่อย ๆ
ทำไม กฎการกระจายไม่เหมาะ หรือ health check มองไม่เห็นสถานะจริง → ผลคือ เซิร์ฟเวอร์เครื่องเดียวโหลดเกิน หรือพยายามเชื่อมต่อไปเซิร์ฟเวอร์ที่ตายแล้ว → บนหน้าจอ เฉพาะบางแชนแนลหรือบางคนที่เป็นสโลว์โมชั่น, เข้าเกมไม่ได้หรือโหลดไม่จบ
อาการ สโลว์โมชั่น , เข้าเกมไม่ได้/โหลดไม่จบ
ปัจจัย การหยุดชะงัก, แพ็กเก็ตหาย
ใครเจอ บางจุด/บางแชนแนล
เกิดเมื่อไร หลังล็อกอิน/หลังปิดปรับปรุง, ตอนคนแห่มารวมกัน
ผู้รับผิดชอบ ผู้รับผิดชอบหลัก อินฟราเครือข่าย (ทีมอินฟรา) · ร่วมกับ พัฒนาเซิร์ฟเวอร์ (ทีมพัฒนาเกม)
งานฝั่งทีมพัฒนาเกม ทำ health check ที่ตอบคำขอตรวจของโหลดบาลานเซอร์ตามสถานะเกมจริง (ทิกยังเดิน, การเชื่อมต่อ DB), ส่งค่าโหลดของเซิร์ฟเวอร์ไปด้วย
งานฝั่งทีมอินฟรา เปลี่ยน health check เป็นแบบที่ตรวจการตอบสนองจริงของเกม, กระจายโหลดตามโหลดของเซิร์ฟเวอร์, มอนิเตอร์ความต่างของจำนวนการเชื่อมต่อในแต่ละเซิร์ฟเวอร์
บนกราฟ สูงเฉพาะบางกลุ่ม · จำนวนการเชื่อมต่อ/อัตราการใช้ CPU แยกตามเซิร์ฟเวอร์
จุดที่ต้องดู ซ้อนจำนวนการเชื่อมต่อ (ss -s) และอัตราการใช้ CPU ของแต่ละเซิร์ฟเวอร์หลังโหลดบาลานเซอร์ไว้ในกราฟเดียว แล้วเทียบสถานะ health ของ target ในโหลดบาลานเซอร์ (AWS ดู HealthyHostCount และ UnHealthyHostCount ใน CloudWatch) กับสถานะจริงของเซิร์ฟเวอร์เกม สัญญาณว่าใช่ มีเซิร์ฟเวอร์หนึ่งหรือสองเครื่องที่จำนวนการเชื่อมต่อและ CPU สูงกว่าเครื่องอื่นมาก หรือเซิร์ฟเวอร์ที่ทิกหยุดไปแล้วยังมีสถานะ health เป็น “healthy” และยังรับการเชื่อมต่อใหม่อยู่เรื่อย ๆ สัญญาณว่าไม่ใช่ ถ้าจำนวนการเชื่อมต่อแต่ละเซิร์ฟเวอร์เท่า ๆ กันแต่ช้าเฉพาะแชนแนลเดียว น่าจะเป็นโหลดภายในแชนแนลนั้น (“พื้นที่ที่รันบนเธรดเดียวโหลดเกิน (hotspot)”) วิธีตรวจ ใช้เครื่องมือฝั่งอินฟรา (ไม่ต้องใช้โค้ดเกม)
กรณีจริง AWS 2025: DNS ของ DynamoDB ใน AWS us-east-1 ขัดข้อง และการกู้คืนที่ยืดเยื้อ
แหล่งอ้างอิง 3 รายการ
ID dc-microburst · ผู้รับผิดชอบหลัก พัฒนาเซิร์ฟเวอร์ (ทีมพัฒนาเกม) · ร่วมกับ อินฟราเครือข่าย (ทีมอินฟรา), อินฟราเซิร์ฟเวอร์ (ทีมอินฟรา)
ถ้าเซิร์ฟเวอร์หลายเครื่องส่งแพ็กเก็ตถึงผู้เล่นหลายพันคนพร้อมกันในชั่วขณะเดียว บัฟเฟอร์ขนาดเล็กของพอร์ตสวิตช์ที่ทราฟฟิกนั้นไหลมารวมกันจะล้นภายในไม่ถึง 1 ms
ทำไม เวิลด์บอสเกิดหรือมีสกิลขนาดใหญ่ หรือทิกของเซิร์ฟเวอร์หลายเครื่องตรงกันพอดีจนส่งออกพร้อมกัน → ผลคือ บัฟเฟอร์ (หลายร้อย KB ถึงหลาย MB ต่อพอร์ต) ตรงจุดที่หลายพอร์ตไหลเข้าพอร์ตเดียว หรือจุดที่ข้อมูลไหลจากพอร์ตเร็วไปพอร์ตช้า เต็มในชั่วขณะ → บนหน้าจอ แพ็กเก็ตบางส่วนถูกทิ้ง หลายคนวาร์ปหรือสกิลไม่ออกพร้อมกัน
อาการ วาร์ป , กดไม่ติด/โรลแบ็ค
ปัจจัย แพ็กเก็ตหาย
ใครเจอ บางจุด/บางแชนแนล
เกิดเมื่อไร ตอนคนแห่มารวมกัน
ผู้รับผิดชอบ ผู้รับผิดชอบหลัก พัฒนาเซิร์ฟเวอร์ (ทีมพัฒนาเกม) · ร่วมกับ อินฟราเครือข่าย (ทีมอินฟรา), อินฟราเซิร์ฟเวอร์ (ทีมอินฟรา)
งานฝั่งทีมพัฒนาเกม กระจายการส่งให้สม่ำเสมอภายในทิก (pacing), เหลื่อมเวลาเริ่มทิกของแต่ละเซิร์ฟเวอร์เล็กน้อย
งานฝั่งทีมอินฟรา เครือข่าย: ใช้สวิตช์บัฟเฟอร์ใหญ่, กระจายทราฟฟิก (วางเซิร์ฟเวอร์แยกไปหลายสวิตช์และหลายพอร์ต), เฝ้าดูตัวนับการทิ้งแยกตามพอร์ตสวิตช์ เครื่องเซิร์ฟเวอร์/OS: จำกัดความเร็วส่งรวมของเซิร์ฟเวอร์ (shaper ของ Linux tc)
ตัวเลขที่ควรรู้ พอร์ต 10 Gbps ส่งข้อมูลได้ประมาณ 1.25 MB ใน 1 ms ถ้าทราฟฟิกจากสองพอร์ตไหลเข้าพอร์ตเดียวพร้อมกัน ข้อมูลจะกองเพิ่ม 1.25 MB ทุก 1 ms แม้อัตราการใช้งานเฉลี่ย 1 วินาทีจะอยู่ที่ 10% ในระดับ 1 ms ก็อาจล้นได้
บนกราฟ สูงตามจำนวนคนและโหลด · จำนวนการทิ้งขาออกของพอร์ตสวิตช์
จุดที่ต้องดู เก็บตัวนับการทิ้งขาออก (ifOutDiscards หรือ output drops แล้วแต่อุปกรณ์) ของพอร์ตสวิตช์ที่เซิร์ฟเวอร์ต่ออยู่และของพอร์ตที่ทราฟฟิกนั้นไหลมารวม ด้วยช่วงเวลาสั้นที่สุดเท่าที่ทำได้ แล้วเทียบกับเวลาที่บอสเกิดหรือมีการต่อสู้ขนาดใหญ่ ดูแค่กราฟอัตราการใช้งานเฉลี่ย 1 วินาทีหรือ 1 นาทีจะมองไม่เห็น สัญญาณว่าใช่ อัตราการใช้งานเฉลี่ยต่ำ แต่ทุกครั้งที่คนไปรวมกันที่จุดเดียว การทิ้งขาออกจะเพิ่ม และตอนนั้นผู้เล่นหลายคนแจ้งพร้อมกันว่าวาร์ปหรือสกิลไม่ออก สัญญาณว่าไม่ใช่ ถ้าการทิ้งเพิ่มต่อเนื่องในช่วงที่อัตราการใช้งานเฉลี่ยสูง น่าจะเป็น “ลิงก์ของดาต้าเซ็นเตอร์เต็ม” ถ้า input error (CRC) เพิ่ม น่าจะเป็น “สายเสีย/พอร์ตมี error” วิธีตรวจ ใช้เครื่องมือฝั่งอินฟรา (ไม่ต้องใช้โค้ดเกม)
แหล่งอ้างอิง 3 รายการ
ID dc-uplink · ผู้รับผิดชอบหลัก อินฟราเครือข่าย (ทีมอินฟรา) · ร่วมกับ อินฟราเซิร์ฟเวอร์ (ทีมอินฟรา)
ถ้าการแจกจ่ายแพตช์ การส่ง log หรือการสำรองข้อมูล ใช้ลิงก์เดียวกับเกม ลิงก์จะเต็ม
ทำไม การส่งข้อมูลขนาดใหญ่กินลิงก์เดียวกัน → ผลคือ คิวในลิงก์และแพ็กเก็ตหายเพิ่มขึ้น → บนหน้าจอ ปิงสูงขึ้นทั้งเซิร์ฟเวอร์และวาร์ป
อาการ อินพุตดีเลย์ , วาร์ป
ปัจจัย ความหน่วง, แพ็กเก็ตหาย
ใครเจอ ทั้งเซิร์ฟเวอร์
เกิดเมื่อไร เป็นรอบสม่ำเสมอ, ตอนคนแห่มารวมกัน
ผู้รับผิดชอบ ผู้รับผิดชอบหลัก อินฟราเครือข่าย (ทีมอินฟรา) · ร่วมกับ อินฟราเซิร์ฟเวอร์ (ทีมอินฟรา)
งานฝั่งทีมอินฟรา เครือข่าย: ให้ความสำคัญกับทราฟฟิกเกมก่อน (QoS), แยกลิงก์สำหรับส่งข้อมูลขนาดใหญ่, ตั้ง alert อัตราการใช้งานลิงก์ เครื่องเซิร์ฟเวอร์/OS: จำกัดความเร็วการสำรองข้อมูล การส่ง log และการ deploy แล้วรันในช่วงที่คนน้อย
บนกราฟ ชนเพดานแล้วแบนราบ · อัตราการใช้งานลิงก์, RTT (ปิง)
จุดที่ต้องดู วางอัตราการใช้งาน (คำนวณจาก SNMP ifHCInOctets และ ifHCOutOctets) และการทิ้งขาออก (ifOutDiscards) ของอินเทอร์เฟซลิงก์ดาต้าเซ็นเตอร์ (uplink) ไว้บนแกนเวลาเดียวกับตารางการสำรองข้อมูล การ deploy และการส่ง log สัญญาณว่าใช่ ในเวลาที่อัตราการใช้งานลิงก์ชนขีดจำกัดแบนด์วิดท์จนแบนราบ RTT ของทั้งเซิร์ฟเวอร์และการทิ้งสูงขึ้น และเวลานั้นตรงกับงานส่งข้อมูลขนาดใหญ่ สัญญาณว่าไม่ใช่ ถ้าอัตราการใช้งานระดับนาทียังห่างจากขีดจำกัดมากแต่มีการทิ้ง น่าจะเป็น “microburst ที่สวิตช์” วิธีตรวจ ใช้เครื่องมือฝั่งอินฟรา (ไม่ต้องใช้โค้ดเกม)
แหล่งอ้างอิง 3 รายการ
ID dc-failover · ผู้รับผิดชอบหลัก อินฟราเครือข่าย (ทีมอินฟรา) · ร่วมกับ พัฒนาเซิร์ฟเวอร์ (ทีมพัฒนาเกม), พัฒนาไคลเอนต์ (ทีมพัฒนาเกม)
ระหว่างไม่กี่วินาทีที่เราเตอร์หรือไฟร์วอลล์ตัวหนึ่งเสียแล้วสลับไปใช้อุปกรณ์สำรอง (failover) ทุกคนจะค้างพร้อมกัน
ทำไม อุปกรณ์เสียหรืออยู่ระหว่างซ่อมบำรุง จึงสลับไปใช้อุปกรณ์สำรอง → ผลคือ การสลับใช้เวลาหลายวินาที ถ้าข้อมูลเซสชันไม่ได้ซิงก์ไว้ การเชื่อมต่อจะถูกรีเซ็ต → บนหน้าจอ ผู้เล่นทุกคนในเซิร์ฟเวอร์ค้างพร้อมกัน, หลุดจำนวนมาก
อาการ ค้าง , หลุด
ปัจจัย แพ็กเก็ตหาย
ใครเจอ ทั้งเซิร์ฟเวอร์
เกิดเมื่อไร สุ่มเป็นครั้งคราว
ผู้รับผิดชอบ ผู้รับผิดชอบหลัก อินฟราเครือข่าย (ทีมอินฟรา) · ร่วมกับ พัฒนาเซิร์ฟเวอร์ (ทีมพัฒนาเกม), พัฒนาไคลเอนต์ (ทีมพัฒนาเกม)
งานฝั่งทีมพัฒนาเกม เซิร์ฟเวอร์: ตั้งไทม์เอาต์ที่ทนการขาดช่วงสั้น ๆ (หลายวินาที) ได้, ถ้าขาดแล้วเชื่อมต่อใหม่ ให้รับเซสชันต่อด้วย session token ไคลเอนต์: เชื่อมต่อใหม่อัตโนมัติเมื่อหลุด (กระจายช่วงห่างของการลองใหม่แบบสุ่มเพื่อไม่ให้แห่มาพร้อมกัน)
งานฝั่งทีมอินฟรา ทำระบบสำรอง (redundancy) ที่แชร์สถานะการเชื่อมต่อ, ใช้ BFD ตรวจจับความเสียหายภายใน 1 วินาที, ทดสอบการสลับเป็นประจำ
ตัวเลขที่ควรรู้ ถ้าอุปกรณ์ตรวจพบความเสียหายได้ทันที จะใช้เวลาราว 1–3 วินาที ถ้าไม่มีการตรวจจับความเสียหายแบบเร็ว (BFD) และปล่อยให้ใช้ตัวจับเวลาค่าเริ่มต้นของ BGP อย่างเดียว เส้นทางอาจขาดไป 90–180 วินาทีกว่าอุปกรณ์ข้างเคียงจะตรวจพบ
บนกราฟ การเชื่อมต่อหลุดพร้อมกัน · จำนวนการเชื่อมต่อ, ปริมาณรับส่งรวมของเซิร์ฟเวอร์
จุดที่ต้องดู ดู event log ของเราเตอร์และไฟร์วอลล์ (VRRP เปลี่ยนบทบาท, เซสชัน BFD หรือ BGP ล่ม, ประวัติ failover) และจำนวนการเชื่อมต่อกับปริมาณรับส่งรวมของเซิร์ฟเวอร์ในเวลาเดียวกัน สัญญาณว่าใช่ ในเวลาที่ log ของอุปกรณ์บันทึกการสลับ ทราฟฟิกของเซิร์ฟเวอร์ทุกเครื่องหลังอุปกรณ์นั้นเป็น 0 ไปหลายวินาที หรือจำนวนการเชื่อมต่อลดลงพร้อมกัน สัญญาณว่าไม่ใช่ ถ้าการเชื่อมต่อลดลงเฉพาะเซิร์ฟเวอร์เครื่องเดียว น่าจะเป็น “เซิร์ฟเวอร์แครช” หรือ “ปัญหาไดรเวอร์/เฟิร์มแวร์ของ NIC” ถ้า log ของอุปกรณ์สะอาด และเซิร์ฟเวอร์ที่หยุดเป็น VM บนคลาวด์เครื่องเดียว น่าจะเป็น “การซ่อมบำรุงโฮสต์คลาวด์/live migration” วิธีตรวจ ใช้เครื่องมือฝั่งอินฟรา (ไม่ต้องใช้โค้ดเกม)
แหล่งอ้างอิง 3 รายการ
ID dc-bad-cable · ผู้รับผิดชอบหลัก อินฟราเครือข่าย (ทีมอินฟรา)
ถ้าโมดูลออปติกหรือสายเสีย แพ็กเก็ตที่ผ่านเส้นทางนั้นจะเสียหายในสัดส่วนคงที่
ทำไม บิตผิดพลาดเพราะโมดูลออปติกหรือสายเสีย → ผลคือ อุปกรณ์ทิ้งแพ็กเก็ตที่เสียหายเงียบ ๆ → บนหน้าจอ เฉพาะเซิร์ฟเวอร์และผู้เล่นบางส่วนที่ใช้เส้นทางนั้น แพ็กเก็ตหายต่อเนื่องจนวาร์ปหรือดีดกลับ
อาการ วาร์ป , ดีดกลับ
ปัจจัย แพ็กเก็ตหาย
ใครเจอ บางจุด/บางแชนแนล
เกิดเมื่อไร ตลอดเวลา
ผู้รับผิดชอบ ผู้รับผิดชอบหลัก อินฟราเครือข่าย (ทีมอินฟรา)
งานฝั่งทีมอินฟรา มอนิเตอร์และตั้ง alert ตัวนับ error ของพอร์ต (CRC), เปลี่ยนชิ้นส่วนอย่างโมดูลออปติกหรือสาย, ระหว่างรอเปลี่ยนให้ถอดลิงก์ที่มีปัญหาออกแล้วอ้อมไปทางอื่น
บนกราฟ สูงเฉพาะบางกลุ่ม · จำนวน CRC error แยกตามพอร์ต, อัตราแพ็กเก็ตหายแยกตามเซิร์ฟเวอร์/เส้นทาง
จุดที่ต้องดู ดูตัวนับ CRC ทั้งสองฝั่งของลิงก์ สวิตช์ดู FCS error (dot3StatsFCSErrors) และ input error (ifInErrors) ของพอร์ต เซิร์ฟเวอร์ดู crc ใน RX errors ของ ip -s -s link (สถิติเคอร์เนล rx_crc_errors) สัญญาณว่าใช่ CRC error ของพอร์ตหนึ่งเพิ่มขึ้นต่อเนื่องไม่ว่าปริมาณทราฟฟิกหรือช่วงเวลาจะเป็นอย่างไร และมีแพ็กเก็ตหายเฉพาะเซิร์ฟเวอร์และผู้เล่นที่ผ่านพอร์ตนั้น สัญญาณว่าไม่ใช่ ถ้าไม่มี CRC error แต่การทิ้งขาออกเพิ่มอย่างเดียว น่าจะเป็นความแออัด (“microburst ที่สวิตช์”, “ลิงก์ของดาต้าเซ็นเตอร์เต็ม”) วิธีตรวจ ใช้เครื่องมือฝั่งอินฟรา (ไม่ต้องใช้โค้ดเกม)
แหล่งอ้างอิง 3 รายการ
ID dc-mtu · ผู้รับผิดชอบหลัก อินฟราเครือข่าย (ทีมอินฟรา) · ร่วมกับ อินฟราเซิร์ฟเวอร์ (ทีมอินฟรา), พัฒนาเซิร์ฟเวอร์ (ทีมพัฒนาเกม)
ถ้า MTU (ขนาดที่ส่งได้ในครั้งเดียว) ของช่วงกลางทางลดลง แต่ข้อความแจ้งว่าขนาดเกินถูกบล็อก แพ็กเก็ตใหญ่จะหายไปเรื่อย ๆ
ทำไม MTU ลดลงในช่วง tunnel หรือ VPN → ผลคือ ข้อความแจ้งว่าขนาดเกิน (ICMP) ถูกไฟร์วอลล์บล็อก ฝั่งส่งจึงไม่รู้ → บนหน้าจอ ค้างเฉพาะตอนเปิดหน้าจอที่ข้อมูลเยอะ เช่น กระเป๋าหรือรายชื่อตัวละคร แล้วหลุด
อาการ ค้าง , หลุด , เข้าเกมไม่ได้/โหลดไม่จบ
ปัจจัย แพ็กเก็ตหาย
ใครเจอ บางพื้นที่/บาง ISP, เราคนเดียว
เกิดเมื่อไร ตอนทำแอ็กชันบางอย่าง, หลังล็อกอิน/หลังปิดปรับปรุง
ผู้รับผิดชอบ ผู้รับผิดชอบหลัก อินฟราเครือข่าย (ทีมอินฟรา) · ร่วมกับ อินฟราเซิร์ฟเวอร์ (ทีมอินฟรา), พัฒนาเซิร์ฟเวอร์ (ทีมพัฒนาเกม)
งานฝั่งทีมพัฒนาเกม ถ้าจะลดจากฝั่งเซิร์ฟเวอร์โดยตรง ให้ตั้งขนาด segment สูงสุดของซ็อกเก็ต (TCP_MAXSEG) เพราะแค่แบ่งข้อความในโค้ดเกมให้เล็กลงยังกันไม่ได้, รักษาขนาดแพ็กเก็ต UDP ไว้ไม่เกิน 1,200 ไบต์
งานฝั่งทีมอินฟรา เครือข่าย: ลดขนาดแพ็กเก็ต TCP ในช่วง tunnel (ปรับ MSS), อนุญาตข้อความแจ้งว่าขนาดเกิน (ICMP) ในไฟร์วอลล์และ network ACL บนคลาวด์ เครื่องเซิร์ฟเวอร์/OS: อนุญาตข้อความแจ้งว่าขนาดเกิน (ICMP) ในไฟร์วอลล์ของเซิร์ฟเวอร์และ security group บนคลาวด์ด้วย, เปิดการค้นหา MTU ของเคอร์เนลเซิร์ฟเวอร์ (tcp_mtu_probing=1) ไว้เป็นด่านสุดท้าย ซึ่งจะทำงานหลังหยุดไปหลายวินาทีแล้ว
ตัวเลขที่ควรรู้ ปกติ 1,500 ไบต์ เมื่อผ่าน tunnel จะลดเหลือราว 1,400
บนกราฟ สูงเฉพาะบางกลุ่ม · หลุดแยกตามพื้นที่/ISP, การตอบกลับขนาดใหญ่ล้มเหลว
จุดที่ต้องดู จาก PC ของผู้เล่นที่มีปัญหา ส่ง ping ที่เปิดแฟล็กห้ามแบ่ง (DF) ไปที่เซิร์ฟเวอร์โดยเปลี่ยนขนาดไปเรื่อย ๆ Windows ใช้ ping /f /l 1472 SERVER_IP, Linux ใช้ ping -M do -s 1472 SERVER_IP (1,472 คือ MTU 1,500 ลบเฮดเดอร์ IP 20 ไบต์และเฮดเดอร์ ICMP 8 ไบต์) ลดขนาดลงเรื่อย ๆ เพื่อหาขนาดสูงสุดที่ผ่าน และตรวจว่า security group และไฟร์วอลล์ฝั่งเซิร์ฟเวอร์อนุญาตข้อความ ICMP แจ้งว่าขนาดเกิน (Fragmentation Needed) หรือไม่ สัญญาณว่าใช่ ping ขนาดเล็กผ่าน แต่ ping DF ขนาด 1,472 ไบต์ล้มเหลว (ไม่มีการตอบกลับ หรือได้ error ว่าต้อง fragment) และขนาดสูงสุดที่ผ่านเล็กราว 1,400 ผู้เล่นในพื้นที่เดียวกันค้างเฉพาะตอนเปิดหน้าจอที่ข้อมูลเยอะ สัญญาณว่าไม่ใช่ ถ้า ping DF ขนาด 1,472 ไบต์ก็ผ่านดี แสดงว่าไม่ใช่ปัญหา path MTU ถ้า ping ขนาดเล็กก็ไม่ผ่าน แสดงว่า ICMP ถูกบล็อกทั้งหมด จึงใช้วิธีนี้ตัดสินไม่ได้ วิธีตรวจ ตรวจที่สภาพแวดล้อมฝั่งผู้เล่น
แหล่งอ้างอิง 5 รายการ RFC 2923: TCP Problems with Path MTU Discovery IETF ถ้าไฟร์วอลล์บล็อก ICMP (Fragmentation Needed) การค้นหา path MTU จะล้มเหลว และแพ็กเก็ตใหญ่จะหายไปเรื่อย ๆ (black hole), ping และการสื่อสารขนาดเล็กยังใช้ได้ จึงวินิจฉัยยาก Maximum transmission unit and maximum segment size Cloudflare path MTU ของอินเทอร์เน็ต 1,500 เมื่อผ่าน GRE tunnel เหลือ 1,476 แนะนำให้จำกัด TCP MSS ไว้ไม่เกิน 1,436 IP Sysctl Linux kernel tcp_mtu_probing=1 ปกติปิดอยู่ และจะเปิดการค้นหา path MTU ของ TCP เมื่อตรวจพบ ICMP black hole ping(8) — Linux manual page iputils -M do เปิดแฟล็ก DF และปฏิเสธแพ็กเก็ตที่ใหญ่กว่า path MTU, -s กำหนดขนาดข้อมูล (ค่าเริ่มต้น 56 ไบต์ บวกเฮดเดอร์ ICMP 8 ไบต์) ping Microsoft /f เปิดแฟล็ก DF ใช้หาปัญหา path MTU และ /l กำหนดขนาดข้อมูล
L6 การ์ดเครือข่ายของเซิร์ฟเวอร์
9 สาเหตุ · บทในฉบับหลัก
ID nic-irq · ผู้รับผิดชอบหลัก อินฟราเซิร์ฟเวอร์ (ทีมอินฟรา)
ถ้า NIC ส่งอินเทอร์รัปต์แจ้งว่าแพ็กเก็ตมาถึงไปที่คอร์ CPU เพียงคอร์เดียว คอร์นั้นจะกลายเป็นคอขวด
ทำไม มี receive queue เดียว หรือปิด RSS ที่กระจายไปหลายคอร์ → ผลคือ คอร์หนึ่งขึ้นถึง 100% จนดึงแพ็กเก็ตออกมาไม่ทัน → บนหน้าจอ ตอนคนแห่มารวมกัน ทั้งเซิร์ฟเวอร์มีแพ็กเก็ตหายและความหน่วง (วาร์ป, อินพุตดีเลย์)
อาการ วาร์ป , ดีดกลับ , อินพุตดีเลย์
ปัจจัย แพ็กเก็ตหาย, ความหน่วง
ใครเจอ ทั้งเซิร์ฟเวอร์
เกิดเมื่อไร ตอนคนแห่มารวมกัน
ผู้รับผิดชอบ ผู้รับผิดชอบหลัก อินฟราเซิร์ฟเวอร์ (ทีมอินฟรา)
งานฝั่งทีมอินฟรา ตั้งค่า RSS (NIC กระจาย) และ RPS (เคอร์เนลกระจาย), กระจายอินเทอร์รัปต์ไปหลายคอร์, ตั้งให้ UDP แบ่งคิวโดยดูถึงพอร์ตด้วย (rx-flow-hash udp4 sdfn ของ ethtool -N), แยกคอร์ที่จัดการอินเทอร์รัปต์ออกจากคอร์ของเธรดทิกเกม, เฝ้าดู %soft แยกตามคอร์
ตัวเลขที่ควรรู้ ปริมาณที่คอร์หนึ่งประมวลผลผ่านเคอร์เนลได้อยู่ที่ราวหลายแสนแพ็กเก็ตต่อวินาที ขึ้นกับขนาดแพ็กเก็ตและการตั้งค่า ถ้าดูอัตราการใช้งานแยกตามคอร์แล้วพบว่าสัดส่วนงานรับแพ็กเก็ต (%soft ของ mpstat) กระจุกอยู่ที่คอร์เดียว ก็คือกรณีนี้
บนกราฟ ชนเพดานแล้วแบนราบ · %soft แยกตามคอร์, จำนวนแพ็กเก็ตรับต่อวินาที
จุดที่ต้องดู ใช้ mpstat -P ALL 1 ดู %soft (สัดส่วนเวลาจัดการ software interrupt) แยกตามคอร์ แล้วตรวจด้วย /proc/interrupts ว่าอินเทอร์รัปต์ของแต่ละคิวของ NIC ไปที่คอร์ไหน ใช้ ethtool -l ดูจำนวนคิว และ ethtool -S ดูจำนวนแพ็กเก็ตแยกตามคิว (ชื่อต่างกันตามไดรเวอร์) สัญญาณว่าใช่ มีคอร์เดียวที่ %soft ติดอยู่ใกล้ 100% ส่วนคอร์อื่นว่าง และอินเทอร์รัปต์กับแพ็กเก็ตกระจุกอยู่ที่คิวเดียว ตั้งแต่นั้นจำนวนแพ็กเก็ตรับต่อวินาทีก็ไม่ขึ้นอีก สัญญาณว่าไม่ใช่ ถ้า %soft กระจายเท่า ๆ กันในหลายคอร์ ก็ไม่ใช่สาเหตุนี้ ถ้า CPU ว่างแต่มีแพ็กเก็ตหาย น่าจะเป็น “เกินขีดจำกัด PPS ของคลาวด์” หรือ “ring buffer ไม่พอ” วิธีตรวจ ใช้เครื่องมือฝั่งอินฟรา (ไม่ต้องใช้โค้ดเกม)
รายละเอียดเพิ่มเติม แม้มีหลายคิว ถ้าทราฟฟิกส่วนใหญ่มาจาก IP ไม่กี่ตัว เช่น เกตเวย์หรือ proxy ก็จะไปกองที่คิวเดียว สำหรับ UDP การตั้งค่าเริ่มต้นของ NIC บางรุ่นแบ่งคิวโดยดูแค่ IP ต้องเปลี่ยนให้ดูถึงพอร์ตด้วยจึงจะกระจายได้เท่า ๆ กัน
แหล่งอ้างอิง 4 รายการ
ID nic-ring · ผู้รับผิดชอบหลัก อินฟราเซิร์ฟเวอร์ (ทีมอินฟรา)
ถ้า ring buffer ที่ NIC ใช้พักแพ็กเก็ตไว้ชั่วคราวมีขนาดเล็ก เมื่อแพ็กเก็ตทะลักเข้ามาในชั่วขณะ บัฟเฟอร์จะล้นและแพ็กเก็ตถูกทิ้ง
ทำไม ring buffer เล็กตามค่าเริ่มต้น (256–2,048 สล็อต แล้วแต่ไดรเวอร์) → ผลคือ ตอนเกิด burst บัฟเฟอร์ล้นก่อนที่ CPU จะดึงออกไป → บนหน้าจอ แพ็กเก็ตหายเฉพาะตอน burst (วาร์ป, สกิลไม่ออก) ไม่มีร่องรอยใน log ของเซิร์ฟเวอร์เกม
อาการ วาร์ป , กดไม่ติด/โรลแบ็ค
ปัจจัย แพ็กเก็ตหาย
ใครเจอ ทั้งเซิร์ฟเวอร์
เกิดเมื่อไร ตอนคนแห่มารวมกัน
ผู้รับผิดชอบ ผู้รับผิดชอบหลัก อินฟราเซิร์ฟเวอร์ (ทีมอินฟรา)
งานฝั่งทีมอินฟรา ขยาย ring buffer (ethtool -G), เฝ้าดูตัวนับการทิ้ง (drop) เช่น rx_missed_errors ใน ethtool -S (ชื่อต่างกันตามไดรเวอร์)
ตัวเลขที่ควรรู้ ถ้าแพ็กเก็ตทะลักเข้ามา 1 ล้านแพ็กเก็ตต่อวินาที 1,024 สล็อตจะเต็มในเวลาประมาณ 1 ms ระหว่างนั้นถ้า CPU มาช้าแค่ครั้งเดียวก็ล้น NIC ส่วนใหญ่เพิ่มได้ถึงหลายพันสล็อต
บนกราฟ พุ่งแบบสุ่มเป็นครั้งคราว · ตัวนับการทิ้งขาเข้าของ NIC
จุดที่ต้องดู เก็บตัวนับการทิ้งขาเข้าใน ethtool -S (rx_missed_errors, rx_fifo_errors ฯลฯ ชื่อต่างกันตามไดรเวอร์) และ missed ใน ip -s -s link ด้วยช่วงเวลาสั้น ๆ และใช้ ethtool -g ดูขนาด ring ปัจจุบันกับค่าสูงสุด สัญญาณว่าใช่ ตัวนับการทิ้งเพิ่มขึ้นตอนเกิด burst และขนาด ring ปัจจุบันเล็กกว่าค่าสูงสุดมาก เมื่อขยาย ring การทิ้งก็ลดลง สัญญาณว่าไม่ใช่ ถ้าตัวนับการทิ้งไม่ขยับแต่มีแพ็กเก็ตหาย น่าจะเป็นขั้นถัดไปในเคอร์เนล (“บัฟเฟอร์ซ็อกเก็ตของเคอร์เนลไม่พอ”) หรือช่วงเครือข่าย ถ้า %soft ของคอร์เดียวอยู่ที่ 100% น่าจะเป็น “อินเทอร์รัปต์ของ NIC กระจุกที่คอร์เดียว” วิธีตรวจ ใช้เครื่องมือฝั่งอินฟรา (ไม่ต้องใช้โค้ดเกม)
แหล่งอ้างอิง 4 รายการ
ID nic-coalesce · ผู้รับผิดชอบหลัก อินฟราเซิร์ฟเวอร์ (ทีมอินฟรา)
การรวบแพ็กเก็ตไว้แล้วแจ้งทีเดียวช่วยลดภาระ CPU แต่ก็ทำให้ช้าลงตามเวลาที่ใช้รวบ
ทำไม NIC รวบแพ็กเก็ตตามเวลาหรือจำนวนที่กำหนดแล้วจึงแจ้ง → ผลคือ แพ็กเก็ตต้องรอระหว่างรวบ → บนหน้าจอ ความหน่วงเพิ่มขึ้นเล็กน้อย ปกติน้อยมาก แต่ถ้าตั้งมากเกินไปจะถึงระดับ ms
อาการ อินพุตดีเลย์
ปัจจัย ความหน่วง
ใครเจอ ทั้งเซิร์ฟเวอร์
เกิดเมื่อไร ตลอดเวลา
ผู้รับผิดชอบ ผู้รับผิดชอบหลัก อินฟราเซิร์ฟเวอร์ (ทีมอินฟรา)
งานฝั่งทีมอินฟรา ใช้ adaptive coalescing, ปรับค่าให้เหมาะกับเซิร์ฟเวอร์เกม (ethtool -C)
ตัวเลขที่ควรรู้ ปกติหลายสิบถึงหลายร้อย µs ซึ่งสำหรับเกมมักน้อยจนไม่ต้องสนใจ แต่ถ้าตั้งค่ามากเกินไปจะขึ้นไปถึงระดับ ms
บนกราฟ สูงตลอดตั้งแต่แรก · เวลาไปกลับภายในดาต้าเซ็นเตอร์เดียวกัน
จุดที่ต้องดู ใช้ ethtool -c ดูการตั้ง coalescing ปัจจุบัน (adaptive-rx, rx-usecs, rx-frames) แล้วเทียบเวลาไปกลับของ ping กับเซิร์ฟเวอร์อื่นในดาต้าเซ็นเตอร์เดียวกันก่อนและหลังเปลี่ยนค่า สัญญาณว่าใช่ rx-usecs ตั้งไว้สูงตั้งแต่หลายร้อย µs ขึ้นไป และเมื่อลดค่าลง เวลาไปกลับภายในดาต้าเซ็นเตอร์เดียวกันก็ลดลงตามนั้น สัญญาณว่าไม่ใช่ ถ้าลดค่าแล้วเวลาไปกลับยังเท่าเดิม ก็ไม่ใช่สาเหตุนี้ วิธีตรวจ ใช้เครื่องมือฝั่งอินฟรา (ไม่ต้องใช้โค้ดเกม)
แหล่งอ้างอิง 3 รายการ
ID nic-cloud-pps · ผู้รับผิดชอบหลัก อินฟราเซิร์ฟเวอร์ (ทีมอินฟรา) · ร่วมกับ พัฒนาเซิร์ฟเวอร์ (ทีมพัฒนาเกม), ภายนอก (ภายนอก)
เซิร์ฟเวอร์บนคลาวด์แต่ละประเภทมีขีดจำกัดจำนวนแพ็กเก็ตต่อวินาทีและแบนด์วิดท์ ถ้าเกินจะถูกทิ้งเงียบ ๆ
ทำไม ผู้เล่นออนไลน์พร้อมกันเพิ่มขึ้นจนจำนวนแพ็กเก็ตต่อวินาทีเกินขีดจำกัดของอินสแตนซ์ → ผลคือ เครือข่ายของคลาวด์ทิ้งส่วนที่เกิน → บนหน้าจอ วาร์ปหรือสกิลไม่ออกจากแพ็กเก็ตหายที่หาสาเหตุไม่เจอ ขณะที่ CPU ของเซิร์ฟเวอร์ยังว่าง
อาการ วาร์ป , กดไม่ติด/โรลแบ็ค
ปัจจัย แพ็กเก็ตหาย
ใครเจอ ทั้งเซิร์ฟเวอร์
เกิดเมื่อไร ตอนคนแห่มารวมกัน, ช่วงพีคหัวค่ำ
ผู้รับผิดชอบ ผู้รับผิดชอบหลัก อินฟราเซิร์ฟเวอร์ (ทีมอินฟรา) · ร่วมกับ พัฒนาเซิร์ฟเวอร์ (ทีมพัฒนาเกม), ภายนอก (ภายนอก)
งานฝั่งทีมพัฒนาเกม รวมแพ็กเก็ต (ส่งข้อความของหนึ่งทิกในแพ็กเก็ตเดียว), ไม่ส่งแพ็กเก็ตเล็กมาก ๆ ถี่เกินไป
งานฝั่งทีมอินฟรา ตรวจและตั้ง alert ตัวนับที่เกินขีดจำกัด (AWS คือ pps_allowance_exceeded, conntrack_allowance_exceeded ฯลฯ), ใช้อินสแตนซ์ที่ใหญ่ขึ้น, เลี่ยงขีดจำกัด connection tracking ด้วยการตั้ง security group แบบที่ไม่เกิดการติดตาม
งานฝั่งภายนอก สอบถามผู้ให้บริการคลาวด์ถึงขีดจำกัดจำนวนแพ็กเก็ตต่อวินาทีและ connection tracking ของอินสแตนซ์แต่ละประเภท
ตัวเลขที่ควรรู้ ขีดจำกัดต่างกันตามขนาดอินสแตนซ์ และขีดจำกัดจำนวนแพ็กเก็ตต่อวินาทีมักไม่เปิดเผย “สูงสุด 10 Gbps” ของอินสแตนซ์ขนาดเล็กเป็นความเร็ว burst ที่ใช้ได้เฉพาะช่วงที่ยังมีเครดิตเหลือ (ปกติ 5–60 นาที) ความเร็วพื้นฐานตามปกติต่ำกว่านั้นมาก
บนกราฟ ชนเพดานแล้วแบนราบ · จำนวนแพ็กเก็ตต่อวินาที, ตัวนับ allowance ที่เกิน
จุดที่ต้องดู เก็บตัวนับของ ENA ใน ethtool -S ได้แก่ pps_allowance_exceeded, bw_in_allowance_exceeded, bw_out_allowance_exceeded และ conntrack_allowance_exceeded ด้วยช่วงเวลาสั้น ๆ แล้วดูคู่กับจำนวนแพ็กเก็ตต่อวินาที จะใช้ CloudWatch agent ส่งตัวนับเหล่านี้ขึ้น CloudWatch แล้วตั้ง alert ก็ได้ สัญญาณว่าใช่ ในเวลาที่แพ็กเก็ตหาย ตัวนับ allowance ที่เกินเพิ่มขึ้น และจำนวนแพ็กเก็ตต่อวินาทีไม่ขึ้นเกินค่าหนึ่ง ขณะที่ CPU ของเซิร์ฟเวอร์ยังว่าง สัญญาณว่าไม่ใช่ ถ้าตัวนับที่เกินไม่ขยับ ก็ไม่ใช่สาเหตุนี้ ถ้า %soft ของคอร์เดียวอยู่ที่ 100% น่าจะเป็น “อินเทอร์รัปต์ของ NIC กระจุกที่คอร์เดียว” วิธีตรวจ ใช้เครื่องมือฝั่งอินฟรา (ไม่ต้องใช้โค้ดเกม)
รายละเอียดเพิ่มเติม conntrack_allowance_exceeded คือกรณีที่ตาราง connection tracking เต็มจนการเชื่อมต่อใหม่ถูกทิ้ง ถ้าตารางยังมีที่ว่างแต่การเชื่อมต่อที่ idle หลุดเพราะการติดตามหมดอายุ ให้ดูสาเหตุ “connection tracking ของ security group บนคลาวด์หมดอายุ”
แหล่งอ้างอิง 2 รายการ
ID nic-saturate · ผู้รับผิดชอบหลัก พัฒนาเซิร์ฟเวอร์ (ทีมพัฒนาเกม) · ร่วมกับ อินฟราเซิร์ฟเวอร์ (ทีมอินฟรา)
ถ้าใช้การ์ด 1 Gbps หรือ 10 Gbps จนถึงขีดจำกัด transmit queue จะยาวขึ้น และสุดท้ายแพ็กเก็ตจะถูกทิ้ง
ทำไม broadcast เพิ่มขึ้นจนปริมาณส่งชนขีดจำกัดของการ์ด → ผลคือ transmit queue ยาวขึ้น และเมื่อล้นก็ทิ้ง → บนหน้าจอ ความหน่วงและแพ็กเก็ตหายทั้งเซิร์ฟเวอร์ (อินพุตดีเลย์, วาร์ป)
อาการ อินพุตดีเลย์ , วาร์ป
ปัจจัย ความหน่วง, แพ็กเก็ตหาย
ใครเจอ ทั้งเซิร์ฟเวอร์
เกิดเมื่อไร ตอนคนแห่มารวมกัน
ผู้รับผิดชอบ ผู้รับผิดชอบหลัก พัฒนาเซิร์ฟเวอร์ (ทีมพัฒนาเกม) · ร่วมกับ อินฟราเซิร์ฟเวอร์ (ทีมอินฟรา)
งานฝั่งทีมพัฒนาเกม ลดปริมาณการส่ง (AOI, บีบอัด, ส่งเฉพาะส่วนที่เปลี่ยน)
งานฝั่งทีมอินฟรา เพิ่มการ์ด (NIC ที่เร็วขึ้น, บนคลาวด์ใช้อินสแตนซ์ที่ใหญ่ขึ้น), ตั้ง alert อัตราการใช้งาน NIC
บนกราฟ ชนเพดานแล้วแบนราบ · ปริมาณส่งของ NIC, การทิ้งขาออก
จุดที่ต้องดู เทียบ txkB/s และ %ifutil (อัตราการใช้งานเทียบกับความเร็วอินเทอร์เฟซ) ของ sar -n DEV 1 กับความเร็ว NIC และแบนด์วิดท์ของอินสแตนซ์ แล้วดู TX dropped ของ ip -s link ประกอบ สัญญาณว่าใช่ ปริมาณส่งแบนราบใกล้แบนด์วิดท์ของ NIC หรืออินสแตนซ์ และตั้งแต่นั้นการทิ้งขาออกและความหน่วงของทั้งเซิร์ฟเวอร์ก็เพิ่มขึ้น สัญญาณว่าไม่ใช่ ถ้าแบนด์วิดท์ยังเหลือ ก็ไม่ใช่สาเหตุนี้ ถ้ามีแพ็กเก็ตเล็กจำนวนมากและมีแพ็กเก็ตหาย น่าจะเป็น “เกินขีดจำกัด PPS ของคลาวด์” วิธีตรวจ ใช้เครื่องมือฝั่งอินฟรา (ไม่ต้องใช้โค้ดเกม)
แหล่งอ้างอิง 3 รายการ
ID nic-noisy · ผู้รับผิดชอบหลัก อินฟราเซิร์ฟเวอร์ (ทีมอินฟรา) · ร่วมกับ ภายนอก (ภายนอก)
ถ้า VM อื่นที่อยู่บนเครื่องจริงเครื่องเดียวกันใช้เครือข่ายหรือ CPU มาก การประมวลผลของเซิร์ฟเวอร์เราจะถูกเลื่อนออกไปอย่างไม่สม่ำเสมอ
ทำไม VM อื่นบนเครื่องจริงเครื่องเดียวกันใช้ทรัพยากรมาก → ผลคือ การประมวลผลแพ็กเก็ตของ VM เราล่าช้าอย่างไม่สม่ำเสมอ → บนหน้าจอ เกิดจิตเตอร์ (ช่วงเวลาที่แพ็กเก็ตมาถึงไม่สม่ำเสมอ) เป็นครั้งคราวโดยไม่มีสาเหตุชัดเจน จนภาพกระตุก
อาการ กระตุก
ปัจจัย จิตเตอร์
ใครเจอ ทั้งเซิร์ฟเวอร์
เกิดเมื่อไร สุ่มเป็นครั้งคราว
ผู้รับผิดชอบ ผู้รับผิดชอบหลัก อินฟราเซิร์ฟเวอร์ (ทีมอินฟรา) · ร่วมกับ ภายนอก (ภายนอก)
งานฝั่งทีมอินฟรา ใช้ dedicated host, ใช้อินสแตนซ์ที่รับประกันประสิทธิภาพ, อินสแตนซ์ที่จิตเตอร์ไม่หายให้หยุดแล้วเริ่มใหม่เพื่อย้ายไปโฮสต์อื่น
งานฝั่งภายนอก แจ้งผู้ให้บริการคลาวด์เรื่องโฮสต์ที่มีปัญหา
บนกราฟ พุ่งแบบสุ่มเป็นครั้งคราว · จิตเตอร์ของเวลาไปกลับภายในดาต้าเซ็นเตอร์เดียวกัน, %steal
จุดที่ต้องดู ส่ง ping ต่อเนื่องไปยังเซิร์ฟเวอร์อื่นในดาต้าเซ็นเตอร์เดียวกันเพื่อบันทึกจิตเตอร์ของเวลาไปกลับ แล้วเทียบกับอินสแตนซ์อื่นที่ตั้งค่าแบบเดียวกัน พร้อมดู %steal ของ mpstat สัญญาณว่าใช่ เฉพาะอินสแตนซ์นี้ที่จิตเตอร์ของเวลาไปกลับหรือ %steal พุ่งแบบไม่สม่ำเสมอ ส่วนอินสแตนซ์อื่นที่ตั้งค่าเหมือนกันนิ่ง เมื่อหยุดแล้วเริ่มใหม่จนย้ายไปโฮสต์อื่น อาการก็หายไป สัญญาณว่าไม่ใช่ ถ้าอินสแตนซ์ที่ตั้งค่าเหมือนกันพุ่งเหมือนกันหมด ก็ไม่ใช่ปัญหาที่โฮสต์ ให้ดูโหลดฝั่งเซิร์ฟเวอร์เกมหรือช่วงเครือข่าย วิธีตรวจ ใช้เครื่องมือฝั่งอินฟรา (ไม่ต้องใช้โค้ดเกม)
แหล่งอ้างอิง 2 รายการ
ID nic-host-maintenance · ผู้รับผิดชอบหลัก อินฟราเซิร์ฟเวอร์ (ทีมอินฟรา) · ร่วมกับ พัฒนาเซิร์ฟเวอร์ (ทีมพัฒนาเกม), ภายนอก (ภายนอก)
เมื่อผู้ให้บริการคลาวด์ซ่อมบำรุงเครื่องจริง (โฮสต์) จะย้าย VM ไปโฮสต์อื่น (live migration) หรือหยุด VM ชั่วคราว ระหว่างนั้นทั้งเซิร์ฟเวอร์จะหยุด และถ้าหยุดนาน การเชื่อมต่อจะขาด
ทำไม ผู้ให้บริการย้าย VM ไปโฮสต์อื่นหรือพักการทำงานชั่วคราว เพราะซ่อมบำรุงโฮสต์หรือคาดว่าฮาร์ดแวร์จะเสีย → ผลคือ ระหว่างย้าย CPU หน่วยความจำ และเครือข่ายช้าลง และช่วงท้าย VM จะหยุดสนิทชั่วครู่ (ไม่ถึง 1 วินาทีจนถึงราว 30 วินาที ขึ้นกับผู้ให้บริการและวิธี) → บนหน้าจอ ทุกคนในเซิร์ฟเวอร์ค้างพร้อมกันแล้วกรอเร็วหรือวาร์ป ถ้าหยุดนานกว่าไทม์เอาต์ จะหลุดจำนวนมาก
อาการ ค้าง , กรอเร็ว , วาร์ป , หลุด
ปัจจัย การหยุดชะงัก, แพ็กเก็ตหาย
ใครเจอ ทั้งเซิร์ฟเวอร์
เกิดเมื่อไร สุ่มเป็นครั้งคราว
ผู้รับผิดชอบ ผู้รับผิดชอบหลัก อินฟราเซิร์ฟเวอร์ (ทีมอินฟรา) · ร่วมกับ พัฒนาเซิร์ฟเวอร์ (ทีมพัฒนาเกม), ภายนอก (ภายนอก)
งานฝั่งทีมพัฒนาเกม ตั้งไทม์เอาต์ที่ทนการหยุดหลายวินาทีได้, ตั้งเพดานจำนวนทิกที่เร่งคำนวณให้ทันหลังหยุด, คำนวณเวลาที่ผ่านไปด้วย monotonic clock, มีขั้นตอนบันทึกความคืบหน้าและย้ายผู้เล่นไปเซิร์ฟเวอร์อื่นเมื่อได้รับแจ้งการซ่อมบำรุง
งานฝั่งทีมอินฟรา สมัครรับและตั้ง alert การแจ้งซ่อมบำรุง (Google Cloud maintenance-event, AWS scheduled event และ AWS Health, Azure Scheduled Events), เมื่อได้รับแจ้งให้เปลี่ยนเซิร์ฟเวอร์ล่วงหน้าในช่วงที่ผู้เล่นน้อย, ปรับเวลาซ่อมบำรุงถ้าผู้ให้บริการอนุญาต (Azure Maintenance Configuration, AWS scheduled event บางประเภท), เทียบประวัติการซ่อมบำรุงกับบันทึกเหตุขัดข้อง
งานฝั่งภายนอก สอบถามผู้ให้บริการคลาวด์ถึงกำหนดการซ่อมบำรุงและขอบเขตผลกระทบ, แจ้งผู้ให้บริการถ้าอินสแตนซ์เดิมหยุดซ้ำ ๆ
ตัวเลขที่ควรรู้ Google Compute Engine ระบุว่าการหยุดระหว่าง live migration ปกติสั้นกว่า 1 วินาทีมาก และระหว่างหยุด นาฬิการะบบอาจกระโดดไปข้างหน้าได้สูงสุด 5 วินาที ค่า maintenance-event ใน metadata จะเปลี่ยน 60 วินาทีก่อนย้าย (กรณีที่เคยอ่านค่านี้ไว้อย่างน้อยหนึ่งครั้งก่อนหน้านั้น) Azure ระบุว่าการซ่อมบำรุงที่ไม่ต้องรีบูตแทบทุกครั้งหยุดไม่ถึง 10 วินาที นาน ๆ ครั้ง (ขนาดทั่วไปไม่เกินหนึ่งครั้งใน 18 เดือน) หยุดราว 30 วินาที และ live migration ปกติไม่เกิน 5 วินาที Azure Scheduled Events แจ้งการหยุดแบบนี้ (Freeze) ล่วงหน้าอย่างน้อย 15 นาที แต่ถ้าฮาร์ดแวร์ของโฮสต์เสียกะทันหัน จะเริ่มกู้คืนทันทีโดยไม่แจ้ง
บนกราฟ ขาดช่วงแล้วมารวดเดียว · จำนวนแพ็กเก็ตรับส่งของเซิร์ฟเวอร์, ช่วงห่างระหว่างทิก
จุดที่ต้องดู เทียบเวลาที่หยุดกับบันทึกของผู้ให้บริการ Google Cloud ดู compute.instances.migrateOnHostMaintenance ใน audit log, AWS ดู scheduled event ใน describe-instance-status และ AWS Health, Azure ดูเวลาที่มี Microsoft.Compute/virtualMachines/liveMigration/action ใน Activity Log และเวลาที่เมตริกความพร้อมใช้งานของ VM (VmAvailabilityMetric) ลดลงเป็น 0 ภายในเซิร์ฟเวอร์ให้ดูว่าเมตริกและ log ว่างไปในช่วงที่หยุดหรือไม่ และนาฬิกากระโดดทันทีหลังจากนั้นหรือไม่ (log การซิงก์เวลา) สัญญาณว่าใช่ เวลาที่ทั้งเซิร์ฟเวอร์หยุดตรงกับเวลาซ่อมบำรุงหรือ migration ที่ผู้ให้บริการบันทึกไว้ และในไม่กี่วินาทีนั้นเมตริกและ log ในเซิร์ฟเวอร์ว่างหมด สัญญาณว่าไม่ใช่ ถ้าไม่มีในบันทึกของผู้ให้บริการ และมีการหยุดสั้น ๆ ซ้ำบ่อย น่าจะเป็น “CPU steal (VM)” ถ้า log ของเคอร์เนลมีประวัติรีเซ็ต NIC น่าจะเป็น “ปัญหาไดรเวอร์/เฟิร์มแวร์ของ NIC” วิธีตรวจ ใช้เครื่องมือฝั่งอินฟรา (ไม่ต้องใช้โค้ดเกม)
รายละเอียดเพิ่มเติม AWS แจ้งผ่าน scheduled event โดย system-reboot หมายถึงรีบูตพร้อมย้ายไปโฮสต์ใหม่ และ system-maintenance หมายถึงอาจได้รับผลกระทบชั่วครู่จากการซ่อมบำรุงเครือข่ายหรือไฟฟ้า แม้จะหยุดแค่ไม่กี่วินาที ไคลเอนต์ที่ไม่ได้รับ ACK ของแพ็กเก็ตที่ส่งไปยังเซิร์ฟเวอร์ระหว่างนั้นจะเพิ่มเวลารอส่งซ้ำเป็นสองเท่าไปเรื่อย ๆ แม้เซิร์ฟเวอร์จะกลับมาทำงานแล้ว การเชื่อมต่อ TCP จึงอาจยังหยุดอยู่ต่ออีกพักหนึ่ง (“TCP RTO และ exponential backoff”) เมื่อตื่นจากการหยุด นาฬิกาอาจกระโดดจนกลายเป็น “นาฬิการะบบกระโดด (NTP step)” และ health check ของโหลดบาลานเซอร์อาจล้มเหลวจนถอดเซิร์ฟเวอร์นั้นออกชั่วคราว อินสแตนซ์ที่ย้ายไม่ได้ (เช่น bare metal instance ของ Google Cloud) จะถูกหยุดหรือเริ่มใหม่เมื่อมีการซ่อมบำรุง
แหล่งอ้างอิง 6 รายการ Live migration process during maintenance events Google Cloud การหยุดระหว่าง live migration ปกติสั้นกว่า 1 วินาทีมาก, ระหว่างหยุดนาฬิการะบบกระโดดไปข้างหน้าได้สูงสุด 5 วินาที, ระหว่างย้าย ประสิทธิภาพดิสก์ CPU หน่วยความจำ และเครือข่ายลดลงชั่วครู่, VM ที่ไม่ใช้ live migration จะถูกปิดเมื่อซ่อมบำรุง (bare metal instance ไม่รองรับ) Query metadata server for maintenance event notices Google Cloud ค่า metadata ของ maintenance-event เปลี่ยน 60 วินาทีก่อน live migration (กรณีตั้งค่าเป็น live migration และเคยอ่านค่านี้อย่างน้อยหนึ่งครั้งหลังการซ่อมบำรุงครั้งก่อน) Monitor and plan for a host maintenance event Google Cloud เมื่อซ่อมบำรุงจะมี system event compute.instances.migrateOnHostMaintenance ใน audit log Scheduled events for Amazon EC2 instances AWS ประเภทของ scheduled event (system-reboot คือรีบูตพร้อมย้ายไปโฮสต์ใหม่, system-maintenance คือได้รับผลกระทบชั่วครู่จากการซ่อมบำรุงเครือข่ายหรือไฟฟ้า), แจ้งทางอีเมลและ AWS Health, ดูได้ด้วย describe-instance-status, บางประเภทปรับเวลาได้ Maintenance and updates Microsoft Azure การซ่อมบำรุงที่ไม่ต้องรีบูตแทบทุกครั้งหยุดไม่ถึง 10 วินาที, นาน ๆ ครั้ง (ขนาดทั่วไปไม่เกินหนึ่งครั้งใน 18 เดือน) ราว 30 วินาที, live migration ปกติไม่เกิน 5 วินาที, หลังหยุดนาฬิกาซิงก์อัตโนมัติ, การเชื่อมต่อ TCP ที่เปิดไว้นานอาจขาด หรืออีกฝั่งส่งซ้ำข้อมูลที่ส่งไปยัง VM ที่หยุดอยู่แบบ exponential backoff ทำให้กู้คืนช้าลงอีก, health check ของโหลดบาลานเซอร์ตัดสินว่าผิดปกติภายในราว 10 วินาที, ตรวจได้จาก Microsoft.Compute/virtualMachines/liveMigration/action ใน Activity Log และ VmAvailabilityMetric ที่เป็น 0 ระหว่างหยุด, เลือกเวลาที่จะใช้การซ่อมบำรุงได้ด้วย Maintenance Configuration Scheduled Events for Linux VMs in Azure Microsoft Azure Freeze (หยุดไม่กี่วินาที CPU และเครือข่ายอาจหยุด) แจ้งล่วงหน้าอย่างน้อย 15 นาที, กรณีฮาร์ดแวร์ของโฮสต์เสีย จะเริ่มกู้คืนทันทีโดยไม่มีช่วงแจ้งล่วงหน้า
ID nic-reset · ผู้รับผิดชอบหลัก อินฟราเซิร์ฟเวอร์ (ทีมอินฟรา)
ระหว่างที่การ์ดหยุดแล้วเริ่มใหม่เพราะบั๊กของไดรเวอร์หรือฟีเจอร์ทำงานผิดพลาด การรับส่งทั้งหมดจะขาด
ทำไม บั๊กของไดรเวอร์, ฟีเจอร์ offload ทำงานผิดพลาด → ผลคือ NIC หยุดแล้วเริ่มใหม่ (หลายวินาที) → บนหน้าจอ ทุกคนในเซิร์ฟเวอร์นั้นค้างพร้อมกันแล้ววาร์ปหรือหลุด
อาการ ค้าง , หลุด
ปัจจัย แพ็กเก็ตหาย
ใครเจอ ทั้งเซิร์ฟเวอร์
เกิดเมื่อไร สุ่มเป็นครั้งคราว, ยิ่งเปิดไว้นานยิ่งเป็น
ผู้รับผิดชอบ ผู้รับผิดชอบหลัก อินฟราเซิร์ฟเวอร์ (ทีมอินฟรา)
งานฝั่งทีมอินฟรา ตรวจและตั้ง alert ข้อความ “transmit queue … timed out” และ “Link is Down” ใน log ของเคอร์เนล, อัปเดตไดรเวอร์และเฟิร์มแวร์, ปิดฟีเจอร์ที่มีปัญหา (เช่น offload)
บนกราฟ ขาดช่วงแล้วมารวดเดียว · จำนวนแพ็กเก็ตรับส่งของเซิร์ฟเวอร์
จุดที่ต้องดู ใช้ dmesg หาใน log ของเคอร์เนลว่ามี “NETDEV WATCHDOG … transmit queue N timed out”, การรีเซ็ตของไดรเวอร์ หรือ “Link is Down” และ “Link is Up” หรือไม่ แล้วดูจำนวนแพ็กเก็ตรับส่งของเซิร์ฟเวอร์ในเวลานั้น สัญญาณว่าใช่ ในเวลาที่หยุด log ของเคอร์เนลมี transmit queue timeout หรือบันทึกลิงก์ down และ up และในไม่กี่วินาทีนั้นจำนวนแพ็กเก็ตรับส่งเป็น 0 สัญญาณว่าไม่ใช่ ถ้า log ของเคอร์เนลสะอาดและพอร์ตฝั่งสวิตช์ก็ปกติ น่าจะเป็นโปรเซสเซิร์ฟเวอร์เกมหยุด (“GC ของเซิร์ฟเวอร์หยุดทั้งระบบ”, “เดดล็อก”) หรือ “การ failover ของอุปกรณ์เครือข่าย” วิธีตรวจ ใช้เครื่องมือฝั่งอินฟรา (ไม่ต้องใช้โค้ดเกม)
แหล่งอ้างอิง 3 รายการ
ID nic-offload · ผู้รับผิดชอบหลัก อินฟราเซิร์ฟเวอร์ (ทีมอินฟรา)
เป็นฟีเจอร์ที่รวมหลายแพ็กเก็ตเป็นก้อนเดียวเพื่อลดภาระ CPU บางการตั้งค่าทำให้แพ็กเก็ตเกมขนาดเล็กต้องรอแพ็กเก็ตถัดไปที่จะรวมด้วยสักครู่
ทำไม NIC และเคอร์เนลรวมแพ็กเก็ตที่มาถึงแล้วประมวลผลพร้อมกัน → ผลคือ ถ้าเปิดการรวมในฮาร์ดแวร์ (LRO) หรือตั้งเวลารอรวมไว้ จะรอแพ็กเก็ตถัดไปสักครู่ → บนหน้าจอ ความหน่วงเพิ่มขึ้นเล็กน้อย (ส่วนใหญ่ไม่เกินหลายสิบ µs)
อาการ อินพุตดีเลย์
ปัจจัย ความหน่วง
ใครเจอ ทั้งเซิร์ฟเวอร์
เกิดเมื่อไร ตลอดเวลา
ผู้รับผิดชอบ ผู้รับผิดชอบหลัก อินฟราเซิร์ฟเวอร์ (ทีมอินฟรา)
งานฝั่งทีมอินฟรา ปรับให้เหมาะกับทราฟฟิกเกม (ปิด LRO, ตรวจการตั้งเวลารอรวม), ผลกระทบส่วนใหญ่น้อย จึงตรวจหลังสาเหตุอื่น
บนกราฟ สูงตลอดตั้งแต่แรก · เวลาไปกลับภายในดาต้าเซ็นเตอร์เดียวกัน
จุดที่ต้องดู ใช้ ethtool -k ดูสถานะ lro และ gro และดูค่า gro_flush_timeout ในการตั้งค่า sysfs ของอุปกรณ์ แล้วเทียบเวลาไปกลับของแพ็กเก็ตขนาดเล็กภายในดาต้าเซ็นเตอร์เดียวกันก่อนและหลังเปลี่ยน สัญญาณว่าใช่ LRO เปิดอยู่ หรือ gro_flush_timeout มากกว่า 0 และเมื่อปิดหรือตั้งเป็น 0 เวลาไปกลับของแพ็กเก็ตขนาดเล็กลดลง สัญญาณว่าไม่ใช่ ถ้าเปลี่ยนแล้วต่างกันแค่ไม่กี่ µs ก็ไม่ใช่สาเหตุนี้ วิธีตรวจ ใช้เครื่องมือฝั่งอินฟรา (ไม่ต้องใช้โค้ดเกม)
แหล่งอ้างอิง 3 รายการ
L7 OS ของเซิร์ฟเวอร์ (เคอร์เนล)
14 สาเหตุ · บทในฉบับหลัก
ID so-backlog · ผู้รับผิดชอบหลัก พัฒนาเซิร์ฟเวอร์ (ทีมพัฒนาเกม) · ร่วมกับ อินฟราเซิร์ฟเวอร์ (ทีมอินฟรา), พัฒนาไคลเอนต์ (ทีมพัฒนาเกม)
ทันทีหลังปิดปรับปรุง ถ้าผู้เล่นหลายหมื่นคนเชื่อมต่อพร้อมกัน คิวรอเชื่อมต่อ (backlog) ของเคอร์เนลจะล้น และความพยายามเชื่อมต่อจะถูกทิ้ง
ทำไม พอปิดปรับปรุงเสร็จ การเชื่อมต่อก็ทะลักเข้ามาเร็วกว่าที่เซิร์ฟเวอร์เกมรับด้วย accept ทัน → ผลคือ คิวรอเชื่อมต่อของเคอร์เนล (backlog คือค่าที่น้อยกว่าระหว่างค่าที่โค้ดเซิร์ฟเวอร์ส่งให้ listen กับเพดานของเคอร์เนล) เต็ม → บนหน้าจอ ความพยายามเชื่อมต่อถูกทิ้งและลองใหม่วนไปเรื่อย ๆ จนเข้าเกมไม่ได้/โหลดไม่จบ
อาการ เข้าเกมไม่ได้/โหลดไม่จบ
ปัจจัย แพ็กเก็ตหาย
ใครเจอ ทั้งเซิร์ฟเวอร์
เกิดเมื่อไร หลังล็อกอิน/หลังปิดปรับปรุง
ผู้รับผิดชอบ ผู้รับผิดชอบหลัก พัฒนาเซิร์ฟเวอร์ (ทีมพัฒนาเกม) · ร่วมกับ อินฟราเซิร์ฟเวอร์ (ทีมอินฟรา), พัฒนาไคลเอนต์ (ทีมพัฒนาเกม)
งานฝั่งทีมพัฒนาเกม เซิร์ฟเวอร์: เพิ่มค่า listen ที่ส่งในโค้ด, อย่าให้เธรดที่รับการเชื่อมต่อหยุดเพราะงานอื่น, ทำระบบคิวล็อกอิน ไคลเอนต์: เพิ่มช่วงห่างการลองใหม่ (สุ่มให้กระจาย)
งานฝั่งทีมอินฟรา เพิ่ม somaxconn ของเคอร์เนล (ต้องเพิ่มคู่กับค่า listen ในโค้ดเซิร์ฟเวอร์จึงจะได้ผล), เปิด SYN cookie ไว้, มอนิเตอร์จำนวนครั้งที่ล้น (TcpExtListenOverflows ของ nstat)
ตัวเลขที่ควรรู้ เพดานของเคอร์เนล Linux (somaxconn) มีค่าเริ่มต้น 4,096 ตั้งแต่ 5.4 (ก่อนหน้านั้น 128) แต่ถ้าโค้ดเซิร์ฟเวอร์ส่งค่าที่น้อยกว่าให้ listen ค่านั้นจะกลายเป็นขีดจำกัด เมื่อคิวเต็ม Linux จะทิ้งคำขอเชื่อมต่อเงียบ ๆ โดยไม่ส่งข้อผิดพลาดกลับ OS ฝั่งไคลเอนต์จะส่งซ้ำอีกไม่กี่ครั้งโดยเริ่มหลัง 1 วินาที ผู้เล่นจึงเห็นแค่หน้าโหลดนาน ๆ โดยไม่ขึ้น “เชื่อมต่อไม่สำเร็จ” ส่วนเซิร์ฟเวอร์ Windows จะส่งการตอบกลับว่าปฏิเสธ ไคลเอนต์จึงเห็น “เชื่อมต่อไม่สำเร็จ” ทันที
บนกราฟ พุ่งทันทีหลังเปิดเซิร์ฟ/ปิดปรับปรุง · จำนวนครั้งที่คิวรอเชื่อมต่อล้น (ListenOverflows), จำนวนความพยายามเชื่อมต่อ
จุดที่ต้องดู ค่าที่เพิ่มขึ้นของ TcpExtListenOverflows และ TcpExtListenDrops จาก nstat -az และใช้ ss -ltn เทียบ Recv-Q (จำนวนการเชื่อมต่อที่รอ accept) กับ Send-Q (ขีดจำกัด backlog) ของซ็อกเก็ตที่ listen อยู่ สัญญาณว่าใช่ ช่วงที่การเชื่อมต่อแห่เข้ามา ListenOverflows เพิ่มขึ้น และ Recv-Q ของซ็อกเก็ตที่ listen อยู่ชนค่า Send-Q สัญญาณว่าไม่ใช่ ListenOverflows ไม่ขยับ: ไม่ใช่สาเหตุนี้ ถ้าเชื่อมต่อได้แต่โหลดไม่จบ ให้ดู “คนแห่ล็อกอินและคิวรี N+1” ถ้าติดที่จำนวนคนค่าหนึ่งพอดี ให้ดู “ขีดจำกัด file descriptor” วิธีตรวจ ใช้เครื่องมือฝั่งอินฟรา (ไม่ต้องใช้โค้ดเกม)
แหล่งอ้างอิง 5 รายการ listen(2) — Linux manual page Linux man-pages ถ้า backlog ของ listen เกิน somaxconn จะถูกตัดเงียบ ๆ, somaxconn ค่าเริ่มต้น 4,096 (ตั้งแต่ 5.4 ก่อนหน้านั้น 128), เมื่อคิวเต็มอาจเพิกเฉยต่อคำขอแล้วปล่อยให้ไคลเอนต์ลองใหม่เอง IP Sysctl Linux kernel tcp_syn_retries: ส่งคำขอเชื่อมต่อ (SYN) ซ้ำหลายครั้ง โดยรอ 1 วินาทีก่อนส่งซ้ำครั้งแรก, tcp_abort_on_overflow ปิดเป็นค่าเริ่มต้น (คิวล้นก็ไม่ส่งการปฏิเสธกลับ), tcp_syncookies เปิดเป็นค่าเริ่มต้น listen function (winsock2.h) Microsoft บน Windows เมื่อคิวเต็ม ไคลเอนต์จะได้รับข้อผิดพลาด WSAECONNREFUSED SNMP counter Linux kernel TcpExtListenOverflows: จำนวนครั้งที่ทิ้งคำขอเชื่อมต่อ (SYN) เพราะคิว accept เต็ม ซึ่ง TcpExtListenDrops จะเพิ่มขึ้นไปพร้อมกัน net/ipv4/tcp_diag.c (Linux v6.12) Linux kernel ค่า Recv-Q และ Send-Q ของ ss: ซ็อกเก็ตที่ listen อยู่คือจำนวนการเชื่อมต่อที่รอ accept และขีดจำกัด backlog, ซ็อกเก็ตที่เชื่อมต่อแล้วคือไบต์ที่แอปยังไม่ได้อ่าน และไบต์ที่ส่งไปแล้วแต่ยังไม่ได้รับ ACK
ID so-fd · ผู้รับผิดชอบหลัก อินฟราเซิร์ฟเวอร์ (ทีมอินฟรา) · ร่วมกับ พัฒนาเซิร์ฟเวอร์ (ทีมพัฒนาเกม)
ทุกการเชื่อมต่อต้องใช้ file descriptor (fd คือหมายเลขที่ OS กำหนดให้ไฟล์หรือซ็อกเก็ตที่เปิดอยู่) แต่จำนวน fd ที่หนึ่งโปรเซสเปิดได้มีจำกัด
ทำไม จำนวนผู้เล่นออนไลน์พร้อมกันแตะขีดจำกัด file descriptor ของโปรเซส → ผลคือ เซิร์ฟเวอร์รับการเชื่อมต่อใหม่ไม่ได้ (Too many open files) การเปิดไฟล์ log และการเชื่อมต่อ DB ก็ล้มเหลวไปด้วย → บนหน้าจอ พอถึงจำนวนคนค่าหนึ่งพอดีก็ไม่มีใครเข้าได้อีก: เข้าเกมไม่ได้/โหลดไม่จบ
อาการ เข้าเกมไม่ได้/โหลดไม่จบ
ปัจจัย แพ็กเก็ตหาย
ใครเจอ ทั้งเซิร์ฟเวอร์
เกิดเมื่อไร หลังล็อกอิน/หลังปิดปรับปรุง, ตอนคนแห่มารวมกัน
ผู้รับผิดชอบ ผู้รับผิดชอบหลัก อินฟราเซิร์ฟเวอร์ (ทีมอินฟรา) · ร่วมกับ พัฒนาเซิร์ฟเวอร์ (ทีมพัฒนาเกม)
งานฝั่งทีมพัฒนาเกม ปิดซ็อกเก็ตให้แน่นอนเมื่อจบการเชื่อมต่อ (กัน fd รั่ว), ถ้า accept ล้มเหลวด้วย EMFILE (fd ไม่พอ) ให้หยุดรับการเชื่อมต่อชั่วครู่ หรือใช้ fd สำรองที่กันไว้รับแล้วปิดทันที (จะได้ไม่เสีย CPU ไปกับการจัดการแจ้งเตือนการเชื่อมต่อเดิมซ้ำ ๆ)
งานฝั่งทีมอินฟรา ตรวจ ulimit และการตั้งค่าเซอร์วิส (LimitNOFILE ของ systemd), ตั้ง alert เมื่อใกล้ขีดจำกัด
ตัวเลขที่ควรรู้ บน Linux ถ้าไม่ได้ตั้งค่าเซอร์วิสแยกไว้ ขีดจำกัดยังเป็น 1,024 อยู่บ่อย ๆ เซิร์ฟเวอร์เกมมักเพิ่มเป็นหลายหมื่นถึงหลายแสน ส่วน Windows ไม่มีขีดจำกัดเริ่มต้นที่ต่ำแบบนี้
บนกราฟ ชนเพดานแล้วแบนราบ · จำนวน fd ที่โปรเซสเปิดอยู่, จำนวนผู้เล่นออนไลน์พร้อมกัน
จุดที่ต้องดู fd-nr (จำนวน file descriptor ที่เปิดอยู่) ของโปรเซสเซิร์ฟเวอร์เกมจาก pidstat -v, ขีดจำกัดจำนวนไฟล์ที่เปิดได้จาก /proc/PID/limits และ accept ที่ล้มเหลว (EMFILE, Too many open files) ใน log ของเซิร์ฟเวอร์ สัญญาณว่าใช่ จำนวน fd แบนราบที่ค่าขีดจำกัด และตั้งแต่ตอนนั้น accept ล้มเหลวด้วย EMFILE สัญญาณว่าไม่ใช่ จำนวน fd ยังห่างจากขีดจำกัดมาก: ไม่ใช่สาเหตุนี้ ถ้าคำขอเชื่อมต่อถูกทิ้งในเคอร์เนล ให้ดู “คิวรอเชื่อมต่อ (backlog) ล้น” ถ้าเกี่ยวกับ connection tracking ให้ดู “ตาราง conntrack ของเซิร์ฟเวอร์เต็ม” วิธีตรวจ ใช้เครื่องมือฝั่งอินฟรา (ไม่ต้องใช้โค้ดเกม)
รายละเอียดเพิ่มเติม การเชื่อมต่อที่รับไม่ได้จะยังรออยู่ในคิวรอเชื่อมต่อ (backlog) ของเคอร์เนล ขึ้นอยู่กับโค้ดเซิร์ฟเวอร์ บางครั้งจะได้รับแจ้ง “มีการเชื่อมต่อใหม่” ซ้ำไปเรื่อย ๆ จนเปลือง CPU
แหล่งอ้างอิง 5 รายการ
ID so-sockbuf · ผู้รับผิดชอบหลัก อินฟราเซิร์ฟเวอร์ (ทีมอินฟรา) · ร่วมกับ พัฒนาเซิร์ฟเวอร์ (ทีมพัฒนาเกม)
ถ้าบัฟเฟอร์ส่งและรับเล็ก เมื่อทราฟฟิกมาเป็น burst แพ็กเก็ตที่รับทาง UDP จะถูกทิ้ง ส่วนการส่งทาง TCP จะติดเพราะบัฟเฟอร์ไม่มีที่ว่าง
ทำไม SO_SNDBUF และ SO_RCVBUF ใช้ค่าเริ่มต้นหรือเล็กเกินไป → ผลคือ ระหว่าง burst หรือช่วงที่เธรดรับหยุดชั่วครู่ receive buffer ของ UDP ล้นจนแพ็กเก็ตถูกทิ้ง ส่วน TCP ต้องรอเพราะ send buffer ไม่มีที่ว่าง → บนหน้าจอ วาร์ป (UDP แพ็กเก็ตหาย) หรือกรอเร็ว (TCP รอ)
อาการ วาร์ป , กรอเร็ว
ปัจจัย แพ็กเก็ตหาย, การหยุดชะงัก
ใครเจอ ทั้งเซิร์ฟเวอร์
เกิดเมื่อไร ตอนคนแห่มารวมกัน
ผู้รับผิดชอบ ผู้รับผิดชอบหลัก อินฟราเซิร์ฟเวอร์ (ทีมอินฟรา) · ร่วมกับ พัฒนาเซิร์ฟเวอร์ (ทีมพัฒนาเกม)
งานฝั่งทีมพัฒนาเกม ตั้งขนาดบัฟเฟอร์ (SO_SNDBUF, SO_RCVBUF) ในโค้ดให้เหมาะกับทราฟฟิก, ระวังว่าถ้ากำหนดขนาดบัฟเฟอร์ของ TCP เอง Linux จะปิดการปรับขนาดอัตโนมัติ, อย่าตั้งใหญ่เกินไปเพราะข้อมูลเก่าจะกองในบัฟเฟอร์จนดีเลย์เพิ่ม, อย่าให้เธรดรับหยุด
งานฝั่งทีมอินฟรา ปรับเพดานของเคอร์เนล (rmem_max, wmem_max: ขนาดบัฟเฟอร์ที่ตั้งในโค้ดก็เกินค่านี้ไม่ได้) และค่าเริ่มต้น (rmem_default), มอนิเตอร์ตัวนับบัฟเฟอร์ล้น (RcvbufErrors)
ตัวเลขที่ควรรู้ ค่าเริ่มต้นของ receive buffer ของ UDP บน Linux อยู่ที่ประมาณ 208 KB แพ็กเก็ตเล็ก ๆ หนึ่งแพ็กเก็ตก็กินหน่วยความจำเคอร์เนลมากกว่าขนาดจริงมาก แค่หลายสิบถึงหลายร้อยแพ็กเก็ตก็เต็ม ถ้าเซิร์ฟเวอร์รับ 100,000 แพ็กเก็ตต่อวินาที เธรดรับหยุดแค่ไม่กี่ ms บัฟเฟอร์ก็ล้น
บนกราฟ พุ่งแบบสุ่มเป็นครั้งคราว · receive buffer ของ UDP ล้น (UdpRcvbufErrors)
จุดที่ต้องดู ค่าที่เพิ่มขึ้นของ UdpRcvbufErrors จาก nstat -az และ skmem ใน ss -uamn (rb คือขนาด receive buffer, d คือจำนวนแพ็กเก็ตที่ใส่ซ็อกเก็ตไม่ได้จนถูกทิ้ง) ส่วน TCP ดู skmem ของ ss -tm ว่าหน่วยความจำที่รอส่ง (w) ชนขนาด send buffer (tb) หรือไม่ สัญญาณว่าใช่ ช่วง burst หรือตอนที่เธรดรับหยุด UdpRcvbufErrors (หรือ d ของซ็อกเก็ต) เพิ่มขึ้น และ rb อยู่ใกล้ค่าเริ่มต้น (ประมาณ 208 KB) ส่วน TCP: w ติดอยู่ที่ tb และ send ถูกบล็อก สัญญาณว่าไม่ใช่ ตัวนับไม่ขยับแต่มีแพ็กเก็ตหาย: น่าจะเป็นที่ขั้น NIC (“ring buffer ไม่พอ”) หรือช่วงเครือข่าย วิธีตรวจ ใช้เครื่องมือฝั่งอินฟรา (ไม่ต้องใช้โค้ดเกม)
แหล่งอ้างอิง 6 รายการ socket(7) — Linux manual page Linux man-pages ค่าเริ่มต้นของ SO_RCVBUF และ SO_SNDBUF คือ rmem_default และ wmem_default, เพดานคือ rmem_max และ wmem_max, เคอร์เนลจะเพิ่มค่าที่ตั้งเป็นสองเท่า include/net/sock.h (Linux v6.18) Linux kernel กำหนดบัฟเฟอร์ซ็อกเก็ตเริ่มต้นเท่ากับแพ็กเก็ตขนาด 256 ไบต์จำนวน 256 แพ็กเก็ตรวม overhead ของ sk_buff (SKB_TRUESIZE(256)×256), เฟรมเล็ก ๆ ก็คิดเป็น sk_buff+MTU (ประมาณ 208 KB คือค่าที่คำนวณบน x86-64) IP Sysctl Linux kernel tcp_rmem, tcp_wmem: ถ้ากำหนด SO_RCVBUF หรือ SO_SNDBUF เอง การปรับขนาดอัตโนมัติของซ็อกเก็ตนั้นจะปิด net/ipv4/udp.c (Linux v6.12) Linux kernel ถ้าคิวรับของ UDP เกินขนาดบัฟเฟอร์ซ็อกเก็ต จะทิ้งทันทีและเพิ่มค่า RcvbufErrors net/ipv4/proc.c (Linux v6.12) Linux kernel ชื่อตัวนับที่ nstat แสดง: RcvbufErrors และ SndbufErrors ในกลุ่ม Udp ss(8) — Linux manual page iproute2 skmem ของ -m: rb ขนาด receive buffer, tb ขนาด send buffer, w หน่วยความจำที่รอส่ง, d จำนวนแพ็กเก็ตที่ถูกทิ้งก่อนเข้าซ็อกเก็ต
ID so-context · ผู้รับผิดชอบหลัก พัฒนาเซิร์ฟเวอร์ (ทีมพัฒนาเกม) · ร่วมกับ อินฟราเซิร์ฟเวอร์ (ทีมอินฟรา)
ถ้ารันเธรดมากกว่าจำนวนคอร์มาก ๆ OS จะเสีย CPU ไปกับการสลับให้เธรดผลัดกันทำงานอย่างเดียว
ทำไม มีเธรดหลายร้อยถึงหลายพันตัว เช่น สร้างเธรดหนึ่งตัวต่อหนึ่งการเชื่อมต่อ → ผลคือ ต้นทุน context switch (การสลับเธรดที่กำลังรัน) และ cache miss เพิ่มขึ้น → บนหน้าจอ CPU ยุ่งแต่ throughput ต่ำ ทิกไม่สม่ำเสมอ จึงกระตุกและเป็นสโลว์โมชั่น
อาการ กระตุก , สโลว์โมชั่น
ปัจจัย การหยุดชะงัก, จิตเตอร์
ใครเจอ ทั้งเซิร์ฟเวอร์
เกิดเมื่อไร ตอนคนแห่มารวมกัน
ผู้รับผิดชอบ ผู้รับผิดชอบหลัก พัฒนาเซิร์ฟเวอร์ (ทีมพัฒนาเกม) · ร่วมกับ อินฟราเซิร์ฟเวอร์ (ทีมอินฟรา)
งานฝั่งทีมพัฒนาเกม ใช้จำนวนเธรดให้เหมาะกับจำนวนคอร์, ใช้ async I/O (epoll, IOCP)
งานฝั่งทีมอินฟรา มอนิเตอร์จำนวน context switch และจำนวนเธรดที่รอรัน (cs และ r ของ vmstat)
ตัวเลขที่ควรรู้ context switch หนึ่งครั้งใช้เวลาไม่กี่ µs และถ้ารวมต้นทุน cache miss ที่ตามมาด้วยจะมากกว่านั้น
บนกราฟ สูงตามจำนวนคนและโหลด · จำนวน context switch ต่อวินาที, จำนวนเธรดที่รอรัน
จุดที่ต้องดู cs (context switch ต่อวินาที) และ r (จำนวนที่กำลังรันหรือรอ CPU) จาก vmstat 1 เทียบกับจำนวนคอร์ และ context switch แบบ voluntary (cswch/s) กับ involuntary (nvcswch/s) แยกตามเธรดของเซิร์ฟเวอร์เกมจาก pidstat -w -t สัญญาณว่าใช่ เมื่อผู้เล่นออนไลน์เพิ่มขึ้น r พุ่งสูงกว่าจำนวนคอร์มาก cs ก็พุ่งตาม และมีเธรดหลายร้อยตัวที่มี involuntary context switch สูง สัญญาณว่าไม่ใช่ r อยู่ไม่เกินจำนวนคอร์: ไม่ใช่สาเหตุนี้ ถ้ามีแต่ voluntary switch สูง แปลว่าเธรดกำลังรอล็อกหรือ I/O (“การแย่งล็อก”, “โครงสร้างแบบ blocking I/O”) วิธีตรวจ ใช้เครื่องมือฝั่งอินฟรา (ไม่ต้องใช้โค้ดเกม)
แหล่งอ้างอิง 4 รายการ Quantifying The Cost of Context Switch (ExpCS 2007) ACM ต้นทุนทางตรงของ context switch ประมาณ 3.8 µs, ต้นทุนทางอ้อมรวมผลต่อแคชตั้งแต่ไม่กี่ µs ถึงมากกว่า 1,000 µs (ตามสภาพแวดล้อมที่วัด) vmstat(8) — Linux manual page procps-ng ฟิลด์ cs (จำนวน context switch ต่อวินาที) และ r (จำนวนโปรเซสที่กำลังรันหรือรอรัน) I/O Completion Ports Microsoft ใช้ thread pool ที่สร้างไว้ล่วงหน้าร่วมกับ IOCP จัดการ async I/O จำนวนมาก และกำหนดจำนวนเธรดที่รันพร้อมกันให้เท่ากับจำนวนที่ CPU รันพร้อมกันได้ pidstat(1) — Linux manual page sysstat cswch/s ของ -w คือ voluntary context switch ที่เธรดหยุดเองเพื่อรอทรัพยากร, nvcswch/s คือ involuntary context switch ที่ถูกสลับออกเพราะใช้ time slice หมด, -t แสดงแยกตามเธรด
ID so-steal · ผู้รับผิดชอบหลัก อินฟราเซิร์ฟเวอร์ (ทีมอินฟรา) · ร่วมกับ ภายนอก (ภายนอก)
ระหว่างที่เครื่องจริง (ไฮเปอร์ไวเซอร์) ยก CPU time ของ VM ไปให้ VM ตัวอื่นชั่วครู่ (CPU steal) เซิร์ฟเวอร์เกมจะหยุดชะงัก
ทำไม VM ตัวอื่นบนโฮสต์เดียวกันใช้ CPU มาก → ผลคือ VM ของเราไม่ได้รับ CPU ครั้งละไม่กี่ ms ถึงหลายสิบ ms → บนหน้าจอ เวลาต่อทิกพุ่งโดยหาสาเหตุไม่เจอ: กระตุก, ค้าง
อาการ กระตุก , ค้าง
ปัจจัย การหยุดชะงัก
ใครเจอ ทั้งเซิร์ฟเวอร์
เกิดเมื่อไร สุ่มเป็นครั้งคราว
ผู้รับผิดชอบ ผู้รับผิดชอบหลัก อินฟราเซิร์ฟเวอร์ (ทีมอินฟรา) · ร่วมกับ ภายนอก (ภายนอก)
งานฝั่งทีมอินฟรา มอนิเตอร์ค่า steal (st ของ top และ vmstat), ใช้คอร์หรือโฮสต์เฉพาะ (dedicated), เลี่ยงอินสแตนซ์แบบ burstable ที่ช้าลงเมื่อ CPU credit หมด, อินสแตนซ์ที่ steal สูงต่อเนื่องให้ stop แล้ว start ใหม่เพื่อย้ายไปโฮสต์อื่น
งานฝั่งภายนอก แจ้งผู้ให้บริการคลาวด์ว่าโฮสต์มีค่า steal สูงต่อเนื่อง
บนกราฟ พุ่งแบบสุ่มเป็นครั้งคราว · %steal, เวลาต่อทิกของเซิร์ฟเวอร์
จุดที่ต้องดู %steal จาก mpstat -P ALL 1 วางบนแกนเวลาเดียวกับเวลาต่อทิกของเซิร์ฟเวอร์ สัญญาณว่าใช่ ตอนที่ทิกพุ่ง %steal พุ่งด้วย และลดลงหลัง stop แล้ว start ใหม่เพื่อย้ายไปโฮสต์อื่น สัญญาณว่าไม่ใช่ %steal ใกล้ 0 แต่ทิกยังพุ่ง: น่าจะเป็นสาเหตุภายในเซิร์ฟเวอร์เกม (“GC ของเซิร์ฟเวอร์หยุดทั้งระบบ”, “การแย่งล็อก”) ถ้าเป็นคอนเทนเนอร์ ให้ดู “CPU throttling ของคอนเทนเนอร์ (CFS quota)” วิธีตรวจ ใช้เครื่องมือฝั่งอินฟรา (ไม่ต้องใช้โค้ดเกม)
แหล่งอ้างอิง 4 รายการ
ID so-cpu-quota · ผู้รับผิดชอบหลัก อินฟราเซิร์ฟเวอร์ (ทีมอินฟรา) · ร่วมกับ พัฒนาเซิร์ฟเวอร์ (ทีมพัฒนาเกม)
ถ้าตั้งขีดจำกัด CPU ให้คอนเทนเนอร์ เมื่อใช้โควตาหมดภายในรอบที่กำหนด (ปกติ 100 ms) คอนเทนเนอร์จะถูกบังคับหยุดตลอดเวลาที่เหลือของรอบนั้น (throttling)
ทำไม ตั้งขีดจำกัด CPU (limit) ให้คอนเทนเนอร์เซิร์ฟเวอร์เกมไว้ เช่น ใน Kubernetes → ผลคือ ตอนที่งานคำนวณทิกมากระจุกกัน โควตาหมดจนต้องหยุดหลายสิบ ms รอรอบถัดไป → บนหน้าจอ CPU เฉลี่ยต่ำ แต่ทิกพุ่งเป็นรอบ: กระตุก, สโลว์โมชั่น
อาการ กระตุก , สโลว์โมชั่น
ปัจจัย การหยุดชะงัก, จิตเตอร์
ใครเจอ ทั้งเซิร์ฟเวอร์
เกิดเมื่อไร ตอนคนแห่มารวมกัน, สุ่มเป็นครั้งคราว
ผู้รับผิดชอบ ผู้รับผิดชอบหลัก อินฟราเซิร์ฟเวอร์ (ทีมอินฟรา) · ร่วมกับ พัฒนาเซิร์ฟเวอร์ (ทีมพัฒนาเกม)
งานฝั่งทีมพัฒนาเกม ตั้งจำนวน worker thread ให้เท่ากับขีดจำกัด CPU (อย่าให้ runtime สร้างเธรดเท่าจำนวนคอร์ทั้งหมดของโฮสต์)
งานฝั่งทีมอินฟรา ตั้งขีดจำกัด CPU ให้เผื่อมาก ๆ หรือเอาออกแล้วจัดคอร์เฉพาะให้, มอนิเตอร์จำนวนครั้งที่ถูก throttle (nr_throttled)
ตัวเลขที่ควรรู้ บนเซิร์ฟเวอร์ที่จำกัดไว้ 2 คอร์ ถ้าเธรด 8 ตัวทำงานพร้อมกัน จะใช้โควตาของรอบ 100 ms หมดภายใน 25 ms แล้วหยุดไป 75 ms
บนกราฟ สูงตามจำนวนคนและโหลด · จำนวนครั้งที่ถูก throttle (nr_throttled), เวลาต่อทิกของเซิร์ฟเวอร์
จุดที่ต้องดู ค่าที่เพิ่มขึ้นของ nr_throttled และ throttled_usec (cgroup v1 คือ nr_throttled และ throttled_time) ใน cpu.stat ของ cgroup คอนเทนเนอร์ ดูคู่กับเวลาต่อทิกของเซิร์ฟเวอร์ สัญญาณว่าใช่ อัตราการใช้ CPU เฉลี่ยต่ำกว่าขีดจำกัด แต่ nr_throttled และ throttled_usec เพิ่มขึ้นเรื่อย ๆ และตรงกับช่วงที่ทิกพุ่ง สัญญาณว่าไม่ใช่ nr_throttled ไม่เพิ่ม: ไม่ใช่สาเหตุนี้ ถ้าตัว VM เองถูกแย่ง CPU ให้ดู “CPU steal (VM)” วิธีตรวจ ใช้เครื่องมือฝั่งอินฟรา (ไม่ต้องใช้โค้ดเกม)
แหล่งอ้างอิง 3 รายการ
ID so-cstate · ผู้รับผิดชอบหลัก อินฟราเซิร์ฟเวอร์ (ทีมอินฟรา)
คอร์ CPU ที่ว่างจะเข้าโหมดประหยัดพลังงานระดับลึก (C-state) และลดความถี่ลงเพื่อประหยัดไฟ เมื่อแพ็กเก็ตหรือตัวจับเวลามาถึง ต้องใช้เวลาตื่นและเพิ่มความถี่ การประมวลผลแพ็กเก็ตเล็ก ๆ จึงมีดีเลย์เพิ่มขึ้น
ทำไม นโยบายปรับความถี่ของ OS (governor) หรือการตั้งค่าพลังงานใน BIOS ยอมให้ใช้ C-state ระดับลึกและความถี่ต่ำ → ผลคือ คอร์ที่ว่างอยู่ตื่นช้าสูงสุดหลายร้อย µs ทุกครั้งที่ออกจากโหมดประหยัดพลังงานระดับลึก และถ้าความถี่ถูกตรึงไว้ต่ำ การคำนวณทิกเองก็ช้าลง → บนหน้าจอ ปกติรู้สึกได้ยาก แต่ถ้าเรียกกันระหว่างเซิร์ฟเวอร์บ่อย ดีเลย์จะสะสมเป็นอินพุตดีเลย์ที่กลับหนักขึ้นตอนเซิร์ฟเวอร์ว่าง ถ้าความถี่ถูกตรึงไว้ต่ำ ตอนคนแห่มารวมกันทิกจะตามไม่ทันจนเป็นสโลว์โมชั่น
อาการ อินพุตดีเลย์ , สโลว์โมชั่น
ปัจจัย ความหน่วง, จิตเตอร์, การหยุดชะงัก
ใครเจอ ทั้งเซิร์ฟเวอร์
เกิดเมื่อไร ตลอดเวลา, สุ่มเป็นครั้งคราว
ผู้รับผิดชอบ ผู้รับผิดชอบหลัก อินฟราเซิร์ฟเวอร์ (ทีมอินฟรา)
งานฝั่งทีมอินฟรา ตั้งค่าพลังงานใน BIOS ไปทางประสิทธิภาพ, ตั้ง governor ของ OS เป็น performance (scaling_governor ของ cpufreq), จำกัด C-state ระดับลึกบนเซิร์ฟเวอร์ที่ไวต่อความหน่วง (โปรไฟล์ tuned latency-performance, /dev/cpu_dma_latency ของ PM QoS, พารามิเตอร์เคอร์เนล intel_idle.max_cstate), หลังเปลี่ยนให้เทียบเวลาไปกลับภายในดาต้าเซ็นเตอร์เดียวกัน จิตเตอร์ของเวลาต่อทิก และการใช้พลังงานไปพร้อมกัน
ตัวเลขที่ควรรู้ ตารางของไดรเวอร์ intel_idle ใน Linux 6.12 ระบุว่า CPU เซิร์ฟเวอร์ของ Intel ใช้เวลาตื่นจาก C1 (ระดับตื้น) 1–2 µs และจาก C6 (ระดับลึก) 133 µs (Skylake-SP) ถึง 290 µs (Sapphire Rapids) ครั้งเดียวถือว่าน้อย แต่ถ้าคำขอหนึ่งต้องผ่านเซิร์ฟเวอร์หลายเครื่อง ดีเลย์ก็สะสมตามจำนวนนั้น เคอร์เนลจะเลือกสถานะที่ลึกขึ้นเมื่อคาดว่าจะว่างนานขึ้น อาการนี้จึงพบบ่อยกว่าบนเซิร์ฟเวอร์ที่ว่างซึ่งแพ็กเก็ตมาห่าง ๆ governor แบบ powersave ของ cpufreq ทั่วไปจะตรึงความถี่ไว้ที่ค่าต่ำสุดในช่วงที่อนุญาต (ส่วนอัลกอริทึมชื่อเดียวกันของ intel_pstate จะปรับตามโหลด)
บนกราฟ สูงตลอดตั้งแต่แรก · เวลาไปกลับภายในดาต้าเซ็นเตอร์เดียวกัน, ความถี่ของคอร์
จุดที่ต้องดู สัดส่วนเวลาที่แต่ละคอร์อยู่ในแต่ละ C-state และความถี่จริงจาก cpupower monitor, name, latency (µs ที่ใช้ตื่น) และ usage ของแต่ละ state ใต้ /sys/devices/system/cpu/cpu0/cpuidle/, scaling_governor ของ cpufreq และโปรไฟล์ปัจจุบันจาก tuned-adm active สัญญาณว่าใช่ ตอนว่าง คอร์อยู่ใน C-state ลึกสุดเป็นเวลานาน หรือความถี่ถูกตรึงไว้ใกล้ค่าต่ำสุด และเมื่อเปลี่ยนเป็น performance governor กับ C-state ระดับตื้น เวลาไปกลับและจิตเตอร์ของคำขอเล็ก ๆ ลดลง สัญญาณว่าไม่ใช่ เปลี่ยนแล้วต่างกันไม่เกินหลักสิบ µs: ข้ามสาเหตุนี้ได้ ถ้าพุ่งในระดับ ms ให้ดู “CPU steal (VM)” หรือชั้นอื่น วิธีตรวจ ใช้เครื่องมือฝั่งอินฟรา (ไม่ต้องใช้โค้ดเกม)
รายละเอียดเพิ่มเติม เซิร์ฟเวอร์ bare-metal ใน IDC ต้องดูการตั้งค่าพลังงานใน BIOS (เฟิร์มแวร์) ควบคู่กับการตั้งค่าของ OS ส่วนบนคลาวด์ มีเพียงอินสแตนซ์บางประเภทที่ OS เปลี่ยน C-state และความถี่ได้ และ AWS ตั้งค่าเริ่มต้นไว้ทางประสิทธิภาพสูงสุด ส่วนใหญ่จึงปล่อยไว้ตามเดิมได้ โปรไฟล์ tuned latency-performance ของตระกูล Red Hat ตั้ง governor เป็น performance และใช้ PM QoS ให้ใช้เฉพาะ C-state ระดับตื้น การปิดโหมดประหยัดพลังงานทำให้ใช้ไฟมากขึ้น จึงควรใช้เฉพาะกับเซิร์ฟเวอร์ที่ไวต่อความหน่วง
แหล่งอ้างอิง 7 รายการ CPU Idle Time Management Linux kernel โหมดประหยัดพลังงานแต่ละระดับมีเวลาตื่น (exit latency) และเวลาอยู่ขั้นต่ำ (target residency) และจะเลือกสถานะลึกตามเวลาว่างที่คาดไว้, latency, usage และ time ของแต่ละ state ใน sysfs, จำกัดสถานะลึกด้วย PM QoS (/dev/cpu_dma_latency) และ intel_idle.max_cstate drivers/idle/intel_idle.c (Linux v6.12) Linux kernel เวลาตื่นของแต่ละ C-state บน CPU เซิร์ฟเวอร์ของ Intel: Skylake-SP (C1 2 µs, C1E 10 µs, C6 133 µs), Ice Lake (C6 170 µs), Sapphire Rapids (C1 1 µs, C6 290 µs) CPU Performance Scaling Linux kernel ตรวจและเปลี่ยน governor ด้วย scaling_governor, performance จะขอความถี่สูงสุดในช่วงที่อนุญาต, powersave ขอความถี่ต่ำสุด intel_pstate CPU Performance Scaling Driver Linux kernel อัลกอริทึม powersave ของ intel_pstate ต่างจาก powersave governor ทั่วไป คือปรับตามโหลด (คล้าย schedutil และ ondemand) Chapter 2. Getting started with TuneD Red Hat โปรไฟล์ latency-performance ปิดฟีเจอร์ประหยัดพลังงาน ตั้ง governor เป็น performance และใช้ PM QoS ให้ใช้เฉพาะ C-state ระดับตื้น, ตรวจโปรไฟล์ปัจจุบันด้วย tuned-adm active tools/power/cpupower/man/cpupower-monitor.1 (Linux v6.12) Linux kernel cpupower monitor: สถิติความถี่และโหมดประหยัดพลังงานแยกตามคอร์ Processor state control for Amazon EC2 Linux instances AWS มีเพียงอินสแตนซ์บางประเภทที่ OS ควบคุม C-state และ P-state ได้ และปรับเพื่อลดความหน่วงได้, ค่าเริ่มต้นเป็นประสิทธิภาพสูงสุดซึ่งเหมาะกับงานส่วนใหญ่, Graviton ใช้ความถี่คงที่ OS จึงไม่ได้ควบคุม
OOM killer Out-of-memory killer
ID so-oom · ผู้รับผิดชอบหลัก พัฒนาเซิร์ฟเวอร์ (ทีมพัฒนาเกม) · ร่วมกับ อินฟราเซิร์ฟเวอร์ (ทีมอินฟรา)
เมื่อหน่วยความจำหมด Linux จะเลือกโปรเซสที่ใช้หน่วยความจำมากที่สุดแล้วบังคับปิด ซึ่งส่วนใหญ่คือเซิร์ฟเวอร์เกม
ทำไม หน่วยความจำหมดเพราะรั่วหรือใช้พุ่ง หรือคอนเทนเนอร์แตะขีดจำกัดหน่วยความจำ → ผลคือ เคอร์เนลบังคับปิดโปรเซสเซิร์ฟเวอร์เกม → บนหน้าจอ ทุกคนในเซิร์ฟเวอร์นั้นหลุดพร้อมกัน ความคืบหน้าล่าสุดอาจโดนโรลแบ็ค
อาการ หลุด , กดไม่ติด/โรลแบ็ค
ปัจจัย การหยุดชะงัก
ใครเจอ ทั้งเซิร์ฟเวอร์
เกิดเมื่อไร ยิ่งเปิดไว้นานยิ่งเป็น, ตอนคนแห่มารวมกัน
ผู้รับผิดชอบ ผู้รับผิดชอบหลัก พัฒนาเซิร์ฟเวอร์ (ทีมพัฒนาเกม) · ร่วมกับ อินฟราเซิร์ฟเวอร์ (ทีมอินฟรา)
งานฝั่งทีมพัฒนาเกม แก้หน่วยความจำรั่ว, กำหนดเพดานการใช้หน่วยความจำและมีขั้นตอนบันทึกข้อมูลแล้วปิดอย่างปกติเมื่อใกล้เพดาน
งานฝั่งทีมอินฟรา ตั้ง alert หน่วยความจำ, ตั้งขีดจำกัดหน่วยความจำของคอนเทนเนอร์ให้เหมาะกับการใช้งานจริง, ปรับลำดับโปรเซสที่จะถูกปิดก่อน (oom_score_adj)
ตัวเลขที่ควรรู้ log ของเคอร์เนล (dmesg) จะมี “Out of memory: Killed process” และใน Kubernetes จะเห็นเป็น OOMKilled ส่วน Windows ไม่มี OOM killer และเซิร์ฟเวอร์มักล่มด้วยข้อผิดพลาดเมื่อจัดสรรหน่วยความจำไม่สำเร็จ
บนกราฟ การเชื่อมต่อหลุดพร้อมกัน · จำนวนการเชื่อมต่อ, ปริมาณการใช้หน่วยความจำ
จุดที่ต้องดู บันทึก “Out of memory: Killed process” ใน dmesg, OOMKilled ในสถานะพ็อด (Kubernetes) หรือ oom_kill ใน memory.events ที่เพิ่มขึ้น (cgroup v2) เทียบกับเวลาที่ผู้เล่นหลุด สัญญาณว่าใช่ ตอนที่การเชื่อมต่อหลุดพร้อมกัน มีบันทึกว่าโปรเซสเซิร์ฟเวอร์เกมถูกปิด และก่อนหน้านั้นการใช้หน่วยความจำไต่ขึ้นไปถึงขีดจำกัด สัญญาณว่าไม่ใช่ ไม่มีบันทึก OOM แต่โปรเซสตาย: ให้ดู crash log และ core dump ตาม “เซิร์ฟเวอร์แครช” วิธีตรวจ ใช้เครื่องมือฝั่งอินฟรา (ไม่ต้องใช้โค้ดเกม)
แหล่งอ้างอิง 4 รายการ
ID so-reclaim · ผู้รับผิดชอบหลัก อินฟราเซิร์ฟเวอร์ (ทีมอินฟรา) · ร่วมกับ พัฒนาเซิร์ฟเวอร์ (ทีมพัฒนาเกม)
โปรเซสจะหยุดชะงักระหว่างที่ OS ทำ compaction หน่วยความจำเพื่อสร้างเพจขนาดใหญ่ (huge page) หรือเรียกคืนหน่วยความจำให้ว่าง (reclaim)
ทำไม หน่วยความจำว่างเหลือน้อย หรือฟีเจอร์ huge page (THP) สั่ง compaction หน่วยความจำ → ผลคือ เธรดที่ขอหน่วยความจำต้องรอจนการ reclaim หรือ compaction เสร็จ → บนหน้าจอ เซิร์ฟเวอร์ค้างเป็นพัก ๆ แบบไม่สม่ำเสมอ (ไม่กี่ ms ถึงหลายร้อย ms)
อาการ ค้าง , กระตุก
ปัจจัย การหยุดชะงัก
ใครเจอ ทั้งเซิร์ฟเวอร์
เกิดเมื่อไร ยิ่งเปิดไว้นานยิ่งเป็น, สุ่มเป็นครั้งคราว
ผู้รับผิดชอบ ผู้รับผิดชอบหลัก อินฟราเซิร์ฟเวอร์ (ทีมอินฟรา) · ร่วมกับ พัฒนาเซิร์ฟเวอร์ (ทีมพัฒนาเกม)
งานฝั่งทีมพัฒนาเกม ลดการจัดสรรหน่วยความจำก้อนใหญ่ระหว่างรัน (จองไว้ล่วงหน้าตอนเริ่มแล้วใช้ซ้ำ)
งานฝั่งทีมอินฟรา ตั้งให้ใช้ huge page (THP) เฉพาะส่วนที่ร้องขอ (madvise), เพิ่มเกณฑ์หน่วยความจำว่างขั้นต่ำ (vm.min_free_kbytes เป็นต้น)
บนกราฟ พุ่งแบบสุ่มเป็นครั้งคราว · เวลาต่อทิกของเซิร์ฟเวอร์, PSI ของหน่วยความจำ
จุดที่ต้องดู some และ full ใน /proc/pressure/memory (สัดส่วนเวลาที่หยุดรอหน่วยความจำ) และค่าที่เพิ่มขึ้นของ compact_stall ใน /proc/vmstat ดูคู่กับเวลาต่อทิกของเซิร์ฟเวอร์ และตรวจค่า /sys/kernel/mm/transparent_hugepage/defrag สัญญาณว่าใช่ ตอนที่ทิกพุ่ง PSI ของหน่วยความจำสูงขึ้นและ compact_stall เพิ่มขึ้น defrag ตั้งเป็น always สัญญาณว่าไม่ใช่ PSI และ compact_stall ไม่ขยับ: ไม่ใช่สาเหตุนี้ ถ้าการใช้ swap เพิ่มขึ้น ให้ดู “สวอป” วิธีตรวจ ใช้เครื่องมือฝั่งอินฟรา (ไม่ต้องใช้โค้ดเกม)
แหล่งอ้างอิง 3 รายการ Transparent Hugepage Support Linux kernel ถ้า defrag=always เมื่อจัดสรร THP ไม่สำเร็จจะ reclaim และ compaction หน่วยความจำทันทีตรงนั้นและหยุดรอ, madvise จะทำแบบนั้นเฉพาะส่วนที่ร้องขอ Documentation for /proc/sys/vm/ Linux kernel min_free_kbytes: เกณฑ์หน่วยความจำว่างขั้นต่ำ (watermark) ที่เคอร์เนลกันไว้ PSI - Pressure Stall Information Linux kernel some (สัดส่วนเวลาที่งานบางส่วนหยุดรอหน่วยความจำ) และ full (สัดส่วนเวลาที่งานทั้งหมดหยุด) ใน /proc/pressure/memory
ID so-timejump · ผู้รับผิดชอบหลัก พัฒนาเซิร์ฟเวอร์ (ทีมพัฒนาเกม) · ร่วมกับ อินฟราเซิร์ฟเวอร์ (ทีมอินฟรา)
ถ้านาฬิกาของเซิร์ฟเวอร์ถูกปรับไปข้างหน้าหรือถอยหลังหลายวินาทีในครั้งเดียว ตัวจับเวลาที่อิงนาฬิการะบบจะทำงานพร้อมกันรวดเดียวหรือหยุดไป
ทำไม การซิงก์เวลาปรับนาฬิกาครั้งใหญ่ในครั้งเดียว → ผลคือ ตัวจับเวลาทำงานรวดเดียวหรือหยุด และตัดสินไทม์เอาต์ผิด → บนหน้าจอ บัฟและคูลดาวน์ผิดปกติ, หลุดพร้อมกันหลายคน, กรอเร็ว
อาการ กรอเร็ว , หลุด , กดไม่ติด/โรลแบ็ค
ปัจจัย การหยุดชะงัก
ใครเจอ ทั้งเซิร์ฟเวอร์
เกิดเมื่อไร สุ่มเป็นครั้งคราว
ผู้รับผิดชอบ ผู้รับผิดชอบหลัก พัฒนาเซิร์ฟเวอร์ (ทีมพัฒนาเกม) · ร่วมกับ อินฟราเซิร์ฟเวอร์ (ทีมอินฟรา)
งานฝั่งทีมพัฒนาเกม คำนวณเวลาที่ผ่านไป ไทม์เอาต์ และคูลดาวน์ด้วย monotonic clock ที่ไม่กระโดดและไม่ถอยหลัง, ใช้ wall clock เฉพาะการแสดงผลและการบันทึก log
งานฝั่งทีมอินฟรา ปรับนาฬิกาแบบค่อยเป็นค่อยไป (ใช้ makestep ของ chrony เฉพาะตอนเพิ่งเริ่มทำงาน), มอนิเตอร์สถานะการซิงก์เวลา (ความต่างของนาฬิกา)
ตัวเลขที่ควรรู้ ntpd จะปรับทีเดียวเมื่อต่างเกิน 0.128 วินาที ถ้าน้อยกว่านั้นจะค่อย ๆ ปรับด้วยอัตราที่ต้องใช้เวลา 30 นาทีเศษในการลบความต่าง 1 วินาที ส่วน chrony ที่นิยมใช้ในปัจจุบัน เมื่อใช้การตั้งค่าที่แนะนำ (makestep) จะปรับทีเดียวเพียงไม่กี่ครั้งหลังเริ่มทำงาน จากนั้นจะค่อย ๆ ปรับ นาฬิกายังกระโดดได้เมื่อ VM หยุดชั่วครู่แล้วกลับมาทำงาน
บนกราฟ พุ่งแบบสุ่มเป็นครั้งคราว · จำนวนครั้งที่ตัวจับเวลาทำงานและจำนวนการหลุด, บันทึกการปรับนาฬิกา
จุดที่ต้องดู บันทึกการปรับนาฬิกาครั้งใหญ่ใน log ของเซอร์วิสซิงก์เวลา เทียบกับเวลาที่เกิดปัญหา chrony จะเขียนลง syslog เมื่อปรับมากกว่าค่า logchange (ค่าเริ่มต้น 1 วินาที) สัญญาณว่าใช่ มีบันทึกการปรับนาฬิกาตรงกับเวลาที่บัฟและคูลดาวน์ผิดปกติ หลุดพร้อมกัน หรือกรอเร็ว และขนาดที่ปรับใกล้เคียงกับขนาดความผิดปกติ สัญญาณว่าไม่ใช่ ไม่มีบันทึกการปรับนาฬิกา: ไม่ใช่สาเหตุนี้ ถ้าเป็น VM ให้ดูกรณีที่หยุดแล้วกลับมาทำงานด้วย (“การซ่อมบำรุงโฮสต์คลาวด์/live migration”) วิธีตรวจ ใช้เครื่องมือฝั่งอินฟรา (ไม่ต้องใช้โค้ดเกม)
แหล่งอ้างอิง 4 รายการ
ID so-cron · ผู้รับผิดชอบหลัก อินฟราเซิร์ฟเวอร์ (ทีมอินฟรา)
งานบีบอัด log, การสำรองข้อมูล และการสแกนความปลอดภัยที่รันเวลาเดิมทุกวันจะกิน CPU และดิสก์
ทำไม งานของ OS เริ่มรันตามเวลาที่กำหนด → ผลคือ แย่ง CPU และดิสก์กับเซิร์ฟเวอร์เกม → บนหน้าจอ กระตุกและสโลว์โมชั่นในเวลาเดิม เช่น 04:00 ทุกวัน
อาการ กระตุก , สโลว์โมชั่น
ปัจจัย การหยุดชะงัก
ใครเจอ ทั้งเซิร์ฟเวอร์
เกิดเมื่อไร เป็นรอบสม่ำเสมอ
ผู้รับผิดชอบ ผู้รับผิดชอบหลัก อินฟราเซิร์ฟเวอร์ (ทีมอินฟรา)
งานฝั่งทีมอินฟรา กระจายเวลาของงาน, ลดลำดับความสำคัญ (nice, ionice), แยกออกจากเซิร์ฟเวอร์เกม (รันบนเซิร์ฟเวอร์อื่น)
บนกราฟ พุ่งเป็นรอบ · อัตราการใช้ CPU, คิวดิสก์, เวลาต่อทิกของเซิร์ฟเวอร์
จุดที่ต้องดู เวลารันของงานตามกำหนดเวลาจาก crontab และ systemctl list-timers และโปรเซสที่ใช้ CPU และดิสก์ตอนที่ทิกพุ่งจาก pidstat -u -d สัญญาณว่าใช่ ทิกพุ่งเวลาเดิมทุกวัน (หรือทุกชั่วโมง) และตอนนั้นโปรเซสของงานตามกำหนดเวลากิน CPU และดิสก์ สัญญาณว่าไม่ใช่ เวลาที่พุ่งไม่ตรงกับเวลาเดิมของแต่ละวัน: ไม่ใช่สาเหตุนี้ ถ้าพุ่งทุกไม่กี่วินาทีหรือไม่กี่นาที ให้ดู “GC ของเซิร์ฟเวอร์หยุดทั้งระบบ”, “ตัวจับเวลาทำงานพร้อมกันจำนวนมาก” วิธีตรวจ ใช้เครื่องมือฝั่งอินฟรา (ไม่ต้องใช้โค้ดเกม)
แหล่งอ้างอิง 4 รายการ
ID so-os-update · ผู้รับผิดชอบหลัก อินฟราเซิร์ฟเวอร์ (ทีมอินฟรา)
โค้ดเกมเหมือนเดิม แต่เซิร์ฟเวอร์ช้าลงตั้งแต่อัปเดต OS, เคอร์เนล, ไดรเวอร์ หรือเฟิร์มแวร์ การอัปเดตอาจเปลี่ยนค่าเริ่มต้น, scheduler, การป้องกันช่องโหว่ CPU (mitigations) และพฤติกรรมของไดรเวอร์
ทำไม แพตช์ความปลอดภัยตามรอบหรืออิมเมจเซิร์ฟเวอร์ใหม่ทำให้เคอร์เนล ไดรเวอร์ หรือเฟิร์มแวร์เปลี่ยน → ผลคือ ค่าเริ่มต้นหรือ scheduler เปลี่ยน หรือเปิด mitigation ตัวใหม่ งานเดิมจึงใช้ CPU time มากขึ้น และลำดับที่เธรดได้รับ CPU เปลี่ยนไป → บนหน้าจอ เซิร์ฟเวอร์ที่เคยลื่นช้าลงนิดหน่อยตลอดเวลาตั้งแต่วันที่อัปเดต: อินพุตดีเลย์ และพอคนแห่มารวมกันก็กระตุกและเป็นสโลว์โมชั่น
อาการ อินพุตดีเลย์ , กระตุก , สโลว์โมชั่น
ปัจจัย ความหน่วง, การหยุดชะงัก, จิตเตอร์
ใครเจอ ทั้งเซิร์ฟเวอร์
เกิดเมื่อไร ตลอดเวลา, ตอนคนแห่มารวมกัน
ผู้รับผิดชอบ ผู้รับผิดชอบหลัก อินฟราเซิร์ฟเวอร์ (ทีมอินฟรา)
งานฝั่งทีมอินฟรา ลงอัปเดตกับเซิร์ฟเวอร์บางเครื่องก่อน แล้วเทียบเวลาต่อทิก ความหน่วง และอัตราการใช้ CPU กับเวอร์ชันก่อนหน้าก่อนขยายวง, deploy คนละวันกับแพตช์เกม, บันทึกเวอร์ชันเคอร์เนล ไดรเวอร์ เฟิร์มแวร์ และค่า sysctl สำคัญก่อนและหลังอัปเดต, ถ้ามีปัญหาให้บูตด้วยเคอร์เนลเดิมเพื่อยืนยัน, ชั่งความเสี่ยงด้านความปลอดภัยก่อนตัดสินใจปิด mitigation (mitigations=off)
ตัวเลขที่ควรรู้ เมื่อเวอร์ชันเคอร์เนลเปลี่ยน พฤติกรรมเริ่มต้นก็เปลี่ยนด้วย เช่น Linux เริ่มย้าย scheduler จาก CFS ไปเป็น EEVDF ตั้งแต่ 6.6 และค่าเริ่มต้นของเพดานคิวรอเชื่อมต่อ (somaxconn) ก็เปลี่ยนจาก 128 เป็น 4,096 ตั้งแต่ 5.4 การป้องกันช่องโหว่ CPU เพิ่มงาน เช่น ล้างบัฟเฟอร์ภายใน CPU ตอนกลับจากเคอร์เนลไปยังโปรแกรม (ทุกครั้งที่จบ system call) และตอน context switch หรือสลับเข้าออก VM เซิร์ฟเวอร์เครือข่ายที่เรียก system call ทุกแพ็กเก็ตจึงได้รับผลมากกว่า ช่องโหว่บางตัวต้องปิด SMT (ฟีเจอร์ที่ให้หนึ่งคอร์ทำงานเหมือนสองเธรด) จึงจะป้องกันได้สมบูรณ์ และการปิด SMT อาจทำให้ประสิทธิภาพลดลงมากแล้วแต่ประเภทงาน พารามิเตอร์เคอร์เนล mitigations=off ปิดการป้องกันทั้งหมดนี้เพื่อเอาประสิทธิภาพคืน แต่ระบบจะเสี่ยงต่อช่องโหว่เหล่านั้น
บนกราฟ ขึ้นเป็นขั้นบันไดจากจุดหนึ่ง · เวลาต่อทิกของเซิร์ฟเวอร์, อัตราการใช้ CPU, ความหน่วงที่โหลดเท่ากัน
จุดที่ต้องดู ประวัติการอัปเดตจาก package manager และเวลารีบูต, เวอร์ชันเคอร์เนลจาก uname -r, ข้อมูลไดรเวอร์ NIC จาก ethtool -i เทียบกับเวลาที่ความหน่วงเริ่มสูง และเทียบเซิร์ฟเวอร์ที่อัปเดตกับที่ยังไม่อัปเดตภายใต้โหลดเท่ากันด้วย mpstat และ pidstat รวมถึงสถานะ mitigation ใน /sys/devices/system/cpu/vulnerabilities/ สัญญาณว่าใช่ ความหน่วงและอัตราการใช้ CPU ขึ้นหนึ่งขั้นตั้งแต่รีบูตหลังอัปเดตแล้วอยู่ระดับนั้น ที่โหลดเท่ากัน เฉพาะเซิร์ฟเวอร์ที่อัปเดตเท่านั้นที่สูง บูตด้วยเคอร์เนลหรือไดรเวอร์เดิมแล้วกลับเป็นปกติ สัญญาณว่าไม่ใช่ เซิร์ฟเวอร์ที่อัปเดตกับที่ยังไม่อัปเดตช้าเท่ากันที่โหลดเท่ากัน: ไม่ใช่สาเหตุนี้ ถ้าวันเดียวกัน deploy แพตช์เกมด้วย และจำนวนหรือขนาดแพ็กเก็ตต่อผู้เล่นเปลี่ยน ให้ดู “แพตช์ทำให้รูปแบบทราฟฟิกเปลี่ยน” วิธีตรวจ ใช้เครื่องมือฝั่งอินฟรา (ไม่ต้องใช้โค้ดเกม)
รายละเอียดเพิ่มเติม ตรวจสถานะ mitigation ได้จากไฟล์ใต้ /sys/devices/system/cpu/vulnerabilities/ ค่าเริ่มต้น (mitigations=auto) ป้องกันโดยยังเปิด SMT ไว้ แต่ถ้าตั้ง auto,nosmt จะปิด SMT บน CPU ที่มีช่องโหว่ หลังอัปเกรดเคอร์เนล จำนวนคอร์ตรรกะ (logical core) จึงอาจลดลงครึ่งหนึ่ง ถ้าอัปเดต OS วันเดียวกับแพตช์เกมจะแยกสาเหตุได้ยาก จึงควร deploy แยกกัน
แหล่งอ้างอิง 6 รายการ The kernel’s command-line parameters Linux kernel mitigations=: off ปิดการป้องกันช่องโหว่ CPU ทั้งหมดเพื่อเพิ่มประสิทธิภาพแต่จะเสี่ยงต่อช่องโหว่, ค่าเริ่มต้น auto ป้องกันโดยเปิด SMT ไว้, auto,nosmt ปิด SMT เมื่อจำเป็น MDS - Microarchitectural Data Sampling Linux kernel mitigation จะล้างบัฟเฟอร์ CPU ตอนกลับจากเคอร์เนลไปยัง user space และตอนเข้า VM, ตรวจสถานะช่องโหว่และ mitigation ได้จากไฟล์ใต้ /sys/devices/system/cpu/vulnerabilities/, CPU จำนวนมากต้องปิด SMT จึงจะป้องกันได้สมบูรณ์ และการปิด SMT อาจกระทบประสิทธิภาพมากแล้วแต่งาน Spectre Side Channels Linux kernel เพื่อป้องกันช่องโหว่ จะล้างบัฟเฟอร์ branch prediction ตอน context switch และตอนสลับ VM, mitigation แบบเข้มเพิ่ม overhead ให้ทุกโปรแกรม EEVDF Scheduler Linux kernel Linux เริ่มย้ายจาก CFS ไปใช้ scheduler EEVDF ตั้งแต่ 6.6 listen(2) — Linux manual page Linux man-pages ค่าเริ่มต้นของ somaxconn เปลี่ยนจาก 128 เป็น 4,096 ตั้งแต่ Linux 5.4 ethtool(8) — Linux manual page ethtool ดูข้อมูลไดรเวอร์ของอุปกรณ์เครือข่ายด้วย ethtool -i
ID so-conntrack · ผู้รับผิดชอบหลัก อินฟราเซิร์ฟเวอร์ (ทีมอินฟรา) · ร่วมกับ พัฒนาเซิร์ฟเวอร์ (ทีมพัฒนาเกม), พัฒนาไคลเอนต์ (ทีมพัฒนาเกม)
เมื่อตาราง connection tracking (conntrack) ที่ไฟร์วอลล์ของ Linux ใช้บันทึกทุกการเชื่อมต่อแตะขีดจำกัด แพ็กเก็ตใหม่จะถูกทิ้ง
ทำไม การเชื่อมต่อทะลักและการเชื่อมต่อสั้น ๆ ซ้ำไปมาทำให้รายการในตารางเพิ่มขึ้น → ผลคือ ตารางเต็ม การเชื่อมต่อใหม่และแพ็กเก็ตบางส่วนถูกทิ้ง → บนหน้าจอ เข้าเกมไม่ได้ และวาร์ปเพราะแพ็กเก็ตหายโดยไม่รู้สาเหตุ
อาการ เข้าเกมไม่ได้/โหลดไม่จบ , วาร์ป
ปัจจัย แพ็กเก็ตหาย
ใครเจอ ทั้งเซิร์ฟเวอร์
เกิดเมื่อไร หลังล็อกอิน/หลังปิดปรับปรุง, ตอนคนแห่มารวมกัน
ผู้รับผิดชอบ ผู้รับผิดชอบหลัก อินฟราเซิร์ฟเวอร์ (ทีมอินฟรา) · ร่วมกับ พัฒนาเซิร์ฟเวอร์ (ทีมพัฒนาเกม), พัฒนาไคลเอนต์ (ทีมพัฒนาเกม)
งานฝั่งทีมพัฒนาเกม เซิร์ฟเวอร์: ลดการเชื่อมต่อสั้น ๆ (ใช้การเชื่อมต่อซ้ำสำหรับการเรียกระหว่างเซิร์ฟเวอร์) ไคลเอนต์: เมื่อเชื่อมต่อไม่สำเร็จหรือหลุด ให้เพิ่มช่วงห่างการลองใหม่ขึ้นเรื่อย ๆ และสุ่มให้กระจาย
งานฝั่งทีมอินฟรา เพิ่มขนาดตาราง (nf_conntrack_max), ไม่ติดตามพอร์ตเกม (NOTRACK ในตาราง raw), ตั้ง alert ปริมาณการใช้งาน
ตัวเลขที่ควรรู้ ขีดจำกัดเริ่มต้นอยู่ที่ประมาณ 60,000–260,000 รายการตามขนาดหน่วยความจำของเซิร์ฟเวอร์ ถ้าล้น log ของเคอร์เนลจะมี “nf_conntrack: table full, dropping packet”
บนกราฟ ชนเพดานแล้วแบนราบ · จำนวนรายการ conntrack (nf_conntrack_count)
จุดที่ต้องดู net.netfilter.nf_conntrack_count (จำนวนรายการปัจจุบัน) จาก sysctl วางบนกราฟเดียวกับ nf_conntrack_max และหา “nf_conntrack: table full, dropping packet” ใน dmesg สัญญาณว่าใช่ nf_conntrack_count แบนราบที่ค่า max และตั้งแต่ตอนนั้น log ของเคอร์เนลขึ้น table full สัญญาณว่าไม่ใช่ จำนวนรายการยังห่างจาก max มาก: ไม่ใช่สาเหตุนี้ ขีดจำกัด connection tracking ของตัวอินสแตนซ์ AWS เองให้ดู conntrack_allowance_exceeded ใน “เกินขีดจำกัด PPS ของคลาวด์” วิธีตรวจ ใช้เครื่องมือฝั่งอินฟรา (ไม่ต้องใช้โค้ดเกม)
แหล่งอ้างอิง 3 รายการ
ID so-ports · ผู้รับผิดชอบหลัก พัฒนาเซิร์ฟเวอร์ (ทีมพัฒนาเกม) · ร่วมกับ อินฟราเซิร์ฟเวอร์ (ทีมอินฟรา)
ถ้าเซิร์ฟเวอร์เกมเปิดและปิดการเชื่อมต่อสั้น ๆ ไปยัง DB หรือเซิร์ฟเวอร์อื่นบ่อย ๆ การเชื่อมต่อที่ปิดแล้วจะยังถือครองพอร์ตอยู่สักพัก จนเปิดการเชื่อมต่อใหม่ไม่ได้
ทำไม เปิดและปิดการเชื่อมต่อใหม่ทุกคำขอ → ผลคือ ฝั่งที่ปิดก่อนจะถือครองพอร์ตไว้ประมาณ 60 วินาทีบน Linux (TIME_WAIT) จนพอร์ตที่ใช้ได้หมด → บนหน้าจอ คำขอภายในล้มเหลว: บันทึกข้อมูลไม่สำเร็จ, ฟีเจอร์ทำงานผิดพลาด
อาการ กดไม่ติด/โรลแบ็ค , เข้าเกมไม่ได้/โหลดไม่จบ
ปัจจัย แพ็กเก็ตหาย
ใครเจอ ทั้งเซิร์ฟเวอร์, เฉพาะบางฟีเจอร์
เกิดเมื่อไร ตอนคนแห่มารวมกัน
ผู้รับผิดชอบ ผู้รับผิดชอบหลัก พัฒนาเซิร์ฟเวอร์ (ทีมพัฒนาเกม) · ร่วมกับ อินฟราเซิร์ฟเวอร์ (ทีมอินฟรา)
งานฝั่งทีมพัฒนาเกม ใช้การเชื่อมต่อซ้ำ (connection pool), เลิกเปิดและปิดการเชื่อมต่อใหม่ทุกคำขอ
งานฝั่งทีมอินฟรา ขยายช่วงพอร์ต (ip_local_port_range), พิจารณาใช้ TIME_WAIT ซ้ำสำหรับการเชื่อมต่อขาออก (tcp_tw_reuse ของ Linux), มอนิเตอร์จำนวน TIME_WAIT
ตัวเลขที่ควรรู้ ช่วงพอร์ตเริ่มต้นของ Linux (32768–60999) มีประมาณ 28,000 พอร์ต ถ้าเปิดการเชื่อมต่อใหม่ไปยังปลายทางเดียวกันเกิน 470 ครั้งใน 1 วินาที พอร์ตจะหมด Windows มีพอร์ตเริ่มต้นประมาณ 16,000 พอร์ต (49152–65535) และ TIME_WAIT ยาวกว่า จึงหมดเร็วกว่า
บนกราฟ ชนเพดานแล้วแบนราบ · จำนวนซ็อกเก็ต TIME_WAIT, จำนวนการเชื่อมต่อภายในที่ล้มเหลว
จุดที่ต้องดู นับซ็อกเก็ต TIME_WAIT แยกตามปลายทางด้วย ss -tan state time-wait และหา connect ที่ล้มเหลว (EADDRNOTAVAIL) ใน log ของเซิร์ฟเวอร์เกม สัญญาณว่าใช่ TIME_WAIT ไปยังปลายทางเดียวกัน (เช่น DB) แบนราบใกล้ขนาดช่วง ephemeral port (ค่าเริ่มต้นประมาณ 28,000) และ connect ล้มเหลวด้วย EADDRNOTAVAIL สัญญาณว่าไม่ใช่ TIME_WAIT น้อย แต่เฉพาะการเชื่อมต่อออกไปภายนอกที่ล้มเหลว: ให้ดู “ขีดจำกัดการเชื่อมต่อ/พอร์ตของ NAT gateway บนคลาวด์” วิธีตรวจ ใช้เครื่องมือฝั่งอินฟรา (ไม่ต้องใช้โค้ดเกม)
รายละเอียดเพิ่มเติม TIME_WAIT 60 วินาทีของ Linux เป็นค่าที่ฝังตายตัวในเคอร์เนล การลด tcp_fin_timeout ซึ่งชื่อคล้ายกันไม่ได้ทำให้ TIME_WAIT สั้นลง
แหล่งอ้างอิง 5 รายการ
L8 ซ็อกเก็ตและโปรโตคอล
14 สาเหตุ · บทในฉบับหลัก
ID sk-hol · ผู้รับผิดชอบหลัก พัฒนาเซิร์ฟเวอร์ (ทีมพัฒนาเกม) · ร่วมกับ พัฒนาไคลเอนต์ (ทีมพัฒนาเกม)
เพื่อรักษาลำดับข้อมูล TCP จะไม่ส่งแพ็กเก็ตที่มาถึงทีหลังให้เกม จนกว่าจะได้รับแพ็กเก็ตที่หายไปหนึ่งตัวนั้นอีกครั้ง
ทำไม แพ็กเก็ตหายไปหนึ่งตัว → ผลคือ แพ็กเก็ตที่ตามมามาถึงแล้ว แต่ต้องรออยู่ใน receive buffer → บนหน้าจอ ค้างไปก่อนแล้วปล่อยออกมารวดเดียวเป็นอาการกรอเร็ว
อาการ ค้าง , กรอเร็ว
ปัจจัย แพ็กเก็ตหาย, การหยุดชะงัก
ใครเจอ เราคนเดียว
เกิดเมื่อไร สุ่มเป็นครั้งคราว
ผู้รับผิดชอบ ผู้รับผิดชอบหลัก พัฒนาเซิร์ฟเวอร์ (ทีมพัฒนาเกม) · ร่วมกับ พัฒนาไคลเอนต์ (ทีมพัฒนาเกม)
งานฝั่งทีมพัฒนาเกม เซิร์ฟเวอร์: ส่งตำแหน่งแบบเรียลไทม์ทาง UDP, ใช้การส่งแบบ reliable เฉพาะข้อมูลที่จำเป็นจริง ๆ, แบ่งเป็นหลาย stream ไคลเอนต์: เปลี่ยนการจัดการเครือข่ายให้ตรงกับเซิร์ฟเวอร์ (UDP, แยกช่องทาง)
ตัวเลขที่ควรรู้ ถ้าแพ็กเก็ตหายหนึ่งตัว จะหยุดอย่างน้อยเท่ากับเวลาไปกลับ + α ถ้าแพ็กเก็ตที่ส่งซ้ำหายอีก จะหยุดหลายร้อย ms ถึงหลายวินาที
บนกราฟ ขาดช่วงแล้วมารวดเดียว · ปริมาณข้อมูลที่รับต่อการเชื่อมต่อ, จำนวนการส่งซ้ำ
จุดที่ต้องดู แพ็กเก็ตที่ส่งซ้ำและช่วงว่างก่อนและหลังแพ็กเก็ตนั้นในการเชื่อมต่อของผู้เล่นคนนั้น จาก packet capture ฝั่งเซิร์ฟเวอร์ (tcpdump, Wireshark) ส่วนทั้งเซิร์ฟเวอร์ดูค่าที่เพิ่มขึ้นของ TcpRetransSegs จาก nstat -az สัญญาณว่าใช่ ช่วงที่หยุดเริ่มด้วยการส่งซ้ำของแพ็กเก็ตเดียว และทันทีที่แพ็กเก็ตที่ส่งซ้ำมาถึง ข้อมูลที่กองรอก็ถูกประมวลผลรวดเดียว (ปริมาณที่รับเป็น 0 แล้วพุ่ง) สัญญาณว่าไม่ใช่ เกมที่สื่อสารทาง UDP: ไม่เกี่ยว ถ้าไม่มีการส่งซ้ำแต่ยังหยุด ให้ดูฝั่งทิกของเซิร์ฟเวอร์ (“ทิกเกินงบเวลา”) วิธีตรวจ ใช้เครื่องมือฝั่งอินฟรา (ไม่ต้องใช้โค้ดเกม)
แหล่งอ้างอิง 4 รายการ
ID sk-rto · ผู้รับผิดชอบหลัก พัฒนาเซิร์ฟเวอร์ (ทีมพัฒนาเกม) · ร่วมกับ พัฒนาไคลเอนต์ (ทีมพัฒนาเกม)
ทุกครั้งที่การส่งซ้ำล้มเหลวอีก เวลารอจะเพิ่มเป็นสองเท่า การเชื่อมต่อที่ขาดไปแป๊บเดียวจึงกลายเป็นการหยุดยาว
ทำไม การเชื่อมต่อขาดไปแป๊บหนึ่ง การส่งซ้ำจึงล้มเหลวติดต่อกัน → ผลคือ เวลารอก่อนลองครั้งถัดไปเพิ่มเป็นสองเท่าทุกครั้ง เช่น 0.3 → 0.6 → 1.2 → 2.4 วินาที (ที่ปิง 100 ms) → บนหน้าจอ เน็ตขาดแค่ 1 วินาที แต่เกมค้างเกิน 2 วินาที ถ้าขาดนานกว่านั้นสุดท้ายก็หลุด
อาการ ค้าง , หลุด
ปัจจัย แพ็กเก็ตหาย, การหยุดชะงัก
ใครเจอ เราคนเดียว
เกิดเมื่อไร สุ่มเป็นครั้งคราว, ระหว่างเดินทาง/ย้ายแมพ
ผู้รับผิดชอบ ผู้รับผิดชอบหลัก พัฒนาเซิร์ฟเวอร์ (ทีมพัฒนาเกม) · ร่วมกับ พัฒนาไคลเอนต์ (ทีมพัฒนาเกม)
งานฝั่งทีมพัฒนาเกม เซิร์ฟเวอร์: ตอบ heartbeat และถ้าไม่ได้รับนานเกินกำหนดให้ปิดการเชื่อมต่อเองก่อน (ร่นจุดที่เลิกรอด้วย TCP_USER_TIMEOUT), ใช้ session token เพื่อต่อเซสชันเดิม, ใช้ reliable UDP ไคลเอนต์: ส่ง heartbeat ถี่ ๆ และเมื่อการตอบกลับขาดหาย ให้เชื่อมต่อใหม่ทันทีโดยไม่ต้องรอการส่งซ้ำของ TCP
ตัวเลขที่ควรรู้ RTO (เวลารอก่อนส่งซ้ำ) ของ Linux มีค่าต่ำสุดเป็น “ปิง + 200 ms” และตอนเริ่มเชื่อมต่อจะเริ่มที่ 1 วินาที ถ้าใช้ค่าเริ่มต้น (tcp_retries2=15) ต่อให้ส่งซ้ำล้มเหลวต่อเนื่อง ก็จะเลิกเชื่อมต่อหลังผ่านไปประมาณ 15 นาที
บนกราฟ ขาดช่วงแล้วมารวดเดียว · RTO และ backoff ต่อการเชื่อมต่อ, จำนวนครั้งที่ RTO หมดเวลา
จุดที่ต้องดู rto (เวลารอส่งซ้ำ ms) และ backoff (จำนวนครั้งที่หมดเวลาติดกัน) ของการเชื่อมต่อที่หยุดจาก ss -ti ส่วนทั้งเซิร์ฟเวอร์ดูค่าที่เพิ่มขึ้นของ TcpExtTCPTimeouts (จำนวนครั้งที่ตัวจับเวลาส่งซ้ำหมดเวลา) จาก nstat -az สัญญาณว่าใช่ backoff ของการเชื่อมต่อที่หยุดอยู่ตั้งแต่ 1 ขึ้นไป rto โตจนเป็นระดับวินาที และตอนนั้น TCPTimeouts เพิ่มขึ้น สัญญาณว่าไม่ใช่ การส่งซ้ำจบด้วย fast retransmit และไม่มี RTO หมดเวลา: การหยุดจะสั้น กรณีนั้นให้ดู “TCP HOL blocking” วิธีตรวจ ใช้เครื่องมือฝั่งอินฟรา (ไม่ต้องใช้โค้ดเกม)
แหล่งอ้างอิง 6 รายการ
ID sk-nagle · ผู้รับผิดชอบหลัก พัฒนาเซิร์ฟเวอร์ (ทีมพัฒนาเกม) · ร่วมกับ พัฒนาไคลเอนต์ (ทีมพัฒนาเกม)
อัลกอริทึม Nagle ที่รวบรวมแพ็กเก็ตเล็กก่อนส่ง กับ delayed ACK ที่ส่ง ACK ช้า ทำงานประกบกัน ทุกครั้งที่เขียนข้อความแบ่งเป็นหลายส่วนจึงดีเลย์ 40–200 ms
ทำไม เขียนข้อความเล็ก ๆ แบ่งเป็นหลายส่วนโดยไม่ได้เปิด TCP_NODELAY → ผลคือ ฝั่งส่งรอ ACK ส่วนฝั่งรับส่ง ACK ช้า → บนหน้าจอ ปิงต่ำ แต่ทุกการกระทำตอบสนองช้าสม่ำเสมอ: อินพุตดีเลย์
อาการ อินพุตดีเลย์
ปัจจัย ความหน่วง
ใครเจอ ทั้งเซิร์ฟเวอร์, เราคนเดียว
เกิดเมื่อไร ตลอดเวลา, ตอนทำแอ็กชันบางอย่าง
ผู้รับผิดชอบ ผู้รับผิดชอบหลัก พัฒนาเซิร์ฟเวอร์ (ทีมพัฒนาเกม) · ร่วมกับ พัฒนาไคลเอนต์ (ทีมพัฒนาเกม)
งานฝั่งทีมพัฒนาเกม เซิร์ฟเวอร์: เปิด TCP_NODELAY, รวบรวมข้อความในหนึ่งทิกแล้วเขียนครั้งเดียว, อย่าพึ่งวิธีปิด delayed ACK ฝั่งรับ (TCP_QUICKACK ของ Linux มีผลแค่ชั่วครู่ ส่วน Windows ต้องแก้ registry ทีละเครื่อง) เพราะเกมควบคุมได้ไม่แน่นอน ไคลเอนต์: เปิด TCP_NODELAY, รวบรวมข้อความในหนึ่งเฟรมแล้วเขียนครั้งเดียว
ตัวเลขที่ควรรู้ delayed ACK ของ Linux ปกติอยู่ที่ 40 ms (สูงสุด 200 ms แล้วแต่สถานการณ์) Windows รุ่นเก่าใช้ 200 ms ส่วนรุ่นปัจจุบันใช้ 40 ms (เทมเพลตเริ่มต้นของ Windows Server 2019 คือ 40 ms) OS ฝั่งรับเป็นผู้กำหนด delayed ACK ถ้าเซิร์ฟเวอร์เปิด Nagle ไว้แล้วส่งข้อความแบ่งเป็นหลายส่วน ก็อาจดีเลย์ครั้งละ 40–200 ms แล้วแต่ PC ที่รับ
บนกราฟ สูงตลอดตั้งแต่แรก · เวลาตอบสนองของแอ็กชัน (RTT ในเกม)
จุดที่ต้องดู ช่วงห่างระหว่างคำขอกับการตอบกลับใน packet capture ฝั่งเซิร์ฟเวอร์ (tcpdump, Wireshark) และตรวจว่าโค้ดเซิร์ฟเวอร์และไคลเอนต์เปิด TCP_NODELAY หรือไม่ สัญญาณว่าใช่ ปิงต่ำ แต่มีช่วงว่างราว 40 ms (Windows รุ่นเก่า 200 ms) ระหว่างแพ็กเก็ตเล็กซ้ำ ๆ และช่วงว่างนั้นจบทันทีที่ ACK จากอีกฝั่งมาถึง เปิด TCP_NODELAY แล้วหายไป สัญญาณว่าไม่ใช่ ช่วงห่างการตอบกลับใกล้เคียงปิง: ไม่ใช่สาเหตุนี้ ถ้าเซิร์ฟเวอร์เกมสร้างการตอบกลับช้า น่าจะเป็นฝั่งการประมวลผลของเซิร์ฟเวอร์ (“ข้อความสะสมในคิว”) วิธีตรวจ ใช้เครื่องมือฝั่งอินฟรา (ไม่ต้องใช้โค้ดเกม)
แหล่งอ้างอิง 5 รายการ
ID sk-block-send · ผู้รับผิดชอบหลัก พัฒนาเซิร์ฟเวอร์ (ทีมพัฒนาเกม)
ถ้า send buffer ของผู้เล่นคนหนึ่งที่เน็ตช้าเต็ม แล้วเซิร์ฟเวอร์ส่งแบบ blocking (การส่งที่ฟังก์ชันจะไม่คืนค่าจนกว่าบัฟเฟอร์จะมีที่ว่าง) เธรดของเซิร์ฟเวอร์จะต้องรอผู้เล่นคนนั้นคนเดียว
ทำไม send buffer ของไคลเอนต์ที่ช้าเต็ม → ผลคือ เป็นการส่งแบบ blocking เธรดของเซิร์ฟเวอร์จึงรอจนบัฟเฟอร์มีที่ว่าง → บนหน้าจอ ทุกคนที่เธรดนั้นดูแลค้างหรือเป็นสโลว์โมชั่น
อาการ ค้าง , สโลว์โมชั่น
ปัจจัย การหยุดชะงัก
ใครเจอ บางจุด/บางแชนแนล, ทั้งเซิร์ฟเวอร์
เกิดเมื่อไร สุ่มเป็นครั้งคราว, ตอนคนแห่มารวมกัน
ผู้รับผิดชอบ ผู้รับผิดชอบหลัก พัฒนาเซิร์ฟเวอร์ (ทีมพัฒนาเกม)
งานฝั่งทีมพัฒนาเกม ใช้การส่งแบบ non-blocking, จำกัดความยาวคิวส่งของแต่ละไคลเอนต์, ทิ้งอัปเดตที่เก่าแล้ว
บนกราฟ พุ่งแบบสุ่มเป็นครั้งคราว · เวลาต่อทิกของเซิร์ฟเวอร์, Send-Q ต่อการเชื่อมต่อ
จุดที่ต้องดู หาการเชื่อมต่อที่ Send-Q (ไบต์ที่ยังไม่ได้รับ ACK หรือยังไม่ได้ส่ง) เต็มเท่าขนาด send buffer ด้วย ss -tn และดู thread dump (stack) ของเซิร์ฟเวอร์เกมตอนที่ทิกพุ่งว่ามีเธรดที่หยุดอยู่ใน send หรือไม่ สัญญาณว่าใช่ ขณะที่มีการเชื่อมต่อช้าที่ Send-Q เต็ม เธรดที่ดูแลการเชื่อมต่อนั้นหยุดอยู่ใน send และเฉพาะคนที่อยู่ในเธรดเดียวกันเท่านั้นที่หยุดไปด้วย สัญญาณว่าไม่ใช่ เธรดที่หยุดรออยู่นอก send (ล็อก, การเรียก DB): ให้ดู “การแย่งล็อก”, “synchronous call บนเธรดเกม” วิธีตรวจ ใช้เครื่องมือฝั่งอินฟรา (ไม่ต้องใช้โค้ดเกม)
แหล่งอ้างอิง 3 รายการ send(2) — Linux manual page Linux man-pages ถ้า send buffer ไม่มีที่ว่าง send() จะถูกบล็อก ส่วนโหมด non-blocking จะคืนค่า EAGAIN ทันที send function (winsock2.h) Microsoft Winsock ก็เช่นกัน ถ้าพื้นที่บัฟเฟอร์ไม่พอ send จะถูกบล็อก เว้นแต่อยู่ในโหมด non-blocking net/ipv4/tcp_diag.c (Linux v6.12) Linux kernel ค่า Recv-Q และ Send-Q ของ ss: ซ็อกเก็ตที่ listen อยู่คือจำนวนการเชื่อมต่อที่รอ accept และขีดจำกัด backlog, ซ็อกเก็ตที่เชื่อมต่อแล้วคือไบต์ที่แอปยังไม่ได้อ่าน และไบต์ที่ส่งไปแล้วแต่ยังไม่ได้รับ ACK
ID sk-slow-client · ผู้รับผิดชอบหลัก พัฒนาเซิร์ฟเวอร์ (ทีมพัฒนาเกม)
เมื่อข้อมูลที่ต้องส่งให้ไคลเอนต์ใดกองสะสมเรื่อย ๆ เซิร์ฟเวอร์จะทิ้งอัปเดตเก่าหรือตัดการเชื่อมต่อ
ทำไม เน็ตของไคลเอนต์รับไม่ทันปริมาณที่เซิร์ฟเวอร์ส่ง → ผลคือ เซิร์ฟเวอร์ทิ้งอัปเดตเก่า หรือตัดการเชื่อมต่อเมื่อเกินขีดจำกัด → บนหน้าจอ เฉพาะคนนั้นวาร์ปหรือหลุด
อาการ วาร์ป , หลุด
ปัจจัย แพ็กเก็ตหาย
ใครเจอ เราคนเดียว
เกิดเมื่อไร ตอนคนแห่มารวมกัน
ผู้รับผิดชอบ ผู้รับผิดชอบหลัก พัฒนาเซิร์ฟเวอร์ (ทีมพัฒนาเกม)
งานฝั่งทีมพัฒนาเกม ลดปริมาณที่ส่ง (ความถี่อัปเดตตามระยะห่าง), ลดคุณภาพแต่ยังส่งต่อไป, ลดปริมาณข้อมูลที่กองไว้ในเคอร์เนล (TCP_NOTSENT_LOWAT ของ Linux)
ตัวเลขที่ควรรู้ ถ้า send buffer มีขนาด 256 KB บนเน็ต 30 KB/s จะมีข้อมูลกองรอเกิน 8 วินาที และบางครั้ง Linux ยังขยายบัฟเฟอร์นี้เองได้ถึงหลาย MB
บนกราฟ สูงเฉพาะบางกลุ่ม · Send-Q ต่อการเชื่อมต่อ, จำนวนอัปเดตที่ทิ้งต่อไคลเอนต์
จุดที่ต้องดู ความยาวคิวส่ง จำนวนอัปเดตที่ทิ้ง และสาเหตุการหลุดของแต่ละไคลเอนต์ที่เซิร์ฟเวอร์เกมบันทึกไว้ และ Send-Q กับ cwnd ของการเชื่อมต่อนั้นคู่กันจาก ss -tni บนเซิร์ฟเวอร์ สัญญาณว่าใช่ เฉพาะการเชื่อมต่อของคนที่วาร์ปหรือหลุดเท่านั้นที่ Send-Q เต็มตลอด และ log ของเกมบันทึกว่าทิ้งอัปเดตของคนนั้นหรือตัดการเชื่อมต่อเพราะคิวส่งเกิน สัญญาณว่าไม่ใช่ Send-Q ว่างแต่ยังวาร์ป: ไม่ใช่ปัญหาฝั่งการส่งของเซิร์ฟเวอร์ ให้ดูแพ็กเก็ตหายบนเน็ตของคนนั้น (“แพ็กเก็ตหายช่วงไร้สาย”) หรือ interpolation บนหน้าจอ วิธีตรวจ ต้องมี log หรือเมตริกจากเซิร์ฟเวอร์/ไคลเอนต์เกม
แหล่งอ้างอิง 2 รายการ IP Sysctl Linux kernel tcp_wmem: ค่าสูงสุดของ send buffer ที่ปรับอัตโนมัติ ค่าเริ่มต้น 64 KB–4 MB (ตามหน่วยความจำ), tcp_notsent_lowat และ TCP_NOTSENT_LOWAT จำกัดปริมาณข้อมูลที่ยังไม่ได้ส่ง net/ipv4/tcp_diag.c (Linux v6.12) Linux kernel ค่า Recv-Q และ Send-Q ของ ss: ซ็อกเก็ตที่ listen อยู่คือจำนวนการเชื่อมต่อที่รอ accept และขีดจำกัด backlog, ซ็อกเก็ตที่เชื่อมต่อแล้วคือไบต์ที่แอปยังไม่ได้อ่าน และไบต์ที่ส่งไปแล้วแต่ยังไม่ได้รับ ACK
ID sk-keepalive · ผู้รับผิดชอบหลัก พัฒนาเซิร์ฟเวอร์ (ทีมพัฒนาเกม) · ร่วมกับ พัฒนาไคลเอนต์ (ทีมพัฒนาเกม), อินฟราเซิร์ฟเวอร์ (ทีมอินฟรา)
ถ้าอีกฝั่งหายไปโดยไม่ส่งสัญญาณปิด TCP จะรู้ตัวหลังผ่านไปนานมาก keepalive (ฟีเจอร์ของ TCP ที่ตรวจว่าการเชื่อมต่อที่ idle ยังอยู่หรือไม่) ปิดไว้เป็นค่าเริ่มต้น และต่อให้เปิด ก็ต้อง idle ครบ 2 ชั่วโมงก่อนจึงเริ่มตรวจ
ทำไม ไคลเอนต์หายไปโดยไม่ส่งสัญญาณปิด เพราะเครื่องดับหรือเน็ตขาด → ผลคือ เซิร์ฟเวอร์ถือว่าการเชื่อมต่อยังอยู่ (keepalive ค่าเริ่มต้น 7,200 วินาที ถ้ามีข้อมูลที่กำลังส่งอยู่ จะใช้ประมาณ 15 นาทีกว่าจะเลิกส่งซ้ำ) → บนหน้าจอ เหลือตัวผีของตัวละครอยู่ในเกม และพอเชื่อมต่อใหม่ก็เจอข้อผิดพลาด “ล็อกอินอยู่แล้ว”
อาการ เข้าเกมไม่ได้/โหลดไม่จบ , มองไม่เห็น/ตัวผี
ปัจจัย แพ็กเก็ตหาย
ใครเจอ เราคนเดียว
เกิดเมื่อไร หลังอยู่เฉย ๆ สักพัก, หลังล็อกอิน/หลังปิดปรับปรุง
ผู้รับผิดชอบ ผู้รับผิดชอบหลัก พัฒนาเซิร์ฟเวอร์ (ทีมพัฒนาเกม) · ร่วมกับ พัฒนาไคลเอนต์ (ทีมพัฒนาเกม), อินฟราเซิร์ฟเวอร์ (ทีมอินฟรา)
งานฝั่งทีมพัฒนาเกม เซิร์ฟเวอร์: ตอบ heartbeat และถ้าไม่ได้รับนานเกินกำหนดให้ปิดการเชื่อมต่อเองก่อน (ปรับ TCP_KEEPIDLE และ TCP_USER_TIMEOUT), เมื่อเชื่อมต่อใหม่ให้ใช้ session token แทนที่เซสชันเดิมแล้วเล่นต่อ ไคลเอนต์: ส่ง heartbeat ระดับเกมทุกไม่กี่วินาทีถึงหลายสิบวินาที (ไม่เกินครึ่งหนึ่งของ idle timeout ที่สั้นที่สุด), เชื่อมต่อใหม่อัตโนมัติเมื่อหลุด
งานฝั่งทีมอินฟรา ลดค่าเริ่มต้นของเคอร์เนล (tcp_keepalive_time เป็นต้น) สำหรับซ็อกเก็ตที่โค้ดไม่ได้กำหนดค่าเอง (มีผลเฉพาะซ็อกเก็ตที่เปิด SO_KEEPALIVE)
ตัวเลขที่ควรรู้ ค่าเริ่มต้นของ Linux จะเริ่มตรวจเมื่อ idle ครบ 7,200 วินาที แล้วส่ง probe 9 ครั้งห่างกันครั้งละ 75 วินาที ถ้าไม่มีการตอบกลับเลยจะตัดการเชื่อมต่อ รวมแล้วประมาณ 2 ชั่วโมง 11 นาที ค่าเริ่มต้นของ Windows ก็ต้อง idle 2 ชั่วโมงก่อนจึงเริ่มตรวจเช่นกัน
บนกราฟ สูงเฉพาะบางกลุ่ม · เวลาที่ผ่านไปนับจากรับข้อมูลครั้งล่าสุดของแต่ละการเชื่อมต่อ
จุดที่ต้องดู lastrcv (ms ที่ผ่านไปนับจากรับข้อมูลครั้งล่าสุด) และตัวจับเวลา keepalive (timer:(keepalive,…)) ของแต่ละการเชื่อมต่อจาก ss -tnoi เทียบกับบันทึกการปฏิเสธ “ล็อกอินอยู่แล้ว” ของเซิร์ฟเวอร์เกม สัญญาณว่าใช่ ยังมีการเชื่อมต่อ ESTABLISHED ที่ lastrcv นานหลายนาทีถึงหลายชั่วโมง และการเชื่อมต่อใหม่ของบัญชีนั้นถูกปฏิเสธด้วย “ล็อกอินอยู่แล้ว” สัญญาณว่าไม่ใช่ ไม่มีการเชื่อมต่อที่เงียบไปนาน แต่ยังขึ้น “ล็อกอินอยู่แล้ว”: น่าจะเป็นโค้ดเก็บกวาดเซสชันของเซิร์ฟเวอร์เกม วิธีตรวจ ใช้เครื่องมือฝั่งอินฟรา (ไม่ต้องใช้โค้ดเกม)
แหล่งอ้างอิง 4 รายการ
ID sk-fragment · ผู้รับผิดชอบหลัก พัฒนาเซิร์ฟเวอร์ (ทีมพัฒนาเกม)
แพ็กเก็ต UDP ที่ใหญ่กว่า MTU (ขนาดสูงสุดที่ส่งได้ในครั้งเดียว) จะถูกแบ่งเป็นชิ้น (fragmentation) ที่ชั้น IP และถ้า fragment หายไปแค่ชิ้นเดียว ทั้งแพ็กเก็ตจะถูกทิ้ง
ทำไม สแนปช็อตในที่ที่คนเยอะมีขนาดเกิน 1,500 ไบต์ → ผลคือ ถูกแบ่งเป็นหลาย fragment ตอนส่ง ถ้าหายแม้แต่ชิ้นเดียวก็ทิ้งทั้งหมด → บนหน้าจอ ยิ่งแพ็กเก็ตใหญ่ อัตราแพ็กเก็ตหายยิ่งสูงขึ้นหลายเท่า วาร์ปเฉพาะในที่ที่คนเยอะ
อาการ วาร์ป
ปัจจัย แพ็กเก็ตหาย
ใครเจอ บางจุด/บางแชนแนล, บางพื้นที่/บาง ISP
เกิดเมื่อไร ตอนคนแห่มารวมกัน
ผู้รับผิดชอบ ผู้รับผิดชอบหลัก พัฒนาเซิร์ฟเวอร์ (ทีมพัฒนาเกม)
งานฝั่งทีมพัฒนาเกม แบ่งแพ็กเก็ตเองให้ไม่เกิน 1,200 ไบต์, ส่งเฉพาะส่วนที่เปลี่ยน
ตัวเลขที่ควรรู้ บนเน็ตที่แพ็กเก็ตหาย 2% แพ็กเก็ตที่ถูกแบ่งเป็น 4 fragment จะหายไปประมาณ 8% ไฟร์วอลล์และ ISP บางรายทิ้งแพ็กเก็ตที่ถูกแบ่งชิ้นไปเลย ผู้เล่นกลุ่มนั้นจึงไม่ได้รับแพ็กเก็ตใหญ่เลยสักตัว
บนกราฟ สูงตามจำนวนคนและโหลด · จำนวน IP fragment (IpFragCreates), ขนาดสแนปช็อต
จุดที่ต้องดู ค่าที่เพิ่มขึ้นของ IpFragCreates (จำนวน fragment ที่สร้างตอนส่ง) จาก nstat -az บนเซิร์ฟเวอร์ และ IpReasmFails (จำนวนครั้งที่ประกอบกลับไม่สำเร็จ) ฝั่งรับ ตรวจการกระจายขนาดแพ็กเก็ต UDP จาก log ของเซิร์ฟเวอร์เกมหรือ packet capture สัญญาณว่าใช่ ในที่ที่คนแห่มารวมกัน IpFragCreates เพิ่มขึ้น มีแพ็กเก็ต UDP ที่ใหญ่เกิน 1,500 ไบต์ และตอนนั้นมีผู้เล่นแจ้งอาการวาร์ปมากขึ้น สัญญาณว่าไม่ใช่ IpFragCreates ไม่เพิ่ม: ฝั่งที่เซิร์ฟเวอร์ส่งไม่ได้เกิด fragmentation วิธีตรวจ ใช้เครื่องมือฝั่งอินฟรา (ไม่ต้องใช้โค้ดเกม)
แหล่งอ้างอิง 3 รายการ
ID sk-reliable-udp · ผู้รับผิดชอบหลัก พัฒนาเซิร์ฟเวอร์ (ทีมพัฒนาเกม) · ร่วมกับ พัฒนาไคลเอนต์ (ทีมพัฒนาเกม)
ถ้ากฎการส่งซ้ำที่สร้างเองบน UDP ระมัดระวังเกินไป การกู้คืนจะช้า ถ้าดุดันเกินไปก็จะยิ่งทำให้เน็ตอุดตัน
ทำไม ช่วงห่าง จำนวนครั้ง และขนาด window ของการส่งซ้ำไม่เหมาะกับเน็ต → ผลคือ กู้คืนช้า หรือส่งซ้ำซ้อนจนความแออัดแย่ลง → บนหน้าจอ สกิลไม่ออก, กรอเร็ว, แลคหนักขึ้นตอนเครือข่ายแออัด
อาการ กดไม่ติด/โรลแบ็ค , กรอเร็ว
ปัจจัย แพ็กเก็ตหาย, ความหน่วง
ใครเจอ เราคนเดียว
เกิดเมื่อไร สุ่มเป็นครั้งคราว
ผู้รับผิดชอบ ผู้รับผิดชอบหลัก พัฒนาเซิร์ฟเวอร์ (ทีมพัฒนาเกม) · ร่วมกับ พัฒนาไคลเอนต์ (ทีมพัฒนาเกม)
งานฝั่งทีมพัฒนาเกม เซิร์ฟเวอร์: ส่งซ้ำตามเวลาไปกลับที่วัดได้, แยกช่องทางตามความสำคัญ ไคลเอนต์: ใช้การตั้งค่าการส่งซ้ำและช่องทางเดียวกับเซิร์ฟเวอร์
บนกราฟ พุ่งแบบสุ่มเป็นครั้งคราว · อัตราการส่งซ้ำของ reliable UDP, RTT ในเกม
จุดที่ต้องดู สถิติต่อการเชื่อมต่อของไลบรารีที่ใช้ (จำนวนการส่งซ้ำ, เวลาไปกลับที่ประมาณ, เวลารอก่อนส่งซ้ำ) บันทึกทั้งฝั่งเซิร์ฟเวอร์และไคลเอนต์ แล้วเทียบกับอัตราแพ็กเก็ตหายจริงบนเน็ตของผู้เล่นคนเดียวกัน (ค่าที่วัดด้วย mtr) สัญญาณว่าใช่ อัตราการส่งซ้ำสูงกว่าอัตราแพ็กเก็ตหายจริงหลายเท่า: ตั้งค่าดุดันเกินไป เวลารอก่อนส่งซ้ำนานเป็นหลายเท่าของเวลาไปกลับที่วัดได้: ตั้งค่าระมัดระวังเกินไป สัญญาณว่าไม่ใช่ อัตราการส่งซ้ำใกล้เคียงอัตราแพ็กเก็ตหาย และเวลารอสอดคล้องกับเวลาไปกลับ: ไม่ใช่ปัญหาการตั้งค่า ให้ดูแพ็กเก็ตหายบนเน็ตโดยตรง วิธีตรวจ ต้องมี log หรือเมตริกจากเซิร์ฟเวอร์/ไคลเอนต์เกม
แหล่งอ้างอิง 1 รายการ RFC 8085: UDP Usage Guidelines IETF การส่งซ้ำอาจเพิ่มความแออัดจึงต้องอยู่ภายใต้ congestion control, ประมาณเวลาไปกลับจากค่าเฉลี่ยของการวัดหลายครั้ง (EWMA), ค่าเริ่มต้น 1 วินาที, ลดอัตราการส่งเมื่อตัวจับเวลาหมดเวลา
ID sk-slowstart · ผู้รับผิดชอบหลัก อินฟราเซิร์ฟเวอร์ (ทีมอินฟรา) · ร่วมกับ พัฒนาเซิร์ฟเวอร์ (ทีมพัฒนาเกม)
เมื่อการเชื่อมต่อ idle ไปสักพัก TCP จะลด congestion window (ปริมาณที่ส่งได้ในครั้งเดียว) กลับลงมา พอต้องส่งข้อมูลก้อนใหญ่ขึ้นมากะทันหันจึงต้องแบ่งส่งหลายรอบ
ทำไม ส่งข้อมูลก้อนใหญ่ผ่านการเชื่อมต่อที่ idle อยู่ เช่น ตอนเข้าเมือง → ผลคือ congestion window ลดลงแล้ว จึงต้องแบ่งส่งเป็นหลายรอบเวลาไปกลับ → บนหน้าจอ หลังเข้าพื้นที่ ตัวละครและ NPC รอบตัวโผล่ช้าไปเท่ากับเวลาไปกลับไม่กี่รอบ (ยิ่งเซิร์ฟเวอร์อยู่ไกลยิ่งเห็นชัด)
อาการ อินพุตดีเลย์ , มองไม่เห็น/ตัวผี
ปัจจัย ความหน่วง
ใครเจอ เราคนเดียว
เกิดเมื่อไร ระหว่างเดินทาง/ย้ายแมพ, หลังอยู่เฉย ๆ สักพัก
ผู้รับผิดชอบ ผู้รับผิดชอบหลัก อินฟราเซิร์ฟเวอร์ (ทีมอินฟรา) · ร่วมกับ พัฒนาเซิร์ฟเวอร์ (ทีมพัฒนาเกม)
งานฝั่งทีมพัฒนาเกม ลดข้อมูลตอนเข้าพื้นที่ (ส่งสิ่งที่จำเป็นก่อน)
งานฝั่งทีมอินฟรา ปิด tcp_slow_start_after_idle (Linux, ตั้งค่าทั้งเซิร์ฟเวอร์)
ตัวเลขที่ควรรู้ ถ้า idle นานกว่า RTO congestion window จะเริ่มลดลง และถ้า idle นานมากจะลดลงเหลือประมาณ 14 KB (10 แพ็กเก็ต) ข้อมูล 100 KB จึงส่งครั้งเดียวไม่ได้ ต้องแบ่งส่งใน 3 รอบเวลาไปกลับ
บนกราฟ สูงเฉพาะบางกลุ่ม · เวลาส่งข้อมูลหลังเข้าพื้นที่ (ผู้เล่นที่ RTT ยาว)
จุดที่ต้องดู ค่า sysctl net.ipv4.tcp_slow_start_after_idle และ cwnd (congestion window) ใน ss -ti ของการเชื่อมต่อนั้นว่าเล็กลงหรือไม่ ตอนที่ผู้เล่นเข้าพื้นที่หลัง idle สัญญาณว่าใช่ ค่าตั้งเป็น 1 (ค่าเริ่มต้น) และตอนเข้าพื้นที่หลัง idle cwnd ลดลงเหลือราว 10 จนการส่งถูกแบ่งเป็นหลายรอบเวลาไปกลับ ผู้เล่นที่ RTT ยาวจะเห็นของโผล่ช้ากว่า และเปลี่ยนเป็น 0 แล้วหายไป สัญญาณว่าไม่ใช่ cwnd ยังใหญ่อยู่แต่ของยังโผล่ช้า: น่าจะเป็นการจัดการตอนเข้าพื้นที่ฝั่งเซิร์ฟเวอร์ (“spawn ทะลักเมื่อเข้าพื้นที่คนหนาแน่น”) วิธีตรวจ ใช้เครื่องมือฝั่งอินฟรา (ไม่ต้องใช้โค้ดเกม)
แหล่งอ้างอิง 4 รายการ
ID sk-congestion · ผู้รับผิดชอบหลัก อินฟราเซิร์ฟเวอร์ (ทีมอินฟรา) · ร่วมกับ พัฒนาเซิร์ฟเวอร์ (ทีมพัฒนาเกม)
TCP มองว่าแพ็กเก็ตหายคือสัญญาณของความแออัด จึงลดอัตราการส่งลง 30–50% และตอบสนองแบบเดียวกันแม้แพ็กเก็ตหายเพราะ Wi-Fi
ทำไม มีแพ็กเก็ตหายเล็กน้อยบน Wi-Fi หรือเน็ตตอนที่มีข้อมูลต้องส่งมาก → ผลคือ TCP ลดอัตราการส่งลงมากแล้วค่อย ๆ ฟื้นตัว (CUBIC ซึ่งเป็นค่าเริ่มต้นของ Linux และ Windows ลด 30%) → บนหน้าจอ ในที่ที่คนเยอะ อัปเดตตามไม่ทัน: กรอเร็ว, อินพุตดีเลย์
อาการ กรอเร็ว , อินพุตดีเลย์
ปัจจัย ความหน่วง, การหยุดชะงัก
ใครเจอ เราคนเดียว
เกิดเมื่อไร ตอนคนแห่มารวมกัน
ผู้รับผิดชอบ ผู้รับผิดชอบหลัก อินฟราเซิร์ฟเวอร์ (ทีมอินฟรา) · ร่วมกับ พัฒนาเซิร์ฟเวอร์ (ทีมพัฒนาเกม)
งานฝั่งทีมพัฒนาเกม ลดปริมาณที่ส่ง (AOI, ส่งเฉพาะส่วนที่เปลี่ยน), แบ่งส่งไม่ให้ออกไปรวดเดียว
งานฝั่งทีมอินฟรา เปลี่ยนไปใช้ congestion control แบบอื่น เช่น BBR (tcp_congestion_control)
บนกราฟ ค่อย ๆ ขึ้นแล้วดิ่งลง · congestion window (cwnd) และอัตราการส่งต่อการเชื่อมต่อ
จุดที่ต้องดู ss -ti ของการเชื่อมต่อของผู้เล่นที่อัปเดตตามไม่ทัน เก็บหลาย ๆ ครั้งเพื่อดูการเปลี่ยนแปลงของ cwnd และ ssthresh และชื่อ congestion control (cubic, bbr) พร้อมดูว่า Send-Q กองสะสมหรือไม่ สัญญาณว่าใช่ หลังแพ็กเก็ตหาย cwnd ลดฮวบแล้วค่อย ๆ ขึ้นวนซ้ำ และระหว่างที่ลดอยู่ Send-Q กองสะสม ตรงกับเวลาที่มีผู้เล่นแจ้งอาการกรอเร็วและอินพุตดีเลย์ สัญญาณว่าไม่ใช่ cwnd เหลือเฟือแต่อัปเดตยังตามไม่ทัน: น่าจะเป็น window ฝั่งรับ (“zero window (การหยุดที่ดูเหมือนการส่งซ้ำ)”) หรือฝั่งการส่งของเซิร์ฟเวอร์ วิธีตรวจ ใช้เครื่องมือฝั่งอินฟรา (ไม่ต้องใช้โค้ดเกม)
แหล่งอ้างอิง 5 รายการ
ID sk-linger · ผู้รับผิดชอบหลัก พัฒนาเซิร์ฟเวอร์ (ทีมพัฒนาเกม)
ถ้าเซิร์ฟเวอร์ตัดการเชื่อมต่อแบบกะทันหัน ข้อความแจ้งสุดท้ายหรือสัญญาณว่าบันทึกข้อมูลเสร็จที่ส่งออกไปจะหายไป
ทำไม เซิร์ฟเวอร์ปิดการเชื่อมต่อแบบบังคับ (RST) เกิดเมื่อตั้ง SO_LINGER เป็น 0 วินาที หรือปิดทั้งที่ยังอ่านข้อมูลที่รับมาไม่หมด → ผลคือ เหตุผลที่ถูกเตะออก (kick) และข้อมูลสุดท้ายที่ยังส่งไม่ถึงถูกทิ้ง → บนหน้าจอ ขึ้นข้อความ “การเชื่อมต่อถูกตัดเนื่องจากข้อผิดพลาดที่ไม่ทราบสาเหตุ” โดยไม่รู้เหตุผล
อาการ หลุด
ปัจจัย แพ็กเก็ตหาย
ใครเจอ เราคนเดียว
เกิดเมื่อไร สุ่มเป็นครั้งคราว
ผู้รับผิดชอบ ผู้รับผิดชอบหลัก พัฒนาเซิร์ฟเวอร์ (ทีมพัฒนาเกม)
งานฝั่งทีมพัฒนาเกม ส่งเหตุผลแล้วปิดเฉพาะทิศทางส่งก่อน (shutdown) อ่านข้อมูลที่รับเข้ามาจนอีกฝั่งปิด แล้วจึงปิดซ็อกเก็ต, เลี่ยง SO_LINGER 0 วินาที
บนกราฟ พุ่งแบบสุ่มเป็นครั้งคราว · จำนวนการเชื่อมต่อที่จบด้วย RST
จุดที่ต้องดู ค่าที่เพิ่มขึ้นของ TcpExtTCPAbortOnData (ปิดด้วย RST ขณะที่ยังมีข้อมูลรอส่ง, SO_LINGER 0 วินาที) และ TcpExtTCPAbortOnClose (ปิดขณะที่ยังมีข้อมูลที่ยังไม่ได้อ่าน) จาก nstat -az และดูใน packet capture ฝั่งเซิร์ฟเวอร์ตอนที่หลุดว่าส่ง RST ออกไปแทน FIN หรือไม่ สัญญาณว่าใช่ ตรงกับเวลาที่ผู้เล่นแจ้งว่าขึ้น “การเชื่อมต่อถูกตัดเนื่องจากข้อผิดพลาดที่ไม่ทราบสาเหตุ” เซิร์ฟเวอร์ส่ง RST และ AbortOnData กับ AbortOnClose เพิ่มขึ้น สัญญาณว่าไม่ใช่ เซิร์ฟเวอร์ปิดตามปกติด้วย FIN แต่ผู้เล่นไม่เห็นเหตุผล: น่าจะเป็นการจัดการตอนปิดของไคลเอนต์ วิธีตรวจ ใช้เครื่องมือฝั่งอินฟรา (ไม่ต้องใช้โค้ดเกม)
แหล่งอ้างอิง 4 รายการ
ID sk-blocking-io · ผู้รับผิดชอบหลัก พัฒนาเซิร์ฟเวอร์ (ทีมพัฒนาเกม)
โครงสร้างที่เธรดทำอย่างอื่นไม่ได้ระหว่างรอซ็อกเก็ตตัวเดียว จะทำให้ทั้งระบบช้าลงเมื่อคนเพิ่มขึ้น
ทำไม ใช้วิธีที่เธรดรอการอ่านและเขียนของแต่ละการเชื่อมต่อ → ผลคือ ดีเลย์ของการเชื่อมต่อหนึ่งลามไปยังการเชื่อมต่ออื่นในเธรดเดียวกัน → บนหน้าจอ ยิ่งผู้เล่นออนไลน์เพิ่มขึ้น ทุกคนยิ่งเจอสโลว์โมชั่นและอินพุตดีเลย์
อาการ สโลว์โมชั่น , อินพุตดีเลย์
ปัจจัย การหยุดชะงัก
ใครเจอ ทั้งเซิร์ฟเวอร์
เกิดเมื่อไร ตอนคนแห่มารวมกัน, ช่วงพีคหัวค่ำ
ผู้รับผิดชอบ ผู้รับผิดชอบหลัก พัฒนาเซิร์ฟเวอร์ (ทีมพัฒนาเกม)
งานฝั่งทีมพัฒนาเกม เปลี่ยนไปใช้ async I/O ที่ใช้ epoll, IOCP หรือ io_uring
บนกราฟ สูงตามจำนวนคนและโหลด · เวลาตอบสนอง, จำนวนเธรด
จุดที่ต้องดู จำนวนเธรดของเซิร์ฟเวอร์เกมและ voluntary context switch ของแต่ละเธรด (cswch/s คือจำนวนครั้งที่หยุดรอทรัพยากร) จาก pidstat -w -t เทียบกับเวลาตอบสนองเมื่อผู้เล่นออนไลน์เพิ่มขึ้น สัญญาณว่าใช่ ยิ่งผู้เล่นออนไลน์เพิ่มขึ้น เวลาตอบสนองยิ่งพุ่งชัน และเธรดส่วนใหญ่ที่เพิ่มขึ้นตามจำนวนการเชื่อมต่อมีแต่ voluntary switch สูง แทบไม่ใช้ CPU (รอซ็อกเก็ต) สัญญาณว่าไม่ใช่ เธรดใช้ CPU ต่อเนื่องโดยไม่ได้รอ: น่าจะเป็นการคำนวณเกินกำลัง (“ทิกเกินงบเวลา”) วิธีตรวจ ใช้เครื่องมือฝั่งอินฟรา (ไม่ต้องใช้โค้ดเกม)
แหล่งอ้างอิง 3 รายการ
ID sk-reuseport · ผู้รับผิดชอบหลัก พัฒนาเซิร์ฟเวอร์ (ทีมพัฒนาเกม) · ร่วมกับ อินฟราเซิร์ฟเวอร์ (ทีมอินฟรา)
เมื่อหลายโปรเซสแบ่งกันรับพอร์ตเดียวกัน เคอร์เนลจะกำหนดโปรเซสที่รับแต่ละการเชื่อมต่อด้วย hash ของที่อยู่ และไม่เปลี่ยนอีก ถ้าโปรเซสตัวใดหยุด เฉพาะคนที่ถูกจัดให้โปรเซสนั้นจะต้องรอ
ทำไม เกตเวย์หรือเซิร์ฟเวอร์ล็อกอินรันหลายโปรเซสด้วย SO_REUSEPORT → ผลคือ แม้โปรเซสหนึ่งหยุดเพราะ GC หรือโหลดเกิน การเชื่อมต่อใหม่และแพ็กเก็ต UDP ที่ถูกจัดให้โปรเซสนั้นก็ไม่ย้ายไปโปรเซสอื่น → บนหน้าจอ บางคนเท่านั้นที่เข้าเกมไม่ได้หรือค้าง ตอนรีสตาร์ตที่จำนวนโปรเซสเปลี่ยน เซสชัน UDP บางส่วนจะหลุด
อาการ เข้าเกมไม่ได้/โหลดไม่จบ , ค้าง , หลุด
ปัจจัย การหยุดชะงัก, แพ็กเก็ตหาย
ใครเจอ เราคนเดียว, ทั้งเซิร์ฟเวอร์
เกิดเมื่อไร หลังล็อกอิน/หลังปิดปรับปรุง, สุ่มเป็นครั้งคราว
ผู้รับผิดชอบ ผู้รับผิดชอบหลัก พัฒนาเซิร์ฟเวอร์ (ทีมพัฒนาเกม) · ร่วมกับ อินฟราเซิร์ฟเวอร์ (ทีมอินฟรา)
งานฝั่งทีมพัฒนาเกม อย่าให้เธรดรับหยุดเด็ดขาด, ทำขั้นตอนส่งต่อเซสชันตอนรีสตาร์ต
งานฝั่งทีมอินฟรา มอนิเตอร์คิวรอเชื่อมต่อของแต่ละโปรเซส (Recv-Q ของ ss), ถ้า deploy แล้วจำนวนโปรเซสเปลี่ยน ให้ทำตามขั้นตอนส่งต่อเซสชัน
บนกราฟ สูงเฉพาะบางกลุ่ม · คิวรอเชื่อมต่อ (Recv-Q) ของแต่ละซ็อกเก็ตที่ listen
จุดที่ต้องดู Recv-Q (จำนวนการเชื่อมต่อที่รอ accept) และโปรเซสเจ้าของของแต่ละซ็อกเก็ตที่ listen บนพอร์ตเดียวกันจาก ss -ltnp และเทียบ throughput ของแต่ละโปรเซส สัญญาณว่าใช่ ในซ็อกเก็ตหลายตัวบนพอร์ตเดียวกัน มีตัวเดียวที่ Recv-Q สะสมเรื่อย ๆ และโปรเซสนั้นหยุดอยู่หรือ throughput ใกล้ 0 สัญญาณว่าไม่ใช่ Recv-Q ของทุกซ็อกเก็ตสะสมเท่า ๆ กัน: น่าจะเป็นโหลดเกินทั้งระบบ (“คิวรอเชื่อมต่อ (backlog) ล้น”) วิธีตรวจ ใช้เครื่องมือฝั่งอินฟรา (ไม่ต้องใช้โค้ดเกม)
แหล่งอ้างอิง 4 รายการ
ID sk-udp-connreset · ผู้รับผิดชอบหลัก พัฒนาเซิร์ฟเวอร์ (ทีมพัฒนาเกม)
ถ้าเซิร์ฟเวอร์ Windows ส่ง UDP ไปหาไคลเอนต์ที่ออกไปแล้ว จะได้ข้อความแจ้ง “ไม่พบพอร์ต” (ICMP) กลับมา ข้อความนั้นทำให้การเรียกรับครั้งถัดไปจบด้วยข้อผิดพลาด และถ้าโค้ดเซิร์ฟเวอร์ถือว่าข้อผิดพลาดนี้คือซ็อกเก็ตเสีย ทุกคนที่ใช้ซ็อกเก็ตนั้นจะได้รับผลกระทบ
ทำไม ยังส่ง UDP ไปยังที่อยู่ของไคลเอนต์ที่เพิ่งออกไปเรื่อย ๆ จนได้ข้อความแจ้ง “ไม่พบพอร์ต” (ICMP) กลับมา → ผลคือ Windows ทำให้การเรียกรับครั้งถัดไปจบด้วยข้อผิดพลาด WSAECONNRESET (10054) แล้วโค้ดเซิร์ฟเวอร์หยุดรับหรือปิดซ็อกเก็ต → บนหน้าจอ ทุกคนที่ใช้ซ็อกเก็ตนั้นค้างหรือหลุดพร้อมกัน
อาการ หลุด , ค้าง
ปัจจัย แพ็กเก็ตหาย, การหยุดชะงัก
ใครเจอ ทั้งเซิร์ฟเวอร์
เกิดเมื่อไร สุ่มเป็นครั้งคราว, หลังล็อกอิน/หลังปิดปรับปรุง
ผู้รับผิดชอบ ผู้รับผิดชอบหลัก พัฒนาเซิร์ฟเวอร์ (ทีมพัฒนาเกม)
งานฝั่งทีมพัฒนาเกม ปิด SIO_UDP_CONNRESET ด้วย WSAIoctl เพื่อไม่ให้รับข้อความแจ้งนี้, ถ้าเกิดข้อผิดพลาดตอนรับให้บันทึก log ไว้แล้วรับต่อไป
บนกราฟ การเชื่อมต่อหลุดพร้อมกัน · จำนวนการเชื่อมต่อ, log ข้อผิดพลาดตอนรับ
จุดที่ต้องดู รหัสข้อผิดพลาดตอนรับ UDP (WSAECONNRESET, 10054) และบันทึกว่าลูปรับหยุดหรือซ็อกเก็ตถูกปิดใน log ของเซิร์ฟเวอร์เกม และดูใน packet capture ฝั่งเซิร์ฟเวอร์ว่ามี ICMP Port Unreachable มาถึงก่อนหน้านั้นหรือไม่ สัญญาณว่าใช่ มีบันทึกข้อผิดพลาดตอนรับ WSAECONNRESET ก่อนการเชื่อมต่อหลุดพร้อมกัน และก่อนหน้านั้นมี ICMP Port Unreachable มาจากที่อยู่ของไคลเอนต์ที่เพิ่งออกไป สัญญาณว่าไม่ใช่ เซิร์ฟเวอร์ Linux หรือโค้ดที่ปิด SIO_UDP_CONNRESET แล้ว: ไม่เกี่ยว วิธีตรวจ ต้องมี log หรือเมตริกจากเซิร์ฟเวอร์/ไคลเอนต์เกม
แหล่งอ้างอิง 3 รายการ
L9 โปรเซสเกมฝั่งเซิร์ฟเวอร์
18 สาเหตุ · บทในฉบับหลัก
ID sp-tick-overrun · ผู้รับผิดชอบหลัก พัฒนาเซิร์ฟเวอร์ (ทีมพัฒนาเกม) · ร่วมกับ อินฟราเซิร์ฟเวอร์ (ทีมอินฟรา)
ถ้างานในหนึ่งทิกเกินงบเวลา รอบทิกของเซิร์ฟเวอร์จะยืดออก และทั้งพื้นที่จะช้าลงหรือกระตุก
ทำไม งานในหนึ่งทิก (เช่น 50 ms) เกินงบเวลา → ผลคือ สถานะเกมที่ควรคำนวณ 20 ครั้งใน 1 วินาที ถูกคำนวณแค่ 8 ครั้ง → บนหน้าจอ ทั้งพื้นที่เป็นสโลว์โมชั่น (แล้วแต่การออกแบบเซิร์ฟเวอร์ อาจเป็นอาการกระตุก), สกิลตอบสนองช้า
อาการ สโลว์โมชั่น , อินพุตดีเลย์ , กระตุก
ปัจจัย การหยุดชะงัก
ใครเจอ บางจุด/บางแชนแนล, ทั้งเซิร์ฟเวอร์
เกิดเมื่อไร ตอนคนแห่มารวมกัน, ช่วงพีคหัวค่ำ
ผู้รับผิดชอบ ผู้รับผิดชอบหลัก พัฒนาเซิร์ฟเวอร์ (ทีมพัฒนาเกม) · ร่วมกับ อินฟราเซิร์ฟเวอร์ (ทีมอินฟรา)
งานฝั่งทีมพัฒนาเกม ลดการคำนวณที่หนัก, แบ่งงานในทิกไปหลายเธรด, กระจายผู้เล่น (แชนแนล), เก็บเวลาประมวลผลต่อทิกเป็นเมตริก
งานฝั่งทีมอินฟรา เพิ่มเวลาต่อทิกและอัตราการใช้ CPU แยกตามคอร์ในการมอนิเตอร์และ alert, พิจารณา CPU หรืออินสแตนซ์ที่ประสิทธิภาพคอร์เดียว (คล็อก) สูง
ตัวเลขที่ควรรู้ งบเวลาของเซิร์ฟเวอร์ 20 ทิกคือ 50 ms, 30 ทิกคือ 33 ms และ 60 ทิกคือ 16.7 ms เพื่อรับมือตอนคนแห่เข้ามากะทันหัน ตามปกติควรใช้แค่ราวครึ่งหนึ่งของงบและเผื่อที่เหลือไว้ จะปลอดภัยกว่า
บนกราฟ สูงตามจำนวนคนและโหลด · เวลาต่อทิกของเซิร์ฟเวอร์, จำนวนผู้เล่นแยกตามโซน/แชนแนล, CPU ของเธรดเกม
จุดที่ต้องดู เวลาประมวลผลต่อทิก (p99) และจำนวนครั้งที่ทิกเกินงบที่เซิร์ฟเวอร์บันทึก วางบนกราฟเดียวกับจำนวนผู้เล่นแยกตามโซน/แชนแนล ถ้าไม่มีเมตริกทิก ให้ดู CPU ของเธรดเกมตัวเดียวด้วย pidstat -t 1 สัญญาณว่าใช่ ช่วงที่คนรวมตัวกัน เวลาต่อทิกเกินงบ (50 ms ที่ 20 ทิก) และระหว่างนั้น CPU ของเธรดเกมอยู่ใกล้ 100% สัญญาณว่าไม่ใช่ ทิกเกินงบแต่ CPU ของเธรดเกมต่ำ: น่าจะเป็นสาเหตุฝั่งการรอ (GC pause, ล็อก, synchronous call) ถ้า run queue latency จาก bcc runqlat สูง แปลว่าเธรดไม่ได้รับ CPU: น่าจะเป็น CPU ไม่พอหรือเธรดมากเกินไป วิธีตรวจ ต้องมี log หรือเมตริกจากเซิร์ฟเวอร์/ไคลเอนต์เกม
รายละเอียดเพิ่มเติม ทิกที่ช้าจะออกมาในลักษณะไหนขึ้นอยู่กับการออกแบบเซิร์ฟเวอร์ เซิร์ฟเวอร์ที่เดินสถานะเกมไปทีละช่วงเวลาคงที่ทุกทิก (เช่น 50 ms) จะทำให้เวลาในเกมเองช้าลงจนเป็นสโลว์โมชั่น ส่วนเซิร์ฟเวอร์ที่ขยับทุกอย่างตามเวลาที่ผ่านไปจริงในครั้งเดียว จะรักษาความเร็วของเกมไว้ได้ แต่แพ็กเก็ตจะมาห่างและแต่ละครั้งขยับไกล จึงเห็นเป็นอาการกระตุกหรือวาร์ป ไม่ว่าแบบไหน การตอบสนองต่ออินพุตก็ช้าลง ถ้าเธรดเกมตัวเดียวดูแลทั้งเซิร์ฟเวอร์ ทั้งเซิร์ฟเวอร์จะช้า ถ้าแยกเธรดตามพื้นที่ พื้นที่นั้นจะช้า บางเกม เช่น EVE Online จงใจทำให้เวลาในเกมช้าลงได้สูงสุด 10 เท่าในศึกใหญ่ (Time Dilation) เพื่อให้การคำนวณตามทัน
กรณีจริง CCP Games 2014: เซิร์ฟเวอร์ EVE Online โหลดเกินในศึกกองยานขนาดใหญ่ที่ HED-GP
แหล่งอ้างอิง 5 รายการ
ID sp-aoi · ผู้รับผิดชอบหลัก พัฒนาเซิร์ฟเวอร์ (ทีมพัฒนาเกม)
ถ้าเปรียบเทียบทุกคนกับทุกคนเพื่อหาว่าใครมองเห็นใคร เมื่อจำนวนคนเพิ่มเป็น 10 เท่า การคำนวณจะเพิ่มเป็น 100 เท่า
ทำไม เทียบระยะห่างระหว่างตัวละครทุกตัว หรือแม้แบ่งเป็นตาราง (grid) แล้วก็ยังมีคนหลายร้อยคนกระจุกรอบเซลล์เดียว → ผลคือ 100 คนเทียบประมาณ 1 หมื่นครั้ง 1,000 คนเทียบประมาณ 1 ล้านครั้ง → บนหน้าจอ ในที่ที่คนกระจุกตัว เช่น เวิลด์บอสหรือศึกชิงปราสาท ทิกพุ่ง: สโลว์โมชั่น, กระตุก
อาการ สโลว์โมชั่น , กระตุก
ปัจจัย การหยุดชะงัก
ใครเจอ บางจุด/บางแชนแนล, ทั้งเซิร์ฟเวอร์
เกิดเมื่อไร ตอนคนแห่มารวมกัน
ผู้รับผิดชอบ ผู้รับผิดชอบหลัก พัฒนาเซิร์ฟเวอร์ (ทีมพัฒนาเกม)
งานฝั่งทีมพัฒนาเกม แบ่งเป็นตารางหรือเขตแล้วเทียบเฉพาะที่อยู่ใกล้, อัปเดตเป้าหมายที่อยู่ไกลให้ห่างขึ้น, จำกัดจำนวนคนที่ผู้เล่นหนึ่งคนมองเห็น
ตัวเลขที่ควรรู้ ถ้าคิดการเทียบระยะและการอัปเดตรายการว่าเห็นหรือไม่เห็นรวมกันเป็น 0.1 µs (หนึ่งในสิบล้านวินาที) ต่อหนึ่งคู่ 1,000 คน (ประมาณ 1 ล้านคู่) จะใช้ 100 ms ต่อทิก เป็นสองเท่าของงบเวลาที่ 20 ทิก (50 ms)
บนกราฟ สูงตามจำนวนคนและโหลด · เวลาต่อทิกของเซิร์ฟเวอร์, จำนวนคนที่รวมตัวในจุดเดียว
จุดที่ต้องดู จำนวนผู้เล่นและเวลาต่อทิกแยกตามโซน/แชนแนลบนกราฟเดียวกัน และเวลาที่ใช้คำนวณระยะมองเห็นในทิกซึ่งวัดแยกไว้ ถ้าไม่ได้วัดแยก ให้ดูสัดส่วน CPU แยกตามฟังก์ชันของโปรเซสเกมด้วย perf top -p สัญญาณว่าใช่ เมื่อจำนวนคนในจุดเดียวเพิ่มเป็น 2 เท่า เวลาต่อทิกเพิ่มเกือบ 4 เท่า และฟังก์ชันคำนวณระยะมองเห็นและระยะห่างกินเวลา CPU ส่วนใหญ่ สัญญาณว่าไม่ใช่ เวลาต่อทิกเพิ่มเป็นสัดส่วนตรงกับจำนวนคน หรือฟังก์ชันส่งข้อมูลและ serialization กินสัดส่วนมาก: น่าจะเป็นปริมาณ broadcast พุ่ง หรือต้นทุนของ serialization และการบีบอัด วิธีตรวจ ต้องมี log หรือเมตริกจากเซิร์ฟเวอร์/ไคลเอนต์เกม
แหล่งอ้างอิง 3 รายการ
ID sp-broadcast · ผู้รับผิดชอบหลัก พัฒนาเซิร์ฟเวอร์ (ทีมพัฒนาเกม) · ร่วมกับ อินฟราเซิร์ฟเวอร์ (ทีมอินฟรา)
ถ้าส่งการเคลื่อนไหวของผู้เล่นหนึ่งคนไปให้ทุกคนที่มองเห็น จะเกิดอัปเดตที่ต้องส่งเท่ากับจำนวนคนที่รวมตัวยกกำลังสอง
ทำไม ส่งการเปลี่ยนแปลงของผู้เล่นหนึ่งคนไปให้ทุกคนที่มองเห็น → ผลคือ ถ้า 1,000 คนมองเห็นกันทั้งหมด จะมีอัปเดต 1 ล้านรายการทุกทิก → บนหน้าจอ คิวส่งและแบนด์วิดท์เต็ม เกิดดีเลย์และแพ็กเก็ตหาย (อินพุตดีเลย์, กรอเร็ว, วาร์ป)
อาการ อินพุตดีเลย์ , วาร์ป , กรอเร็ว
ปัจจัย ความหน่วง, แพ็กเก็ตหาย
ใครเจอ บางจุด/บางแชนแนล, ทั้งเซิร์ฟเวอร์
เกิดเมื่อไร ตอนคนแห่มารวมกัน
ผู้รับผิดชอบ ผู้รับผิดชอบหลัก พัฒนาเซิร์ฟเวอร์ (ทีมพัฒนาเกม) · ร่วมกับ อินฟราเซิร์ฟเวอร์ (ทีมอินฟรา)
งานฝั่งทีมพัฒนาเกม ลดความถี่อัปเดตตามระยะห่างและความสำคัญ (ศัตรูใกล้ตัวทุกทิก คนที่อยู่ไกลไม่กี่ครั้งต่อวินาที), จำกัดปริมาณที่ส่งให้แต่ละคนแล้วเติมจากสิ่งที่สำคัญก่อน, รวมหลายอัปเดตไว้ในแพ็กเก็ตเดียว, จำกัดจำนวนคนที่แสดง
งานฝั่งทีมอินฟรา ตั้ง alert โดยเทียบแบนด์วิดท์ขาออกและจำนวนแพ็กเก็ตต่อวินาทีของแต่ละเซิร์ฟเวอร์กับขีดจำกัดเครือข่ายของ NIC และอินสแตนซ์, ตรวจว่ายังเหลือที่ว่างพอก่อนอีเวนต์ใหญ่
ตัวเลขที่ควรรู้ 1,000 คน × 1,000 คน × 20 ทิก = 20 ล้านรายการต่อวินาที ถ้ารายการละ 40 ไบต์ ทั้งเซิร์ฟเวอร์จะใช้ประมาณ 6.4 Gbps และผู้รับแต่ละคนประมาณ 6.4 Mbps ถ้าจำกัดจำนวนคนที่มองเห็นไว้ 150 คน จะเหลือทั้งหมดประมาณ 1 Gbps และคนละประมาณ 1 Mbps
บนกราฟ สูงตามจำนวนคนและโหลด · แพ็กเก็ตและไบต์ขาออกของเซิร์ฟเวอร์, จำนวนคนที่รวมตัวในจุดเดียว
จุดที่ต้องดู txpck/s และ txkB/s (แพ็กเก็ตและ KB ที่ NIC ของเซิร์ฟเวอร์ส่งต่อวินาที) จาก sar -n DEV 1 ดูคู่กับกราฟจำนวนผู้เล่น สำหรับอินสแตนซ์บนคลาวด์ ดูตัวนับที่เกินขีดจำกัดใน ethtool -S (AWS ENA คือ bw_out_allowance_exceeded และ pps_allowance_exceeded) สัญญาณว่าใช่ เมื่อคนรวมตัวมากขึ้น แพ็กเก็ตและไบต์ขาออกเพิ่มเร็วกว่าจำนวนคน (เกือบเท่ากำลังสอง) และตั้งแต่ตอนที่ชนขีดจำกัด ตัวนับที่เกินขีดจำกัดหรือการทิ้งแพ็กเก็ตขาออกจะเพิ่มขึ้น สัญญาณว่าไม่ใช่ ปริมาณขาออกไม่เปลี่ยนแต่เวลาต่อทิกเพิ่มอย่างเดียว: น่าจะเป็นการคำนวณระยะมองเห็นหรือลอจิกของเกม วิธีตรวจ ใช้เครื่องมือฝั่งอินฟรา (ไม่ต้องใช้โค้ดเกม)
กรณีจริง CCP Games 2014: เซิร์ฟเวอร์ EVE Online โหลดเกินในศึกกองยานขนาดใหญ่ที่ HED-GP
แหล่งอ้างอิง 5 รายการ
ID sp-hotzone · ผู้รับผิดชอบหลัก พัฒนาเซิร์ฟเวอร์ (ทีมพัฒนาเกม) · ร่วมกับ อินฟราเซิร์ฟเวอร์ (ทีมอินฟรา)
ในโครงสร้างที่แต่ละพื้นที่มีเธรดดูแลตัวเดียว ถ้าคนแห่ไปที่จุดเดียว คอร์ตัวนั้นตัวเดียวจะขึ้นไป 100%
ทำไม เธรดหนึ่งตัวดูแลหนึ่งพื้นที่ (แชนแนล) → ผลคือ ถ้าคนแห่ไปที่จุดเดียว คอร์นั้นเต็มอยู่ตัวเดียว ส่วนคอร์อื่นยังว่าง → บนหน้าจอ แลคเฉพาะพื้นที่นั้น พื้นที่อื่นปกติ
อาการ สโลว์โมชั่น , อินพุตดีเลย์
ปัจจัย การหยุดชะงัก
ใครเจอ บางจุด/บางแชนแนล
เกิดเมื่อไร ตอนคนแห่มารวมกัน
ผู้รับผิดชอบ ผู้รับผิดชอบหลัก พัฒนาเซิร์ฟเวอร์ (ทีมพัฒนาเกม) · ร่วมกับ อินฟราเซิร์ฟเวอร์ (ทีมอินฟรา)
งานฝั่งทีมพัฒนาเกม กระจายผู้เล่นไปหลายแชนแนล, ทำงานภายในพื้นที่แบบขนาน, จำกัดจำนวนผู้เล่น
งานฝั่งทีมอินฟรา เพิ่มอัตราการใช้ CPU แยกตามคอร์ในการมอนิเตอร์และ alert (คอร์เดียวที่เต็มจะจมหายในค่าเฉลี่ยของทั้งเซิร์ฟเวอร์)
ตัวเลขที่ควรรู้ บนเซิร์ฟเวอร์ 16 คอร์ ต่อให้คอร์หนึ่งอยู่ที่ 100% อัตราการใช้ CPU รวมของเซิร์ฟเวอร์ก็ดูเหมือนแค่ประมาณ 6% ต้องดูอัตราการใช้แยกตามคอร์จึงจะเจอ
บนกราฟ สูงตามจำนวนคนและโหลด · อัตราการใช้ CPU แยกตามคอร์, CPU แยกตามเธรด
จุดที่ต้องดู อัตราการใช้แยกตามคอร์จาก mpstat -P ALL 1 และ CPU แยกตามเธรดของโปรเซสเกมจาก pidstat -t 1 เทียบกับจำนวนผู้เล่นในโซนที่เธรดที่ยุ่งที่สุดดูแล สัญญาณว่าใช่ CPU รวมของเซิร์ฟเวอร์ต่ำ แต่มีเธรดเดียว (คอร์เดียว) อยู่ใกล้ 100% และตอนนั้นคนกระจุกอยู่ในโซนที่เธรดนั้นดูแล สัญญาณว่าไม่ใช่ หลายคอร์สูงพอ ๆ กัน: ทั้งเซิร์ฟเวอร์โหลดเกิน ถ้า %soft (การประมวลผลแพ็กเก็ตขาเข้า) สูงแค่คอร์เดียว: น่าจะเป็นอินเทอร์รัปต์ของ NIC กระจุกที่คอร์เดียว วิธีตรวจ ใช้เครื่องมือฝั่งอินฟรา (ไม่ต้องใช้โค้ดเกม)
รายละเอียดเพิ่มเติม พื้นที่อื่นจะยังปกติก็ต่อเมื่อแต่ละพื้นที่รันทิกแยกกัน ถ้าเป็นโครงสร้างที่เธรดของหลายพื้นที่รอกันทุกทิกแล้วขยับไปทิกถัดไปพร้อมกัน พื้นที่ที่ยุ่งที่สุดเพียงพื้นที่เดียวจะทำให้ทิกของทั้งเซิร์ฟเวอร์ช้าลง
กรณีจริง CCP Games 2014: เซิร์ฟเวอร์ EVE Online โหลดเกินในศึกกองยานขนาดใหญ่ที่ HED-GP
แหล่งอ้างอิง 3 รายการ
ID sp-lock · ผู้รับผิดชอบหลัก พัฒนาเซิร์ฟเวอร์ (ทีมพัฒนาเกม)
ถ้าหลายเธรดรอล็อกตัวเดียวเพื่อเขียนข้อมูลเดียวกัน ต่อให้เพิ่มเธรด ก็ทำงานได้ทีละตัวเท่านั้น
ทำไม หลายเธรดใช้ข้อมูลที่ใช้ร่วมกันพร้อมกัน เช่น ตลาดประมูลหรือคลังกิลด์ → ผลคือ เธรดอื่นต้องรอจนเธรดที่ถือล็อกทำงานเสร็จ → บนหน้าจอ ช้าเฉพาะบางฟีเจอร์ ถ้าหนัก ทิกทั้งหมดก็ช้าไปด้วย
อาการ อินพุตดีเลย์ , ค้าง
ปัจจัย การหยุดชะงัก
ใครเจอ เฉพาะบางฟีเจอร์, ทั้งเซิร์ฟเวอร์
เกิดเมื่อไร ตอนคนแห่มารวมกัน
ผู้รับผิดชอบ ผู้รับผิดชอบหลัก พัฒนาเซิร์ฟเวอร์ (ทีมพัฒนาเกม)
งานฝั่งทีมพัฒนาเกม แบ่งล็อกให้ละเอียดขึ้น, ลดงานที่ทำในล็อก, ใช้โครงสร้างแบบส่งข้อความ (กำหนดเธรดเจ้าของให้ข้อมูลแต่ละชุด แล้วให้เธรดอื่นส่งคำขอเป็นข้อความเท่านั้น)
ตัวเลขที่ควรรู้ ถ้างานในล็อกคิดเป็น 20% ของงานทั้งหมด ต่อให้เพิ่มเธรดเท่าไร throughput ก็ได้สูงสุด 5 เท่าของตอนมีเธรดเดียว ถ้า 40% จะหยุดที่ 2.5 เท่า
บนกราฟ สูงตามจำนวนคนและโหลด · เวลาประมวลผลคำขอ, CPU และ context switch แยกตามเธรด
จุดที่ต้องดู voluntary context switch แยกตามเธรด (cswch/s คือจำนวนครั้งที่หยุดรอทรัพยากร) จาก pidstat -w -t 1, จุดที่เธรดออกจาก CPU ไปรอ (เวลารอแยกตาม call stack) จาก bcc offcputime -p สำหรับ .NET ดูจำนวนการแย่งล็อกใน dotnet-counters (.NET 9 ขึ้นไปคือ dotnet.monitor.lock_contentions, 8 ลงไปคือ Monitor Lock Contention Count) สัญญาณว่าใช่ โหลดเพิ่มแต่อัตราการใช้ CPU ยังต่ำ ขณะที่เวลาประมวลผลเพิ่มขึ้น เวลารอส่วนใหญ่กระจุกอยู่ใน call stack ที่พยายามถือล็อก และจำนวนการแย่งล็อกสูงขึ้นตาม สัญญาณว่าไม่ใช่ CPU เต็ม: เป็นปัญหาปริมาณการคำนวณ (ทิกเกินงบเวลา, พื้นที่ที่รันบนเธรดเดียวโหลดเกิน) ถ้ารอการเรียก DB หรือไฟล์ น่าจะเป็น synchronous call บนเธรดเกม วิธีตรวจ ใช้เครื่องมือฝั่งอินฟรา (ไม่ต้องใช้โค้ดเกม)
รายละเอียดเพิ่มเติม เกิดในโครงสร้างที่หลายเธรดแก้ข้อมูลเกมร่วมกัน โครงสร้างที่ให้เธรดเดียวดูแลแต่ละพื้นที่หรือฟีเจอร์และสื่อสารกันด้วยข้อความเท่านั้นแทบไม่มีล็อก แต่ต้องระวังปัญหางานกระจุกที่เธรดเดียว (พื้นที่ที่รันบนเธรดเดียวโหลดเกิน) ถ้าเธรดเกมรอล็อกที่งานบันทึกข้อมูลซึ่งช้าถืออยู่ ทั้งทิกนั้นจะหยุดชะงัก
กรณีจริง Roblox 2021: Roblox ล่ม 73 ชั่วโมง: การแย่งทรัพยากรในคลัสเตอร์ service discovery (Consul)
แหล่งอ้างอิง 6 รายการ Amdahl's Law in the Multicore Era IEEE เปเปอร์ IEEE Computer 2008 (ฉบับที่ผู้เขียนเผยแพร่เอง) ถ้าสัดส่วนที่แบ่งทำแบบขนานไม่ได้คือ 1−f ต่อให้เพิ่มคอร์เท่าไร ความเร็วที่เพิ่มขึ้นก็ไม่เกิน 1/(1−f) (กฎของ Amdahl) Request scheduling Microsoft grain (actor) ของ Orleans ใช้โมเดลรันแบบเธรดเดียวที่ประมวลผลคำขอทีละรายการจนจบ จึงไม่มีการแก้สถานะพร้อมกัน, ถ้า grain รอการตอบกลับของกันและกันอาจเกิดเดดล็อก pidstat(1) — Linux manual page sysstat cswch/s ของ -w คือจำนวน voluntary context switch ที่หยุดเพราะรอทรัพยากร, -t แสดงแยกตามเธรด Demonstrations of offcputime, the Linux eBPF/bcc version IO Visor รวมเวลาที่เธรดหยุดอยู่นอก CPU (off-CPU) แยกตาม call stack, -p ระบุโปรเซส Well-known EventCounters in .NET Microsoft Monitor Lock Contention Count (monitor-lock-contention-count): จำนวนครั้งที่เกิดการแย่งกันตอนพยายามถือ monitor lock .NET runtime metrics .NET dotnet.monitor.lock_contentions ตั้งแต่ .NET 9: จำนวนครั้งที่เกิดการแย่งกันตอนพยายามถือ monitor lock นับตั้งแต่โปรเซสเริ่ม
ID sp-deadlock · ผู้รับผิดชอบหลัก พัฒนาเซิร์ฟเวอร์ (ทีมพัฒนาเกม)
ถ้าสองเธรดต่างรอล็อกที่อีกฝ่ายถืออยู่ ทั้งคู่จะหยุดไปตลอดกาล
ทำไม เธรด A ถือล็อก 1 แล้วรอล็อก 2 ส่วน B ถือล็อก 2 แล้วรอล็อก 1 → ผลคือ ทั้งคู่หยุดไปตลอดกาล และเธรดที่เกี่ยวข้องก็หยุดตามกันเป็นทอด ๆ → บนหน้าจอ ทั้งเซิร์ฟเวอร์ค้าง และเมื่อ watchdog รีสตาร์ต ทุกคนก็หลุด
อาการ ค้าง , หลุด
ปัจจัย การหยุดชะงัก
ใครเจอ ทั้งเซิร์ฟเวอร์, เฉพาะบางฟีเจอร์
เกิดเมื่อไร สุ่มเป็นครั้งคราว, ตอนคนแห่มารวมกัน
ผู้รับผิดชอบ ผู้รับผิดชอบหลัก พัฒนาเซิร์ฟเวอร์ (ทีมพัฒนาเกม)
งานฝั่งทีมพัฒนาเกม กำหนดกฎลำดับการถือล็อก, ใช้ล็อกที่มีไทม์เอาต์, มี watchdog และเก็บ thread dump ตอนที่โปรเซสหยุด
บนกราฟ การเชื่อมต่อหลุดพร้อมกัน · จำนวนการเชื่อมต่อ, ปริมาณที่เซิร์ฟเวอร์ส่งออก
จุดที่ต้องดู call stack ของทุกเธรดที่เก็บไว้ระหว่างที่หยุด JVM ใช้ jstack (หาเดดล็อกและแสดงให้อัตโนมัติ) .NET ใช้ dotnet-stack เซิร์ฟเวอร์ native ใช้ thread apply all bt ของ gdb หรือใช้ gcore เก็บ core file ไว้ก่อน แล้วรีสตาร์ตและวิเคราะห์ภายหลัง สัญญาณว่าใช่ มีเธรดตั้งแต่สองตัวขึ้นไปหยุดอยู่ใน stack ที่รอล็อกที่อีกฝ่ายถือ และระหว่างนั้นอัตราการใช้ CPU ของโปรเซสใกล้ 0 สัญญาณว่าไม่ใช่ ระหว่างที่หยุดมีเธรดหนึ่งวิ่งอยู่ที่ CPU 100%: ลูปไม่รู้จบ ถ้าเธรดรอการตอบกลับจาก DB หรือภายนอก: น่าจะเป็น synchronous call หรือ thread pool หมด วิธีตรวจ ใช้เครื่องมือฝั่งอินฟรา (ไม่ต้องใช้โค้ดเกม)
แหล่งอ้างอิง 6 รายการ
ID sp-sync-call · ผู้รับผิดชอบหลัก พัฒนาเซิร์ฟเวอร์ (ทีมพัฒนาเกม)
ถ้ารอการตอบกลับจาก DB หรือการเขียนไฟล์กลางทิก การดำเนินเกมทั้งหมดบนเซิร์ฟเวอร์จะหยุดไปเท่ากับเวลานั้น
ทำไม ทิกต้องรอการอ่านหรือบันทึก DB, การเขียน log หรือการเรียก API ภายนอก → ผลคือ ถ้า DB ใช้ 100 ms ทิกก็หยุด 100 ms → บนหน้าจอ ทุกครั้งที่ DB หรือดิสก์ช้าลง ทั้งฟิลด์จะหยุดแวบ
อาการ ค้าง , กระตุก
ปัจจัย การหยุดชะงัก
ใครเจอ บางจุด/บางแชนแนล, ทั้งเซิร์ฟเวอร์
เกิดเมื่อไร ตอนทำแอ็กชันบางอย่าง, สุ่มเป็นครั้งคราว
ผู้รับผิดชอบ ผู้รับผิดชอบหลัก พัฒนาเซิร์ฟเวอร์ (ทีมพัฒนาเกม)
งานฝั่งทีมพัฒนาเกม ส่งงานที่ช้าทั้งหมด (อ่านหรือบันทึก DB, เขียน log, เรียก API ภายนอก) ไปทำแบบ asynchronous แล้วนำผลมาใช้ในทิกถัดไป (ถ้าแค่ตั้งไทม์เอาต์ ระหว่างรอก็ยังหยุดอยู่ดี)
ตัวเลขที่ควรรู้ ต่อให้เวลาไปกลับถึง DB ในดาต้าเซ็นเตอร์เดียวกันแค่ 0.5 ms ถ้าเรียก 100 ครั้งในหนึ่งทิกก็เป็น 50 ms ลำพังส่วนนี้ก็กินงบเวลาที่ 20 ทิกจนหมด
บนกราฟ พุ่งแบบสุ่มเป็นครั้งคราว · เวลาต่อทิกของเซิร์ฟเวอร์, ความหน่วงของคิวรี DB
จุดที่ต้องดู กราฟเวลาต่อทิกวางบนแกนเวลาเดียวกับความหน่วงของคิวรี DB (slow query log เป็นต้น) และความหน่วงของดิสก์ ถ้าไม่มีเมตริกทิก ให้ใช้ bcc offcputime -p ดูว่าเธรดเกมรออยู่ที่ไหน สัญญาณว่าใช่ เวลาที่ทิกพุ่งตรงกับเวลาที่ความหน่วงของ DB หรือไฟล์พุ่ง และเวลารอของเธรดเกมกระจุกอยู่ใน call stack ที่รับการตอบกลับจาก DB หรือเขียนไฟล์ สัญญาณว่าไม่ใช่ ความหน่วงของ DB และดิสก์ปกติ แต่ทิกพุ่ง: น่าจะเป็น GC pause หรือการแย่งล็อก วิธีตรวจ ต้องมี log หรือเมตริกจากเซิร์ฟเวอร์/ไคลเอนต์เกม
แหล่งอ้างอิง 3 รายการ
ID sp-queue · ผู้รับผิดชอบหลัก พัฒนาเซิร์ฟเวอร์ (ทีมพัฒนาเกม)
ถ้าคำขอเข้ามาเร็วกว่าความเร็วในการประมวลผลจนกองในคิว คำขอที่อยู่ท้ายคิวจะถูกประมวลผลอีกหลายวินาทีต่อมาหรือถูกทิ้ง
ทำไม คำขอมาถึงเร็วกว่าความเร็วในการประมวลผล → ผลคือ คิวยาวขึ้น และถ้าเกินขีดจำกัดก็ทิ้ง → บนหน้าจอ สกิลและเทรดตอบสนองช้า หรือกดไม่ติด
อาการ อินพุตดีเลย์ , กดไม่ติด/โรลแบ็ค
ปัจจัย ความหน่วง, แพ็กเก็ตหาย
ใครเจอ บางจุด/บางแชนแนล, เฉพาะบางฟีเจอร์
เกิดเมื่อไร ตอนคนแห่มารวมกัน
ผู้รับผิดชอบ ผู้รับผิดชอบหลัก พัฒนาเซิร์ฟเวอร์ (ทีมพัฒนาเกม)
งานฝั่งทีมพัฒนาเกม มอนิเตอร์ความยาวคิว, ใช้นโยบายทิ้งคำขอเก่าก่อน, ประมวลผลแบบขนาน
บนกราฟ ชนเพดานแล้วแบนราบ · ความยาวคิวและอายุของข้อความที่เก่าที่สุด, จำนวนที่ประมวลผลต่อวินาที
จุดที่ต้องดู ความยาวของแต่ละคิว อายุของข้อความที่เก่าที่สุด และจำนวนที่เข้ามา ประมวลผล และทิ้งต่อวินาทีที่เซิร์ฟเวอร์บันทึก ถ้าไม่มีเมตริกจากโค้ด ให้ดู Recv-Q ของซ็อกเก็ตเกมด้วย ss (หรือ netstat) ซึ่งคือปริมาณที่เคอร์เนลรับไว้แล้วแต่โปรเซสยังไม่ได้อ่าน สัญญาณว่าใช่ ระหว่างที่จำนวนที่เข้ามามากกว่าจำนวนที่ประมวลผล จำนวนที่ประมวลผลติดอยู่ที่ค่าหนึ่งไม่ขึ้นอีก และความยาวคิว อายุข้อความ และจำนวนที่ทิ้งเพิ่มขึ้นเรื่อย ๆ สัญญาณว่าไม่ใช่ คิวสั้นและข้อความยังใหม่ แต่ตอบสนองช้า: น่าจะเป็นความหน่วงของเน็ตหรือตัวทิกเองที่ช้า วิธีตรวจ ต้องมี log หรือเมตริกจากเซิร์ฟเวอร์/ไคลเอนต์เกม
กรณีจริง CCP Games 2014: เซิร์ฟเวอร์ EVE Online โหลดเกินในศึกกองยานขนาดใหญ่ที่ HED-GP
แหล่งอ้างอิง 4 รายการ
ID sp-timer-burst · ผู้รับผิดชอบหลัก พัฒนาเซิร์ฟเวอร์ (ทีมพัฒนาเกม)
ถ้าการรีสปอนของมอนสเตอร์ทั้งหมด การหมดอายุของบัฟทั้งหมด และของรางวัลตอนตรงชั่วโมงมารวมในทิกเดียวกัน ทิกนั้นจะหนักขึ้นหลายสิบเท่า
ทำไม ตัวจับเวลาของการรีสปอน การหมดอายุ ของรางวัล และการบันทึกอัตโนมัติถูกตั้งไว้เวลาเดียวกัน → ผลคือ ทิกนั้นทิกเดียวมีงานมากกว่าปกติหลายสิบเท่า → บนหน้าจอ หยุดแวบหนึ่งครั้งทุกเวลาที่กำหนด
อาการ ค้าง , กระตุก
ปัจจัย การหยุดชะงัก
ใครเจอ บางจุด/บางแชนแนล, ทั้งเซิร์ฟเวอร์
เกิดเมื่อไร เป็นรอบสม่ำเสมอ
ผู้รับผิดชอบ ผู้รับผิดชอบหลัก พัฒนาเซิร์ฟเวอร์ (ทีมพัฒนาเกม)
งานฝั่งทีมพัฒนาเกม สุ่มกระจายเวลาของตัวจับเวลาเล็กน้อย, แบ่งงานไปประมวลผลในหลายทิก
บนกราฟ พุ่งเป็นรอบ · เวลาต่อทิกของเซิร์ฟเวอร์
จุดที่ต้องดู รวบรวมเวลาที่ทิกพุ่งแล้วดูช่วงห่าง (ตรงชั่วโมง, ทุก 5 นาที เป็นต้น) เทียบกับรายการตัวจับเวลาของการรีสปอน การหมดอายุบัฟ ของรางวัล และการบันทึกอัตโนมัติที่ทำงานในเวลาเดียวกัน สัญญาณว่าใช่ ทิกพุ่งเวลาเดิมหรือช่วงห่างเดิมทุกครั้ง และเวลานั้นมีงานจากตัวจับเวลาของเกมที่ทำงานพร้อมกันรวดเดียว สัญญาณว่าไม่ใช่ เป็นรอบ แต่ตรงกับเวลาหยุดใน GC log หรือเวลา cron และการสำรองข้อมูลของเซิร์ฟเวอร์: น่าจะเป็น “GC ของเซิร์ฟเวอร์หยุดทั้งระบบ” หรือ “งานตามกำหนดเวลา (scheduled job)” วิธีตรวจ ต้องมี log หรือเมตริกจากเซิร์ฟเวอร์/ไคลเอนต์เกม
แหล่งอ้างอิง 1 รายการ Timeouts, retries, and backoff with jitter AWS Amazon Builders' Library เพิ่ม jitter ให้ตัวจับเวลา งานตามรอบ และงานที่หน่วงเวลาไว้ทุกตัว เพื่อกระจายโหลดที่จะมารวมกันในเวลาเดียวกัน, กรณีที่คำขอรอบ 1 นาทีจากเซิร์ฟเวอร์หลายเครื่องมากระจุกในไม่กี่วินาทีแรกของทุกนาที
ID sp-pathfinding · ผู้รับผิดชอบหลัก พัฒนาเซิร์ฟเวอร์ (ทีมพัฒนาเกม)
ถ้ามอนสเตอร์หลายร้อยตัวไล่ตามผู้เล่นและคำนวณเส้นทางพร้อมกัน จะกิน CPU มาก
ทำไม มอนสเตอร์จำนวนมากไล่ตามพร้อมกันจากการลากมอนหรือการ spawn ครั้งใหญ่ → ผลคือ มอนสเตอร์แต่ละตัวคำนวณ pathfinding ของตัวเอง → บนหน้าจอ สโลว์โมชั่นเฉพาะในจุดฟาร์มนั้น
อาการ สโลว์โมชั่น
ปัจจัย การหยุดชะงัก
ใครเจอ บางจุด/บางแชนแนล
เกิดเมื่อไร ตอนคนแห่มารวมกัน
ผู้รับผิดชอบ ผู้รับผิดชอบหลัก พัฒนาเซิร์ฟเวอร์ (ทีมพัฒนาเกม)
งานฝั่งทีมพัฒนาเกม แคชเส้นทาง, จำกัดจำนวนครั้งที่คำนวณ, แบ่งไปคำนวณในหลายทิก
บนกราฟ สูงตามจำนวนคนและโหลด · เวลาต่อทิกของเซิร์ฟเวอร์, จำนวนมอนสเตอร์แยกตามโซน
จุดที่ต้องดู จำนวนมอนสเตอร์ที่กำลังไล่ตามผู้เล่นและเวลาต่อทิกแยกตามโซน ถ้าไม่ได้นับแยกไว้ ให้ดูสัดส่วน CPU แยกตามฟังก์ชันของโปรเซสเกมด้วย perf top -p สัญญาณว่าใช่ ตอนลากมอนหรือ spawn ครั้งใหญ่ เวลาต่อทิกเพิ่มขึ้น และฟังก์ชัน pathfinding (ค้นหาเส้นทาง) กินสัดส่วนเวลา CPU มาก สัญญาณว่าไม่ใช่ มอนสเตอร์น้อยแต่ผู้เล่นเยอะแล้วทิกเพิ่ม: น่าจะเป็นการคำนวณระยะมองเห็นหรือ broadcast วิธีตรวจ ต้องมี log หรือเมตริกจากเซิร์ฟเวอร์/ไคลเอนต์เกม
แหล่งอ้างอิง 2 รายการ
ID sp-serialize · ผู้รับผิดชอบหลัก พัฒนาเซิร์ฟเวอร์ (ทีมพัฒนาเกม)
การแปลงข้อมูลที่จะส่งเป็นไบต์และบีบอัดก็ใช้ CPU เช่นกัน และเมื่อคนเยอะ ต้นทุนนี้จะพุ่งสูง
ทำไม แปลง struct เป็นไบต์และบีบอัดทุกครั้งที่อัปเดต → ผลคือ ต้นทุนเพิ่มตามจำนวนคนยกกำลังสอง → บนหน้าจอ การส่งช้าลงจนเกิดอินพุตดีเลย์
อาการ อินพุตดีเลย์
ปัจจัย การหยุดชะงัก, ความหน่วง
ใครเจอ บางจุด/บางแชนแนล
เกิดเมื่อไร ตอนคนแห่มารวมกัน
ผู้รับผิดชอบ ผู้รับผิดชอบหลัก พัฒนาเซิร์ฟเวอร์ (ทีมพัฒนาเกม)
งานฝั่งทีมพัฒนาเกม ใช้แพ็กเก็ตที่สร้างครั้งเดียวซ้ำกับหลายคน, ใช้ฟอร์แมตที่เบา
บนกราฟ สูงตามจำนวนคนและโหลด · อัตราการใช้ CPU ของเซิร์ฟเวอร์, CPU ของเธรดที่สร้างแพ็กเก็ต
จุดที่ต้องดู สัดส่วนเวลา CPU ของโปรเซสเกมที่ใช้ในฟังก์ชัน serialization การบีบอัด และการเข้ารหัส (รวมฟังก์ชันของไลบรารีอย่าง zlib, LZ4 และ OpenSSL) จาก perf top -p เทียบระหว่างตอนคนน้อยกับตอนคนแห่ สัญญาณว่าใช่ ยิ่งคนแห่มาก สัดส่วนของฟังก์ชัน serialization การบีบอัด และการเข้ารหัสยิ่งสูง และ CPU ของเธรดที่สร้างแพ็กเก็ตเต็มก่อน สัญญาณว่าไม่ใช่ ฟังก์ชันเหล่านี้กินสัดส่วนน้อย: น่าจะเป็นการคำนวณระยะมองเห็นหรือลอจิกของเกม วิธีตรวจ ใช้เครื่องมือฝั่งอินฟรา (ไม่ต้องใช้โค้ดเกม)
รายละเอียดเพิ่มเติม ถ้าการเชื่อมต่อเข้ารหัสแพ็กเก็ต (TLS, DTLS เป็นต้น) การเข้ารหัสและถอดรหัสก็ใช้ CPU ด้วย การเข้ารหัสทำแยกต่อการเชื่อมต่อ ต่อให้ใช้แพ็กเก็ตที่สร้างครั้งเดียวซ้ำกับหลายคน ต้นทุนการเข้ารหัสก็ยังเพิ่มตามจำนวนผู้รับ การเข้ารหัสแบบสมมาตรอย่าง AES-GCM เร็วพอที่คอร์เดียวจะประมวลผลได้หลาย GB ต่อวินาที ปกติจึงกินสัดส่วนน้อย แต่ความเร็วจะต่างกันมากตามขนาดของหน่วยที่เข้ารหัสในครั้งเดียว (record) ถ้ามีแพ็กเก็ตเล็กจำนวนมากแบบเกม ต้นทุนต่อไบต์จะสูงขึ้น ใน handshake ที่ทำครั้งเดียวต่อการเชื่อมต่อ เซิร์ฟเวอร์ต้องเซ็นด้วยคีย์ของใบรับรองและคำนวณการแลกเปลี่ยนคีย์ (ECDHE) คอร์เดียวเซ็นได้ประมาณ 1,100 ครั้ง (RSA 2048) ถึง 18,000 ครั้ง (ECDSA P-256) ต่อวินาที และแลกเปลี่ยนคีย์ได้ประมาณ 9,000 ครั้ง จึงเป็นภาระเมื่อคนแห่ล็อกอิน
แหล่งอ้างอิง 4 รายการ Introduction to Iris in Unreal Engine Epic Games เก็บสถานะที่ต้อง replicate เป็นสำเนาที่ quantize แล้วชุดเดียวเพื่อลดงานที่หนัก และให้หลายการเชื่อมต่อใช้งานนั้นร่วมกัน VALORANT's 128-Tick Servers Riot Games วิธีเทียบตัวแปรที่ replicate ของไคลเอนต์แต่ละรายทุกเฟรมแล้วรวบรวมค่าที่เปลี่ยน ต้องอ่านหน่วยความจำกระจัดกระจาย ซึ่งช้าและกิน CPU ของเซิร์ฟเวอร์มาก How "expensive" is crypto anyway? Cloudflare ผลวัดของ BoringSSL: AES-128-GCM ประมาณ 3.7 GB ต่อวินาที (ต่างกันมากตามขนาด record), คอร์เดียวต่อวินาทีทำ RSA 2048 signature ได้ 1,120 ครั้ง, ECDSA P-256 signature 18,477 ครั้ง และ P-256 ECDHE 9,394 ครั้ง, บนเอดจ์เซิร์ฟเวอร์ของ Cloudflare ไลบรารี TLS ใช้ CPU ประมาณ 1.8% perf-top(1) — Linux manual page perf แสดงสัดส่วนการใช้ CPU ของโปรเซสที่กำลังรัน (-p) แยกตามฟังก์ชัน (symbol) แบบเรียลไทม์
ID sp-crash · ผู้รับผิดชอบหลัก พัฒนาเซิร์ฟเวอร์ (ทีมพัฒนาเกม) · ร่วมกับ อินฟราเซิร์ฟเวอร์ (ทีมอินฟรา)
ถ้าโปรเซสเซิร์ฟเวอร์ตายเพราะข้อผิดพลาดที่ไม่ได้จัดการ ทุกคนในเซิร์ฟเวอร์นั้นจะหลุดพร้อมกัน
ทำไม ข้อผิดพลาดร้ายแรง เช่น อ้างถึงสิ่งที่ไม่มีอยู่ (null reference), ข้อมูลผิดพลาด หรือหน่วยความจำไม่พอ → ผลคือ โปรเซสเซิร์ฟเวอร์ (หรือโซน) จบการทำงาน → บนหน้าจอ ทุกคนหลุดพร้อมกัน ความคืบหน้าหลังการบันทึกครั้งล่าสุดอาจโดนโรลแบ็ค
อาการ หลุด , กดไม่ติด/โรลแบ็ค
ปัจจัย การหยุดชะงัก
ใครเจอ บางจุด/บางแชนแนล, ทั้งเซิร์ฟเวอร์
เกิดเมื่อไร สุ่มเป็นครั้งคราว, ตอนทำแอ็กชันบางอย่าง
ผู้รับผิดชอบ ผู้รับผิดชอบหลัก พัฒนาเซิร์ฟเวอร์ (ทีมพัฒนาเกม) · ร่วมกับ อินฟราเซิร์ฟเวอร์ (ทีมอินฟรา)
งานฝั่งทีมพัฒนาเกม วิเคราะห์ crash dump แล้วแก้ที่ต้นเหตุ, บันทึกข้อมูลบ่อย ๆ
งานฝั่งทีมอินฟรา รีสตาร์ตโปรเซสอัตโนมัติ, เตรียมระบบเก็บและรักษา crash dump, ตั้ง alert ทันทีที่เซิร์ฟเวอร์ล่ม
บนกราฟ การเชื่อมต่อหลุดพร้อมกัน · จำนวนการเชื่อมต่อ, จำนวนครั้งที่โปรเซสรีสตาร์ต
จุดที่ต้องดู บันทึก core dump ใน coredumpctl list (เวลา, PID, สัญญาณที่ทำให้จบ) และบันทึกการจบผิดปกติและการรีสตาร์ตของ service manager (systemd) สำหรับเซิร์ฟเวอร์ Windows ดูไฟล์ dump ที่ WER เก็บไว้ สัญญาณว่าใช่ ตอนที่จำนวนการเชื่อมต่อดิ่งลงเกือบ 0 ทันที โปรเซสเซิร์ฟเวอร์เกมจบแบบผิดปกติและทิ้ง core dump ไว้ สัญญาณว่าไม่ใช่ โปรเซสยังทำงานอยู่แต่การเชื่อมต่อหลุด: น่าจะเป็นอุปกรณ์เครือข่ายหรือ idle timeout ถ้ามีบันทึกว่า watchdog รีสตาร์ตหลังหยุดไปนาน: น่าจะเป็นลูปไม่รู้จบหรือเดดล็อก วิธีตรวจ ใช้เครื่องมือฝั่งอินฟรา (ไม่ต้องใช้โค้ดเกม)
แหล่งอ้างอิง 3 รายการ
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 เสริมตัวเดียวทำให้ทั้งเซิร์ฟเวอร์หยุด
แหล่งอ้างอิง 5 รายการ 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 ลงไป
ID sp-infinite-loop · ผู้รับผิดชอบหลัก พัฒนาเซิร์ฟเวอร์ (ทีมพัฒนาเกม)
ถ้าบั๊กทำให้ทิกหนึ่งไม่จบ เซิร์ฟเวอร์จะหยุด และ watchdog จะบังคับรีสตาร์ต
ทำไม ลูปไม่จบเพราะเงื่อนไขผิด หรือ recursion ไม่หยุด → ผลคือ ทิกไม่จบ เซิร์ฟเวอร์จึงหยุด → บนหน้าจอ ค้างแล้วทุกคนก็หลุด
อาการ ค้าง , หลุด
ปัจจัย การหยุดชะงัก
ใครเจอ บางจุด/บางแชนแนล, ทั้งเซิร์ฟเวอร์
เกิดเมื่อไร ตอนทำแอ็กชันบางอย่าง, สุ่มเป็นครั้งคราว
ผู้รับผิดชอบ ผู้รับผิดชอบหลัก พัฒนาเซิร์ฟเวอร์ (ทีมพัฒนาเกม)
งานฝั่งทีมพัฒนาเกม จำกัดจำนวนรอบของลูป, มี watchdog, เขียนเทสต์ที่จำลองอินพุตที่ก่อปัญหา
บนกราฟ การเชื่อมต่อหลุดพร้อมกัน · จำนวนการเชื่อมต่อ, CPU แยกตามเธรด
จุดที่ต้องดู CPU แยกตามเธรดจาก pidstat -t 1 ระหว่างที่หยุด และดูว่าเธรดที่วิ่งอยู่ที่ 100% วนอยู่ในฟังก์ชันไหนด้วย perf top -t (thread ID) หรือ gdb ถ้ารีสตาร์ตไปแล้ว ให้ดูบันทึก watchdog หมดเวลา (WatchdogSec ของ systemd, liveness probe ของ Kubernetes ล้มเหลว) สัญญาณว่าใช่ ระหว่างที่เซิร์ฟเวอร์หยุด เธรดเกมตัวหนึ่งติดอยู่ที่ CPU 100% และ stack วนอยู่ในฟังก์ชันหรือลูปเดิม สัญญาณว่าไม่ใช่ CPU ใกล้ 0 ระหว่างที่หยุด: น่าจะเป็นเดดล็อกหรือการรอการตอบกลับจากภายนอก วิธีตรวจ ใช้เครื่องมือฝั่งอินฟรา (ไม่ต้องใช้โค้ดเกม)
แหล่งอ้างอิง 4 รายการ
ID sp-hot-entity · ผู้รับผิดชอบหลัก พัฒนาเซิร์ฟเวอร์ (ทีมพัฒนาเกม)
ถ้าคนหลายร้อยคนตีบอสตัวเดียวพร้อมกัน การคำนวณของบอสตัวนั้นจะกระจุกที่จุดเดียว และข้อมูลการโจมตีจะถูกส่งให้ทุกคนที่มองเห็น
ทำไม คนหลายร้อยคนใช้สกิล บัฟ และดีบัฟใส่บอสตัวเดียวไม่หยุด → ผลคือ การคำนวณ HP รายการ aggro และดีบัฟของบอสกระจุกที่จุดเดียว และทุกครั้งที่โจมตี จะส่งแพ็กเก็ตตัวเลขดาเมจและเอฟเฟกต์ให้ทุกคนที่มองเห็น → บนหน้าจอ สกิลเข้าช้า ตัวเลขดาเมจขึ้นมารวดเดียว และเป็นสโลว์โมชั่นเฉพาะรอบบอส
อาการ อินพุตดีเลย์ , กรอเร็ว , สโลว์โมชั่น
ปัจจัย การหยุดชะงัก, ความหน่วง
ใครเจอ บางจุด/บางแชนแนล
เกิดเมื่อไร ตอนคนแห่มารวมกัน
ผู้รับผิดชอบ ผู้รับผิดชอบหลัก พัฒนาเซิร์ฟเวอร์ (ทีมพัฒนาเกม)
งานฝั่งทีมพัฒนาเกม รวบหรือข้ามตัวเลขดาเมจและเอฟเฟกต์ของคนอื่น, จำกัดจำนวนดีบัฟบนเป้าหมายเดียว, แบ่งการประมวลผลการโจมตีไปหลายทิก
ตัวเลขที่ควรรู้ ถ้า 800 คนตีคนละ 2 ครั้งต่อวินาที จะเป็นการโจมตี 1,600 ครั้งต่อวินาที ถ้าแจ้งทุกครั้งให้ 800 คนที่มองเห็น จะเป็น 1.28 ล้านข้อความต่อวินาที
บนกราฟ สูงตามจำนวนคนและโหลด · เวลาต่อทิกของเซิร์ฟเวอร์, จำนวนข้อความที่ส่ง
จุดที่ต้องดู เวลาต่อทิกและจำนวนแพ็กเก็ตที่ส่งช่วงสู้บอส ดูคู่กับจำนวนคนรอบบอส และถ้าทำได้ ดูจำนวนอีเวนต์ต่อวินาที (โจมตี, บัฟ, ดีบัฟ) แยกตามเป้าหมาย สัญญาณว่าใช่ เมื่อคนรอบบอสเพิ่มขึ้น เวลาต่อทิกและปริมาณที่ส่งพุ่งชัน และบอสตัวเดียวมีจำนวนอีเวนต์ต่อวินาทีมากกว่าเป้าหมายอื่นหลายสิบเท่า สัญญาณว่าไม่ใช่ แค่คนมารวมกันในจุดเดียวก็ช้าเท่ากันโดยไม่เกี่ยวกับบอส: น่าจะเป็นการคำนวณระยะมองเห็นหรือปริมาณ broadcast พุ่ง วิธีตรวจ ต้องมี log หรือเมตริกจากเซิร์ฟเวอร์/ไคลเอนต์เกม
แหล่งอ้างอิง 1 รายการ
ID sp-spawn-burst · ผู้รับผิดชอบหลัก พัฒนาเซิร์ฟเวอร์ (ทีมพัฒนาเกม) · ร่วมกับ พัฒนาไคลเอนต์ (ทีมพัฒนาเกม)
ถ้าเทเลพอร์ตเข้าเมืองที่คนแน่น เซิร์ฟเวอร์ต้องส่งรูปลักษณ์ อุปกรณ์ และสถานะของคนหลายร้อยคนที่เพิ่งมองเห็นไปพร้อมกันรวดเดียว
ทำไม โผล่ในที่ที่คนเยอะทันทีจากการเทเลพอร์ต ล็อกอิน หรือย้ายแชนแนล → ผลคือ สร้างข้อมูลทั้งหมดของคนหลายร้อยคนแล้วส่งในครั้งเดียว และ PC ของเราก็โหลดทั้งหมดในครั้งเดียว → บนหน้าจอ ค้างไปชั่วครู่หลังมาถึง, ตัวละครทยอยโผล่ช้าทีละตัว, อินพุตดีเลย์
อาการ ค้าง , อินพุตดีเลย์ , กรอเร็ว
ปัจจัย การหยุดชะงัก, ความหน่วง
ใครเจอ เราคนเดียว, บางจุด/บางแชนแนล
เกิดเมื่อไร ระหว่างเดินทาง/ย้ายแมพ, หลังล็อกอิน/หลังปิดปรับปรุง
ผู้รับผิดชอบ ผู้รับผิดชอบหลัก พัฒนาเซิร์ฟเวอร์ (ทีมพัฒนาเกม) · ร่วมกับ พัฒนาไคลเอนต์ (ทีมพัฒนาเกม)
งานฝั่งทีมพัฒนาเกม เซิร์ฟเวอร์: ทยอยส่งตามลำดับระยะใกล้ไปหลายทิก, แคชข้อมูลรูปลักษณ์ ไคลเอนต์: โหลดล่วงหน้าระหว่างหน้าโหลด, ทยอยสร้างตัวละครที่ได้รับไปหลายเฟรม
ตัวเลขที่ควรรู้ ถ้าข้อมูลรูปลักษณ์ อุปกรณ์ และบัฟของคนหนึ่งคนมีขนาด 300 ไบต์ คน 500 คนจะเป็นประมาณ 150 KB เท่ากับหลายสิบเท่าของปริมาณที่ส่งต่อทิกตามปกติ (ไม่กี่ KB) มารวมในชั่วพริบตาเดียว
บนกราฟ พุ่งทันทีหลังเปิดเซิร์ฟ/ปิดปรับปรุง · ไบต์ที่ส่งต่อการเชื่อมต่อ, เฟรมไทม์ของไคลเอนต์
จุดที่ต้องดู ไบต์และจำนวนแพ็กเก็ตที่ส่งผ่านการเชื่อมต่อนั้นในไม่กี่วินาทีหลังมาถึงที่ที่คนเยอะ (log เซิร์ฟเวอร์) และเฟรมไทม์ของไคลเอนต์ (net graph, log ไคลเอนต์) สัญญาณว่าใช่ หลังมาถึง ปริมาณที่ส่งของการเชื่อมต่อนั้นพุ่งขึ้นเป็นหลายสิบเท่าของทิกปกติแล้วค่อยลดลง และเฟรมไทม์ของไคลเอนต์พุ่งในจังหวะเดียวกัน สัญญาณว่าไม่ใช่ ย้ายไปที่ที่คนน้อยก็หยุดเหมือนกัน: น่าจะเป็นการย้ายโซน (ส่งต่อระหว่างเซิร์ฟเวอร์) หรือการโหลดของไคลเอนต์ วิธีตรวจ ต้องมี log หรือเมตริกจากเซิร์ฟเวอร์/ไคลเอนต์เกม
แหล่งอ้างอิง 2 รายการ
ID sp-entity-buildup · ผู้รับผิดชอบหลัก พัฒนาเซิร์ฟเวอร์ (ทีมพัฒนาเกม)
ถ้าไอเทมที่ตกบนพื้นซึ่งควรหายไปแล้ว ซัมมอน และตัวจับเวลาที่จบแล้วไม่ถูกเก็บกวาดจนกองสะสม ยิ่งเปิดเซิร์ฟเวอร์ไว้นาน งานในแต่ละทิกก็ยิ่งเพิ่ม
ทำไม ไอเทมบนพื้น ซัมมอน ตัวจับเวลาที่หมดอายุ และข้อมูลปาร์ตี้ที่ว่างไม่ถูกลบตามเวลา → ผลคือ รายการที่ต้องไล่ทุกทิกยาวขึ้นทุกวัน → บนหน้าจอ ทันทีหลังปิดปรับปรุงยังปกติ แต่ผ่านไปไม่กี่วัน เฉพาะเซิร์ฟเวอร์หรือพื้นที่นั้นก็ค่อย ๆ อืดขึ้นเรื่อย ๆ
อาการ สโลว์โมชั่น , กระตุก , อินพุตดีเลย์
ปัจจัย การหยุดชะงัก
ใครเจอ ทั้งเซิร์ฟเวอร์, บางจุด/บางแชนแนล
เกิดเมื่อไร ยิ่งเปิดไว้นานยิ่งเป็น
ผู้รับผิดชอบ ผู้รับผิดชอบหลัก พัฒนาเซิร์ฟเวอร์ (ทีมพัฒนาเกม)
งานฝั่งทีมพัฒนาเกม เก็บจำนวนเอนทิตีแยกตามพื้นที่เป็นเมตริกเพื่อดูแนวโน้ม, กำหนดอายุและจำนวนสูงสุดให้เอนทิตีแต่ละแบบ, เก็บกวาดเป็นรอบ
ตัวเลขที่ควรรู้ ถ้าเซิร์ฟเวอร์ไล่ทุกเอนทิตีหนึ่งรอบทุกทิก เมื่อจำนวนเอนทิตีเพิ่มเป็นสองเท่า เวลาต่อทิกในส่วนนั้นก็เพิ่มเป็นสองเท่า
บนกราฟ ค่อย ๆ ขึ้นแล้วดิ่งลง · จำนวนเอนทิตีแยกตามโซน, เวลาต่อทิกของเซิร์ฟเวอร์
จุดที่ต้องดู จำนวนเอนทิตี (ไอเทมบนพื้น, ซัมมอน, ตัวจับเวลา) และเวลาต่อทิกแยกตามโซนและเซิร์ฟเวอร์ ในช่วงที่ยาวกว่ารอบปิดปรับปรุง (หลายสัปดาห์) สัญญาณว่าใช่ จำนวนเอนทิตีและเวลาต่อทิกเริ่มต่ำหลังปิดปรับปรุง ไต่ขึ้นทุกวัน แล้วดิ่งลงเมื่อปิดปรับปรุงหรือรีสตาร์ตวนซ้ำ ระหว่างนั้นหน่วยความจำยังเหลือเฟือ สัญญาณว่าไม่ใช่ ทิกไม่เปลี่ยนแต่หน่วยความจำเพิ่มขึ้นเรื่อย ๆ: น่าจะเป็นหน่วยความจำรั่ว วิธีตรวจ ต้องมี log หรือเมตริกจากเซิร์ฟเวอร์/ไคลเอนต์เกม
รายละเอียดเพิ่มเติม คล้ายหน่วยความจำรั่วตรงที่ยิ่งเปิดนานยิ่งแย่ แต่ต่างกันตรงที่หน่วยความจำยังเหลือเฟือ มีแค่เวลาต่อทิกที่เพิ่มขึ้น ถ้ากราฟจำนวนเอนทิตีเป็นรูปฟันเลื่อยตามรอบปิดปรับปรุง ก็คือกรณีนี้
แหล่งอ้างอิง 2 รายการ
ID sp-patch-traffic · ผู้รับผิดชอบหลัก พัฒนาเซิร์ฟเวอร์ (ทีมพัฒนาเกม) · ร่วมกับ อินฟราเซิร์ฟเวอร์ (ทีมอินฟรา), อินฟราเครือข่าย (ทีมอินฟรา)
ถ้าคอนเทนต์ เอฟเฟกต์ หรือรายการที่ต้องซิงก์ใหม่ทำให้ขนาดและความถี่ของแพ็กเก็ตเพิ่ม เซิร์ฟเวอร์ที่เคยลื่นจะเริ่มชนขีดจำกัด MTU แบนด์วิดท์ และจำนวนแพ็กเก็ตหลังลงแพตช์
ทำไม แพตช์เพิ่มเอฟเฟกต์สกิล รายการที่ต้องซิงก์ หรือข้อมูลไอเทมใหม่ แพ็กเก็ตจึงใหญ่ขึ้นหรือถี่ขึ้น → ผลคือ แพ็กเก็ตใหญ่เกิน MTU จนถูกแบ่งชิ้น และปริมาณที่เพิ่มขึ้นไปชนแบนด์วิดท์ ขีดจำกัด PPS ของคลาวด์ และ send buffer → บนหน้าจอ ตั้งแต่ลงแพตช์ ที่ที่คนเยอะมีอาการวาร์ป สกิลไม่ออก และอินพุตดีเลย์ ฝั่งอินฟราไม่ได้เปลี่ยนอะไร แต่แพ็กเก็ตหายเพิ่มขึ้น
อาการ วาร์ป , กดไม่ติด/โรลแบ็ค , อินพุตดีเลย์
ปัจจัย แพ็กเก็ตหาย, ความหน่วง
ใครเจอ ทั้งเซิร์ฟเวอร์, บางจุด/บางแชนแนล, บางพื้นที่/บาง ISP
เกิดเมื่อไร ตอนคนแห่มารวมกัน, ช่วงพีคหัวค่ำ, ตลอดเวลา
ผู้รับผิดชอบ ผู้รับผิดชอบหลัก พัฒนาเซิร์ฟเวอร์ (ทีมพัฒนาเกม) · ร่วมกับ อินฟราเซิร์ฟเวอร์ (ทีมอินฟรา), อินฟราเครือข่าย (ทีมอินฟรา)
งานฝั่งทีมพัฒนาเกม แบ่งแพ็กเก็ตเองให้ไม่เกิน 1,200 ไบต์, รายการซิงก์ใหม่ให้ส่งเฉพาะส่วนที่เปลี่ยนและลดความถี่ตามระยะห่างและความสำคัญ, ก่อน deploy ให้เทียบแพ็กเก็ตและไบต์ต่อวินาทีต่อผู้เล่นและขนาดแพ็กเก็ตใหญ่สุดกับบิลด์ก่อนหน้าบนเซิร์ฟเวอร์ทดสอบ, ใส่เวอร์ชันบิลด์ไว้ในเมตริกทราฟฟิก
งานฝั่งทีมอินฟรา เครื่องเซิร์ฟเวอร์/OS: ทำเครื่องหมายเวลา deploy บนกราฟ และเทียบแพ็กเก็ตและไบต์ต่อวินาทีต่อผู้เล่นกับขนาดแพ็กเก็ตเฉลี่ยก่อนและหลัง deploy, ตั้ง alert ตัวนับเกินขีดจำกัดของอินสแตนซ์, ถ้าจำเป็นให้ใช้อินสแตนซ์ที่ใหญ่ขึ้น เครือข่าย: ตรวจขีดความสามารถของไฟร์วอลล์ โหลดบาลานเซอร์ และอุปกรณ์ป้องกัน DDoS และดูว่าบล็อก fragment หรือไม่
ตัวเลขที่ควรรู้ แพ็กเก็ต UDP ที่ไม่เกิน 1,200 ไบต์ถือว่าปลอดภัย path MTU ของอินเทอร์เน็ตปกติคือ 1,500 ไบต์ และจะเล็กลงเมื่อผ่าน tunnel (ถ้าเป็น GRE tunnel คือ 1,476 ไบต์) แพ็กเก็ตที่เกิน path MTU จะถูกแบ่งชิ้นหรือถูกทิ้ง และแพ็กเก็ตที่ถูกแบ่งชิ้นจะเสียทั้งหมดแม้ fragment หายไปแค่ชิ้นเดียว ถ้าแพ็กเก็ตต่อวินาทีต่อผู้เล่นเพิ่ม 20% ทั้งเซิร์ฟเวอร์ก็เพิ่ม 20% อินสแตนซ์ที่ใช้อยู่ใกล้ขีดจำกัดจะล้นทันที
บนกราฟ ขึ้นเป็นขั้นบันไดจากจุดหนึ่ง · แพ็กเก็ตและไบต์ต่อวินาทีต่อผู้เล่น, ขนาดแพ็กเก็ตเฉลี่ย
จุดที่ต้องดู แพ็กเก็ตและไบต์ต่อวินาทีของ NIC เซิร์ฟเวอร์ (rxpck/s, txpck/s, rxkB/s และ txkB/s จาก sar -n DEV, บน EC2 คือ NetworkPacketsOut และ NetworkOut) หารด้วยจำนวนผู้เล่นออนไลน์พร้อมกัน แล้วเทียบก่อนและหลังเวลา deploy ขนาดแพ็กเก็ตเฉลี่ยคือไบต์ ÷ แพ็กเก็ต ส่วนการกระจายขนาด ให้ใช้สถิติ Packet Lengths ของ Wireshark กับ packet capture สัญญาณว่าใช่ ตั้งแต่หลัง deploy แพ็กเก็ตและไบต์ต่อผู้เล่นหรือขนาดแพ็กเก็ตเฉลี่ยขึ้นหนึ่งขั้นแล้วอยู่ระดับนั้น และตั้งแต่เวลาเดียวกัน จำนวน fragment ที่เซิร์ฟเวอร์สร้าง (fragcrt/s ของ sar -n IP) หรือตัวนับเกินขีดจำกัดของอินสแตนซ์ (pps_allowance_exceeded และ bw_out_allowance_exceeded ของ AWS ENA) เพิ่มขึ้น สัญญาณว่าไม่ใช่ รูปแบบทราฟฟิกก่อนและหลัง deploy เหมือนกัน แต่มีแค่ความหน่วงและแพ็กเก็ตหายที่เพิ่มขึ้น: ให้ดูการเปลี่ยนแปลงฝั่งอินฟราในเวลาเดียวกัน (คอนฟิก, เส้นทาง, อุปกรณ์, การอัปเดต OS หรือเคอร์เนล) วิธีตรวจ ใช้เครื่องมือฝั่งอินฟรา (ไม่ต้องใช้โค้ดเกม)
รายละเอียดเพิ่มเติม เมื่อมีผู้เล่นแจ้งว่า “ก่อนลงแพตช์ยังเล่นได้ปกติ” นี่คือสาเหตุฝั่งเกมที่ต้องตรวจก่อนพร้อมกับการเปลี่ยนแปลงฝั่งอินฟรา ต่อให้แพตช์โน้ตไม่ได้ระบุการเปลี่ยนแปลงด้านเครือข่าย เอฟเฟกต์หรือรายการซิงก์ใหม่เพียงอย่างเดียวก็ถูกคูณด้วยคนหลายร้อยคนในที่ที่คนเยอะ จุดที่ทราฟฟิกที่เพิ่มขึ้นไปชนขีดจำกัดจริงอยู่ในสาเหตุ “IP fragmentation ของแพ็กเก็ต UDP”, “เกินขีดจำกัด PPS ของคลาวด์”, “แบนด์วิดท์ NIC เต็ม”, “บัฟเฟอร์ซ็อกเก็ตของเคอร์เนลไม่พอ” และ “อุปกรณ์กลางทางเกินขีดความสามารถ (ไฟร์วอลล์/IPS/ระบบป้องกัน DDoS)” ส่วนสาเหตุนี้คือกรณีที่จุดเริ่มต้นที่ทำให้ชนขีดจำกัดเหล่านั้นคือแพตช์เกม จึงควรลดทราฟฟิกที่เพิ่มขึ้นจากแพตช์ก่อนจะขยายขีดจำกัด ถ้าอัปเดต OS หรือเคอร์เนลในเวลาเดียวกันด้วย ให้แยกจาก “ประสิทธิภาพเปลี่ยนไปหลังอัปเดต OS/เคอร์เนล/ไดรเวอร์/เฟิร์มแวร์” โดยดูว่าทราฟฟิกต่อผู้เล่นเปลี่ยนหรือไม่
แหล่งอ้างอิง 7 รายการ
L10 หน่วยความจำ
9 สาเหตุ · บทในฉบับหลัก
ID mem-gc · ผู้รับผิดชอบหลัก พัฒนาเซิร์ฟเวอร์ (ทีมพัฒนาเกม) · ร่วมกับ อินฟราเซิร์ฟเวอร์ (ทีมอินฟรา)
ระหว่างที่เซิร์ฟเวอร์ Java หรือ C# หยุดทุกเธรดเพื่อเก็บคืน garbage (stop-the-world) ทั้งเซิร์ฟเวอร์จะหยุดชะงักไปด้วย
ทำไม heap เต็ม GC จึงเริ่มทำงาน → ผลคือ หยุดเธรดเกมทั้งหมดแล้วเก็บคืน (ยิ่งมีข้อมูลที่ยังใช้อยู่มาก ยิ่งนาน) → บนหน้าจอ ทุกคนบนเซิร์ฟเวอร์ค้างพร้อมกันแล้วตามด้วยอาการกรอเร็ว
อาการ ค้าง , กรอเร็ว
ปัจจัย การหยุดชะงัก
ใครเจอ ทั้งเซิร์ฟเวอร์
เกิดเมื่อไร เป็นรอบสม่ำเสมอ, ยิ่งเปิดไว้นานยิ่งเป็น
ผู้รับผิดชอบ ผู้รับผิดชอบหลัก พัฒนาเซิร์ฟเวอร์ (ทีมพัฒนาเกม) · ร่วมกับ อินฟราเซิร์ฟเวอร์ (ทีมอินฟรา)
งานฝั่งทีมพัฒนาเกม ระบุ GC ที่หยุดสั้น (ZGC, Shenandoah หรือ G1 ที่ลดเวลาเป้าหมายลง) ในออปชันตอนรันโดยตรง, ลดการจัดสรรหน่วยความจำ, ปรับขนาด heap
งานฝั่งทีมอินฟรา ใช้อินสแตนซ์ที่มีหน่วยความจำพอจะให้ heap ได้อย่างเหลือเฟือ, ให้คอนเทนเนอร์มี CPU อย่างน้อย 2 ตัวและหน่วยความจำประมาณ 1.8 GB ขึ้นไป (ถ้าน้อยกว่านั้น JDK 26 ลงไปจะเลือก Serial GC เป็นค่าเริ่มต้น), มอนิเตอร์เวลา GC pause
ตัวเลขที่ควรรู้ Minor GC ที่เก็บคืนเฉพาะออบเจ็กต์ใหม่ (Young generation) ใช้เวลาหลักหน่วยถึงหลักสิบ ms ส่วน Full GC ที่เก็บคืนทั้ง heap ซึ่งมีข้อมูลที่ยังใช้อยู่ (live data) หลาย GB อาจนานเกิน 1 วินาที ZGC หยุดไม่ถึง 1 ms แทบไม่ขึ้นกับขนาด heap และ Shenandoah ก็หยุดสั้นเพราะเวลาหยุดไม่แปรตามขนาด heap
บนกราฟ พุ่งเป็นรอบ · เวลาต่อทิกของเซิร์ฟเวอร์, เวลา GC pause
จุดที่ต้องดู เปิด GC log แล้ววางช่วงที่หยุดและระยะเวลาที่หยุดซ้อนบนกราฟเวลาต่อทิกของเซิร์ฟเวอร์ Java ดูบรรทัด Pause จากออปชันตอนเริ่ม -Xlog:gc* (JDK 8 ลงไปใช้ -XX:+PrintGCDetails), .NET ดูเมตริก GC pause ของ dotnet-counters (ตั้งแต่ .NET 9 คือ dotnet.gc.pause.time, 8 ลงไปคือ % Time in GC since last GC), Go ดูบรรทัดที่ GODEBUG=gctrace=1 เขียนทุกครั้งที่ GC ทำงาน สัญญาณว่าใช่ ช่วงที่ทิกพุ่งตรงกับช่วง GC pause และระยะเวลาที่หยุดใกล้เคียงกับระยะเวลาที่ทิกพุ่ง ทุกโซนและแชนแนลบนเซิร์ฟเวอร์พุ่งพร้อมกัน สัญญาณว่าไม่ใช่ GC log ไม่มีการหยุดนานแต่ทิกยังพุ่ง: น่าจะเป็นสาเหตุอื่น เช่น ล็อก, synchronous call หรือการเขียนดิสก์ ถ้าพุ่งแค่โซนเดียว น่าจะเป็น GC ของสคริปต์เอนจิน (mem-script-gc) หรือโหลดของโซนนั้น วิธีตรวจ ใช้เครื่องมือฝั่งอินฟรา (ไม่ต้องใช้โค้ดเกม)
รายละเอียดเพิ่มเติม เป้าหมายเวลาหยุดต่อครั้งของ G1 ใน Java มีค่าเริ่มต้น 200 ms ซึ่งเท่ากับ 4 ทิกบนเซิร์ฟเวอร์ 20 ทิก ถ้าให้คอนเทนเนอร์มี CPU น้อยกว่า 2 ตัวหรือหน่วยความจำน้อยกว่าประมาณ 1.8 GB Java รุ่น JDK 26 ลงไปจะเลือก Serial GC ที่เก็บคืนด้วยเธรดเดียวเป็น GC เริ่มต้น ทำให้หยุดนานขึ้นมาก เซิร์ฟเวอร์ C# (.NET) มักเปิด server GC และ background GC ไว้ แต่การเก็บคืน generation 0 และ 1 (Gen0/1) ซึ่งเป็นที่อยู่ของออบเจ็กต์ใหม่ และ Full GC ที่มีการบีบอัด (compaction) ยังหยุดทุกเธรดอยู่ดี ส่วน Go ปกติหยุดไม่ถึง 1 ms แต่ถ้าจัดสรรหน่วยความจำมาก ฝั่งที่ขอหน่วยความจำต้องช่วยแบ่งงาน GC ทิกจึงช้าลง ไม่ว่าแบบไหน ถ้าจัดสรรเร็วกว่าเก็บคืน สุดท้ายเธรดเกมก็ต้องหยุด G1 จะเปลี่ยนไปทำ Full GC ส่วน ZGC จะหยุดเธรดที่ขอหน่วยความจำไว้จนกว่าการเก็บคืนจะเสร็จ
กรณีจริง Riot Games 2021: League of Legends EUW ขัดข้อง 5 ชั่วโมง: DB เสริมตัวเดียวทำให้ทั้งเซิร์ฟเวอร์หยุด
แหล่งอ้างอิง 10 รายการ
ID mem-script-gc · ผู้รับผิดชอบหลัก พัฒนาเซิร์ฟเวอร์ (ทีมพัฒนาเกม)
แม้เซิร์ฟเวอร์จะเขียนด้วย C++ แต่ถ้ารันเควสต์, AI และสกิลด้วยสคริปต์อย่าง Lua ระหว่างที่ GC ของสคริปต์เอนจินทำงาน โซนนั้นจะหยุดชะงัก
ทำไม สคริปต์เอนจินของแต่ละโซนรันเควสต์, AI และอีเวนต์ พร้อมสร้างออบเจ็กต์ชั่วคราวจำนวนมาก → ผลคือ ถ้า GC ของสคริปต์เอนจินเก็บคืนทีละมาก ๆ ทิกของโซนนั้นจะหยุดชะงัก → บนหน้าจอ หยุดแวบเป็นรอบเฉพาะในบางโซนหรือระหว่างบางอีเวนต์
อาการ กระตุก , ค้าง
ปัจจัย การหยุดชะงัก
ใครเจอ บางจุด/บางแชนแนล
เกิดเมื่อไร ตอนคนแห่มารวมกัน, เป็นรอบสม่ำเสมอ
ผู้รับผิดชอบ ผู้รับผิดชอบหลัก พัฒนาเซิร์ฟเวอร์ (ทีมพัฒนาเกม)
งานฝั่งทีมพัฒนาเกม ตั้งค่า GC แบบ incremental หรือ generational, ให้ GC ทำงานทีละน้อยทุกทิก, ลดออบเจ็กต์ชั่วคราวในสคริปต์
ตัวเลขที่ควรรู้ เมื่อ heap ของสคริปต์โตถึงหลายร้อย MB การเก็บคืนรวดเดียว (เมื่อปิด incremental collection หรือเป็น full collection ในโหมด generational) อาจใช้เวลาหลายสิบถึงหลายร้อย ms
บนกราฟ พุ่งเป็นรอบ · เวลาต่อทิกแยกตามโซน, หน่วยความจำของสคริปต์เอนจิน
จุดที่ต้องดู บันทึกเวลาต่อทิกของแต่ละโซนและปริมาณหน่วยความจำของสคริปต์เอนจินในโซนนั้น (Lua ใช้ collectgarbage("count")) ทุกทิก แล้ววางซ้อนบนกราฟเดียวกัน สัญญาณว่าใช่ จังหวะที่หน่วยความจำของสคริปต์ดิ่งลง (เก็บคืนรวดเดียว) ตรงกับจังหวะที่ทิกของโซนนั้นพุ่ง และโซนอื่นปกติดี สัญญาณว่าไม่ใช่ ทิกพุ่งโดยหน่วยความจำของสคริปต์ไม่เปลี่ยน: น่าจะเป็นโหลดหรือล็อกของโซนนั้น ถ้าทุกโซนบนเซิร์ฟเวอร์พุ่งพร้อมกัน น่าจะเป็น GC ของเซิร์ฟเวอร์ (mem-gc) หรือสวอป (mem-swap) วิธีตรวจ ต้องมี log หรือเมตริกจากเซิร์ฟเวอร์/ไคลเอนต์เกม
แหล่งอ้างอิง 1 รายการ Lua 5.4 Reference Manual Lua.org โหมด incremental แบ่งการเก็บคืนเป็นขั้นเล็ก ๆ แทรกระหว่างการรันโปรแกรม (ถ้าตั้งขั้นใหญ่จะกลายเป็น stop-the-world), major collection ในโหมด generational เป็น stop-the-world ที่ไล่ทุกออบเจ็กต์, collectgarbage("count") คือปริมาณหน่วยความจำทั้งหมดที่ Lua ใช้ (KB)
ID mem-alloc · ผู้รับผิดชอบหลัก พัฒนาเซิร์ฟเวอร์ (ทีมพัฒนาเกม)
ถ้าสร้างออบเจ็กต์ชั่วคราวจำนวนมากระหว่างอีเวนต์ GC จะทำงานบ่อยกว่าปกติมาก
ทำไม ออบเจ็กต์ชั่วคราวพุ่งจากไอเทมดรอป, log การต่อสู้ และของรางวัลอีเวนต์ → ผลคือ GC ทำงานบ่อยขึ้นหลายเท่า และออบเจ็กต์ที่ยังไม่ทันถูกทิ้งย้ายไปอยู่ใน Old generation ทำให้ Full GC มาเร็วขึ้นด้วย → บนหน้าจอ หยุดแวบเป็นรอบเฉพาะช่วงอีเวนต์
อาการ กระตุก , ค้าง
ปัจจัย การหยุดชะงัก
ใครเจอ ทั้งเซิร์ฟเวอร์, บางจุด/บางแชนแนล
เกิดเมื่อไร ตอนคนแห่มารวมกัน
ผู้รับผิดชอบ ผู้รับผิดชอบหลัก พัฒนาเซิร์ฟเวอร์ (ทีมพัฒนาเกม)
งานฝั่งทีมพัฒนาเกม ใช้ object pool, ใช้บัฟเฟอร์ซ้ำ, ทำ allocation profiling
บนกราฟ สูงตามจำนวนคนและโหลด · จำนวนครั้งที่ GC ทำงาน, อัตราการจัดสรรหน่วยความจำ
จุดที่ต้องดู นับจำนวนครั้งที่ GC ทำงานต่อนาทีจาก GC log (Java -Xlog:gc, Go GODEBUG=gctrace=1) ส่วน .NET ดูปริมาณการจัดสรรและจำนวนครั้งของ GC ใน dotnet-counters (ตั้งแต่ .NET 9 คือ dotnet.gc.heap.total_allocated และ dotnet.gc.collections, 8 ลงไปคือ Allocation Rate และ Gen 0 GC Count) วางซ้อนกับจำนวนผู้เล่นออนไลน์พร้อมกันและเวลาของอีเวนต์ สัญญาณว่าใช่ พออีเวนต์เริ่ม อัตราการจัดสรรและจำนวนครั้งของ GC เพิ่มชันกว่าจำนวนผู้เล่นที่เพิ่มขึ้น และหยุดสั้น ๆ ถี่ขึ้น พออีเวนต์จบก็กลับเป็นปกติ สัญญาณว่าไม่ใช่ จำนวนครั้งของ GC เท่าเดิมแต่หยุดแต่ละครั้งนานขึ้น: ข้อมูลที่ยังใช้อยู่เพิ่มขึ้น (mem-gc-thrash, mem-leak) วิธีตรวจ ใช้เครื่องมือฝั่งอินฟรา (ไม่ต้องใช้โค้ดเกม)
แหล่งอ้างอิง 3 รายการ Garbage Collector Implementation Oracle เมื่อ Young generation เต็มจะเกิด minor GC, ออบเจ็กต์ที่รอดบางส่วนย้ายไป Old generation และเมื่อ Old เต็มจะเก็บคืนทั้ง heap (นานกว่า minor มาก), -Xlog:gc เขียนหนึ่งบรรทัดต่อ GC หนึ่งครั้ง A Guide to the Go Garbage Collector Go ยิ่งอัตราการจัดสรรสูง รอบ GC ยิ่งถี่, ใช้ GODEBUG=gctrace=1 แสดงผลการติดตาม GC dotnet-counters diagnostic tool .NET ตั้งแต่ .NET 9 แสดงเป็น dotnet.gc.heap.total_allocated และ dotnet.gc.collections ส่วน .NET 8 ลงไปแสดงเป็น Allocation Rate และ Gen 0 GC Count
ID mem-leak · ผู้รับผิดชอบหลัก พัฒนาเซิร์ฟเวอร์ (ทีมพัฒนาเกม) · ร่วมกับ อินฟราเซิร์ฟเวอร์ (ทีมอินฟรา)
หน่วยความจำที่ไม่ถูกคืนค่อย ๆ สะสม จนหลายวันต่อมานำไปสู่ GC ทำงานไม่หยุด, สวอป หรือโปรเซสถูกบังคับปิด
ทำไม ข้อมูลตัวละครที่ออกจากเกมไปแล้วและ event handler ไม่ถูกคืนหน่วยความจำ → ผลคือ หน่วยความจำว่างลดลงเรื่อย ๆ ตลอดหลายวัน → บนหน้าจอ หลังปิดปรับปรุงใหม่ ๆ ยังปกติ ยิ่งผ่านไปหลายวันยิ่งแลค สุดท้ายเซิร์ฟเวอร์ล่ม
อาการ สโลว์โมชั่น , ค้าง , หลุด
ปัจจัย การหยุดชะงัก
ใครเจอ ทั้งเซิร์ฟเวอร์
เกิดเมื่อไร ยิ่งเปิดไว้นานยิ่งเป็น, ช่วงพีคหัวค่ำ
ผู้รับผิดชอบ ผู้รับผิดชอบหลัก พัฒนาเซิร์ฟเวอร์ (ทีมพัฒนาเกม) · ร่วมกับ อินฟราเซิร์ฟเวอร์ (ทีมอินฟรา)
งานฝั่งทีมพัฒนาเกม วิเคราะห์ heap dump, ทดสอบโหลดต่อเนื่องเป็นเวลานาน
งานฝั่งทีมอินฟรา มอนิเตอร์แนวโน้มการใช้หน่วยความจำของแต่ละโปรเซสและตั้ง alert
บนกราฟ ค่อย ๆ สูงขึ้น · หน่วยความจำของโปรเซส (RSS), heap หลัง GC
จุดที่ต้องดู ดูหน่วยความจำของโปรเซสเซิร์ฟเวอร์เกม (RSS จาก pidstat -r) เป็นช่วงหลายวัน และสำหรับเซิร์ฟเวอร์ที่ใช้ GC ให้ดู heap ที่เหลือหลัง GC Java ดูค่าหลัง GC จากปริมาณการใช้ก่อนและหลัง GC ในบรรทัดของ -Xlog:gc, .NET ดูขนาด heap หลัง GC ใน dotnet-counters (ตั้งแต่ .NET 9 คือ dotnet.gc.last_collection.heap.size, 8 ลงไปคือ GC Heap Size) สัญญาณว่าใช่ heap ที่เหลือหลัง GC (เส้นฐาน) สูงขึ้นทุกวันหลังรีสตาร์ต และไม่ลดลงแม้ช่วงเช้ามืดที่ผู้เล่นน้อย สัญญาณว่าไม่ใช่ เส้นฐานของ heap แบนราบแต่ RSS สูงขึ้นอย่างเดียว: น่าจะเป็น fragmentation (mem-fragment) หรือหน่วยความจำ native ถ้าขึ้นลงตามจำนวนผู้เล่นคือการใช้งานปกติ วิธีตรวจ ใช้เครื่องมือฝั่งอินฟรา (ไม่ต้องใช้โค้ดเกม)
รายละเอียดเพิ่มเติม ถ้ารีสตาร์ตทุกสัปดาห์ตอนปิดปรับปรุงตามรอบ อาการรั่วจะถูกกลบจนไม่มีใครเจอไปนาน และมักโผล่ขึ้นมากะทันหันเมื่อเลื่อนการปิดปรับปรุงไปหนึ่งครั้ง หรือเมื่อมีอีเวนต์ที่ทำให้ผู้เล่นเพิ่มขึ้น
แหล่งอ้างอิง 5 รายการ Troubleshoot Memory Leaks Oracle ถ้าโปรแกรมช้าลงเรื่อย ๆ ให้สงสัยหน่วยความจำรั่ว สุดท้ายหน่วยความจำจะหมดและโปรแกรมปิดตัวผิดปกติ, ข้อมูลหลักในการวิเคราะห์การรั่วคือ heap dump Debug a memory leak in .NET .NET แม้มี GC แต่ถ้ายังอ้างอิงออบเจ็กต์ที่ไม่ต้องใช้แล้วไว้ก็คือหน่วยความจำรั่ว ทำให้ประสิทธิภาพตกและเกิด OutOfMemoryException, ตรวจแนวโน้มหน่วยความจำและวิเคราะห์ dump Garbage Collector Implementation Oracle บรรทัดของ -Xlog:gc อยู่ในรูปแบบ “ปริมาณที่ใช้ก่อน GC->ปริมาณที่ใช้หลัง GC (ขนาด heap)” dotnet-counters diagnostic tool .NET ตั้งแต่ .NET 9 แสดงเป็น dotnet.gc.last_collection.heap.size ส่วน .NET 8 ลงไปแสดงเป็น GC Heap Size pidstat(1) — Linux manual page sysstat -r: RSS ของแต่ละโปรเซส (หน่วยความจำที่อยู่ใน RAM จริง) และ page fault
ID mem-gc-thrash · ผู้รับผิดชอบหลัก พัฒนาเซิร์ฟเวอร์ (ทีมพัฒนาเกม) · ร่วมกับ อินฟราเซิร์ฟเวอร์ (ทีมอินฟรา)
เมื่อข้อมูลที่ยังใช้อยู่ (live data) เข้าใกล้ขีดจำกัดของ heap แม้ GC ทำงานก็แทบไม่มีอะไรให้เก็บคืน GC จึงวนทำงานซ้ำไม่หยุด
ทำไม ผู้เล่นเพิ่มขึ้นช่วงอีเวนต์หรือหน่วยความจำรั่ว ทำให้ข้อมูลที่ยังใช้อยู่เต็มจนใกล้ขีดจำกัดของ heap → ผลคือ GC เก็บคืนได้นิดเดียวจึงต้องทำ Full GC อีกทันที และ GC ใช้ CPU ไปเกือบทั้งหมด → บนหน้าจอ ทั้งเซิร์ฟเวอร์เป็นสโลว์โมชั่นสลับกับค้างซ้ำ ๆ อยู่หลายนาที แล้วปิดตัวเพราะหน่วยความจำไม่พอ
อาการ สโลว์โมชั่น , ค้าง , หลุด
ปัจจัย การหยุดชะงัก
ใครเจอ ทั้งเซิร์ฟเวอร์
เกิดเมื่อไร ช่วงพีคหัวค่ำ, ตอนคนแห่มารวมกัน, ยิ่งเปิดไว้นานยิ่งเป็น
ผู้รับผิดชอบ ผู้รับผิดชอบหลัก พัฒนาเซิร์ฟเวอร์ (ทีมพัฒนาเกม) · ร่วมกับ อินฟราเซิร์ฟเวอร์ (ทีมอินฟรา)
งานฝั่งทีมพัฒนาเกม ตั้ง heap ให้ใหญ่กว่าข้อมูลที่ยังใช้อยู่ตอนพีคอย่างเหลือเฟือ (ปกติ 2 เท่าขึ้นไป), ลดข้อมูลที่ถูกอ้างอิงไว้นานและลดการรั่ว
งานฝั่งทีมอินฟรา ตั้ง alert ตามสัดส่วนเวลาที่ใช้ไปกับ GC, รีสตาร์ตให้เร็วแทนการฝืนรันต่อ, ใช้อินสแตนซ์ที่มีหน่วยความจำเหลือพอให้ขยาย heap ได้
ตัวเลขที่ควรรู้ ถ้า GC ใช้เวลาเกิน 10% ของเวลารันทั้งหมด มักถือเป็นสัญญาณอันตราย GC บางตัวของ Java จะแจ้งข้อผิดพลาดหน่วยความจำไม่พอ ถ้าใช้เวลา 98% ไปกับ GC แต่แทบเก็บคืนอะไรไม่ได้
บนกราฟ ชนเพดานแล้วแบนราบ · heap หลัง GC, สัดส่วนเวลาที่ใช้ไปกับ GC
จุดที่ต้องดู heap ที่เหลือหลัง GC ใกล้ heap สูงสุดแค่ไหน และสัดส่วนเวลาที่ใช้ไปกับ GC Java ดู “หลัง GC (ขนาด heap)” ในบรรทัดของ -Xlog:gc และความถี่ของบรรทัด Pause Full, .NET ดู dotnet-counters (.NET 8 ลงไปคือ % Time in GC since last GC, ตั้งแต่ .NET 9 คือค่าที่เพิ่มขึ้นของ dotnet.gc.pause.time), Go ดูช่วงห่างระหว่างบรรทัดของ GODEBUG=gctrace=1 สัญญาณว่าใช่ แม้หลัง GC heap ก็ยังเหลือใกล้ค่าสูงสุด Full GC ทำงานติดกันหลายครั้ง และสัดส่วนเวลาที่ใช้ไปกับ GC สูงกว่าปกติมาก (ปกติเกิน 10%) ระหว่างนั้นทิกของทั้งเซิร์ฟเวอร์ช้าลงไปด้วย สัญญาณว่าไม่ใช่ heap หลัง GC ยังมีที่ว่างแต่หยุดนานอย่างเดียว: น่าจะเป็นเรื่องประเภทหรือการตั้งค่า GC (mem-gc) วิธีตรวจ ใช้เครื่องมือฝั่งอินฟรา (ไม่ต้องใช้โค้ดเกม)
แหล่งอ้างอิง 5 รายการ The Parallel Collector Oracle parallel GC จะแจ้ง OutOfMemoryError ถ้าใช้เวลาเกิน 98% ของเวลาทั้งหมดไปกับ GC แล้วเก็บคืน heap ได้น้อยกว่า 2% Garbage-First Garbage Collector Tuning Oracle ค่าเริ่มต้นของ G1 (GCTimeRatio=12) จะกำหนดขนาด heap ให้เวลา GC อยู่ที่ประมาณไม่เกิน 8% ของเวลาทั้งหมด, Full GC ที่เกิดจาก heap ถูกใช้สูงเกินไปหาได้จาก Pause Full (G1 Compaction Pause) ใน log A Guide to the Go Garbage Collector Go ค่าเริ่มต้น GOGC=100 ทำให้ heap เป้าหมายประมาณ 2 เท่าของ heap ที่ยังใช้อยู่, ถ้าชนขีดจำกัดหน่วยความจำ GC จะทำงานไม่หยุดจนเกิด thrashing, ใช้ GODEBUG=gctrace=1 แสดงผลการติดตาม GC Garbage Collector Implementation Oracle บรรทัดของ -Xlog:gc แสดงประเภท GC (Pause Young, Pause Full), “ปริมาณที่ใช้ก่อน GC->ปริมาณที่ใช้หลัง GC (ขนาด heap)” และเวลาที่หยุด dotnet-counters diagnostic tool .NET ตั้งแต่ .NET 9 แสดงเป็น dotnet.gc.pause.time ส่วน .NET 8 ลงไปแสดงเป็น % Time in GC since last GC
สวอป Swapping
ID mem-swap · ผู้รับผิดชอบหลัก อินฟราเซิร์ฟเวอร์ (ทีมอินฟรา) · ร่วมกับ พัฒนาเซิร์ฟเวอร์ (ทีมพัฒนาเกม)
ถ้าหน่วยความจำไม่พอจน OS ย้ายบางส่วนไปไว้บนดิสก์ ทุกครั้งที่ใช้หน่วยความจำส่วนนั้นต้องรอดิสก์ที่ช้ากว่าเกิน 1,000 เท่า
ทำไม หน่วยความจำที่ใช้เกิน RAM จริง → ผลคือ OS ย้ายบางส่วนไปไว้บนดิสก์และอ่านกลับเมื่อต้องใช้ → บนหน้าจอ เวลาต่อทิกพุ่งเป็นหลายร้อย ms ผู้เล่นทุกคนบนเซิร์ฟเวอร์เจอสโลว์โมชั่นและค้าง
อาการ สโลว์โมชั่น , ค้าง
ปัจจัย การหยุดชะงัก
ใครเจอ ทั้งเซิร์ฟเวอร์
เกิดเมื่อไร ยิ่งเปิดไว้นานยิ่งเป็น, ช่วงพีคหัวค่ำ
ผู้รับผิดชอบ ผู้รับผิดชอบหลัก อินฟราเซิร์ฟเวอร์ (ทีมอินฟรา) · ร่วมกับ พัฒนาเซิร์ฟเวอร์ (ทีมพัฒนาเกม)
งานฝั่งทีมพัฒนาเกม กำหนดเพดานการใช้หน่วยความจำของโปรเซส (เช่น ขนาด heap) และตรวจหาการรั่ว
งานฝั่งทีมอินฟรา ตั้งไม่ให้เซิร์ฟเวอร์เกมใช้สวอป, รับมือด้วย alert หน่วยความจำ, ถ้าปิดสวอป โปรเซสจะถูกบังคับปิด (OOM) ทันทีที่หน่วยความจำไม่พอ จึงต้องมี RAM เหลือมากกว่าการใช้งานตอนพีคอย่างเหลือเฟือ
ตัวเลขที่ควรรู้ อ่าน RAM ประมาณ 100 ns, อ่านกลับจาก SSD ประมาณ 100 µs (1,000 เท่า), ดิสก์คลาวด์ที่อยู่อีกฝั่งของเครือข่ายประมาณ 1 ms (1 หมื่นเท่า), HDD 10 ms (1 แสนเท่า)
บนกราฟ ค่อย ๆ สูงขึ้น · ปริมาณการใช้สวอป, swap in/out
จุดที่ต้องดู คอลัมน์ si และ so ของ vmstat 1 (ปริมาณที่อ่านเข้าจากสวอปและเขียนออกไปสวอปต่อวินาที), some และ full ใน /proc/pressure/memory (สัดส่วนเวลาที่หยุดรอหน่วยความจำ) และ majflt/s จาก pidstat -r ของโปรเซสเซิร์ฟเวอร์เกม (page fault ที่ต้องอ่านจากดิสก์) วางซ้อนกับเวลาต่อทิก สัญญาณว่าใช่ ช่วงที่แลค si มากกว่า 0 และ majflt/s ของเซิร์ฟเวอร์เกมกับค่า full ของ memory สูงขึ้นพร้อมกัน สัญญาณว่าไม่ใช่ si และ so เป็น 0 และแรงกดดันของ memory (PSI) ก็ใกล้ 0: สวอปไม่ใช่สาเหตุ ถ้าไม่มีสวอปแต่ majflt/s และ PSI สูงขึ้น แปลว่าหน่วยความจำหมดจนต้องอ่าน code page ซ้ำ ต้องหาหน่วยความจำเพิ่มก่อน วิธีตรวจ ใช้เครื่องมือฝั่งอินฟรา (ไม่ต้องใช้โค้ดเกม)
รายละเอียดเพิ่มเติม เซิร์ฟเวอร์ที่ใช้ GC ต้องอ่าน heap ทั่วทุกส่วนตอนเก็บคืน แม้ heap ถูกสวอปออกไปแค่บางส่วน GC หนึ่งครั้งก็อาจยืดเป็นหลายวินาทีถึงหลายสิบวินาที ถ้าปิดสวอป โปรเซสจะข้ามช่วงที่ช้าลงเพราะสวอปไปถูกบังคับปิด (OOM) ทันที จึงต้องกันหน่วยความจำเหลือไว้ก่อน แม้ไม่มีสวอป ถ้าหน่วยความจำใกล้หมด OS จะเอาแม้แต่ code page ของไฟล์โปรแกรมออกจากหน่วยความจำแล้วอ่านกลับซ้ำ ๆ ทั้งเซิร์ฟเวอร์จึงอาจช้าลงอย่างหนักไปพักหนึ่งก่อนถูกบังคับปิด
แหล่งอ้างอิง 8 รายการ
แคชมิส CPU cache misses
ID mem-cache-miss · ผู้รับผิดชอบหลัก พัฒนาเซิร์ฟเวอร์ (ทีมพัฒนาเกม)
ถ้าข้อมูลกระจัดกระจายอยู่ทั่วหน่วยความจำ CPU ต้องไปรอถึง RAM ที่ช้าทุกครั้ง
ทำไม ออบเจ็กต์กระจัดกระจายเชื่อมกันด้วยพอยน์เตอร์ และถูกเข้าถึงแบบไม่เรียงลำดับ → ผลคือ ไม่มีข้อมูลในแคชของ CPU จึงต้องอ่านจาก RAM ทุกครั้ง (ช้ากว่าราว 100 เท่า) → บนหน้าจอ งานเท่าเดิมแต่ต้นทุนต่อทิกเพิ่มเป็นหลายเท่า ถ้าหนักจะเป็นสโลว์โมชั่น
อาการ สโลว์โมชั่น
ปัจจัย การหยุดชะงัก
ใครเจอ ทั้งเซิร์ฟเวอร์
เกิดเมื่อไร ตลอดเวลา, ตอนคนแห่มารวมกัน
ผู้รับผิดชอบ ผู้รับผิดชอบหลัก พัฒนาเซิร์ฟเวอร์ (ทีมพัฒนาเกม)
งานฝั่งทีมพัฒนาเกม จัดข้อมูลที่ใช้คู่กันบ่อยให้อยู่ติดกัน (data-oriented design)
บนกราฟ สูงตลอดตั้งแต่แรก · เวลาต่อทิก, อัตราการใช้ CPU
จุดที่ต้องดู ใช้ perf stat -d -p PID กับโปรเซสเซิร์ฟเวอร์เกมเพื่อวัดจำนวนคำสั่งต่อรอบสัญญาณนาฬิกา (insn per cycle) และ cache miss ของ L1 และ LLC แล้วดูคู่กับเวลาต่อทิกและอัตราการใช้ CPU สัญญาณว่าใช่ CPU ยุ่งตลอดแต่ insn per cycle ต่ำและ LLC miss สูง ถ้าบิลด์ที่เปลี่ยนการจัดวางข้อมูลทำให้เวลาต่อทิกลดลงมากที่จำนวนผู้เล่นเท่ากัน ถือว่ายืนยันได้ สัญญาณว่าไม่ใช่ อัตราการใช้ CPU ต่ำแต่ทิกช้า: น่าจะเป็นสาเหตุที่รออยู่นอก CPU เช่น ล็อกหรือรอ I/O วิธีตรวจ ใช้เครื่องมือฝั่งอินฟรา (ไม่ต้องใช้โค้ดเกม)
แหล่งอ้างอิง 2 รายการ
ID mem-fragment · ผู้รับผิดชอบหลัก พัฒนาเซิร์ฟเวอร์ (ทีมพัฒนาเกม)
ถ้าจัดสรรและคืนหน่วยความจำซ้ำไปมาจนพื้นที่ว่างแตกเป็นชิ้นเล็ก ๆ โปรเซสจะถือครองหน่วยความจำมากกว่าที่ใช้จริงมาก
ทำไม หลายเธรดจัดสรรและคืนหน่วยความจำขนาดไม่เท่ากันเป็นเวลานาน → ผลคือ พื้นที่ว่างกระจายเป็นชิ้นเล็ก ๆ คืนให้ OS ไม่ได้ ปริมาณการใช้จึงเพิ่มขึ้นเรื่อย ๆ เหมือนหน่วยความจำรั่ว → บนหน้าจอ ยิ่งเปิดไว้นานยิ่งช้าลงเพราะสวอปและหน่วยความจำไม่พอ แล้วถูกบังคับปิด
อาการ สโลว์โมชั่น , หลุด
ปัจจัย การหยุดชะงัก
ใครเจอ ทั้งเซิร์ฟเวอร์
เกิดเมื่อไร ยิ่งเปิดไว้นานยิ่งเป็น
ผู้รับผิดชอบ ผู้รับผิดชอบหลัก พัฒนาเซิร์ฟเวอร์ (ทีมพัฒนาเกม)
งานฝั่งทีมพัฒนาเกม ใช้ memory pool แยกตามขนาด, ใช้ allocator ที่ทนต่อ fragmentation (jemalloc, mimalloc ฯลฯ)
บนกราฟ ค่อย ๆ สูงขึ้น · หน่วยความจำของโปรเซส (RSS)
จุดที่ต้องดู รันเซิร์ฟเวอร์จากบิลด์เดียวกันสองตัว ตัวหนึ่งลดจำนวน arena ของ glibc ด้วยตัวแปรสภาพแวดล้อม MALLOC_ARENA_MAX หรือเปลี่ยนไปใช้ allocator อื่นอย่าง jemalloc แล้วเทียบ RSS จาก pidstat -r เป็นเวลาหลายวัน สัญญาณว่าใช่ จำนวนผู้เล่นและจำนวนเอนทิตีใกล้เคียงกัน แต่เฉพาะเซิร์ฟเวอร์ที่เปลี่ยนแล้ว RSS หยุดเพิ่มหรือลดลงมาก สัญญาณว่าไม่ใช่ เปลี่ยน allocator แล้วยังขึ้นเหมือนเดิม: หน่วยความจำที่ไม่ได้คืน (mem-leak) วิธีตรวจ ใช้เครื่องมือฝั่งอินฟรา (ไม่ต้องใช้โค้ดเกม)
รายละเอียดเพิ่มเติม รูปแบบเหมือนหน่วยความจำรั่ว การวิเคราะห์ heap จึงหาจุดที่รั่วไม่เจอ อาการนี้หนักเป็นพิเศษกับ allocator พื้นฐานของ Linux (glibc) บนเซิร์ฟเวอร์ที่มีเธรดเยอะ บางครั้งแค่เปลี่ยน allocator ปริมาณการใช้ก็ลดลงมาก
แหล่งอ้างอิง 3 รายการ mallopt(3) — Linux manual page Linux man-pages glibc malloc สร้าง arena ได้ถึงจำนวนที่เป็นพหุคูณของจำนวน CPU เพื่อลดการแย่งกันระหว่างเธรด และยิ่งมี arena มาก หน่วยความจำยิ่งถูกใช้มาก (จำกัดด้วย M_ARENA_MAX หรือตั้งผ่านตัวแปรสภาพแวดล้อม MALLOC_ARENA_MAX ก็ได้) jemalloc memory allocator jemalloc malloc อเนกประสงค์ที่เน้นหลีกเลี่ยง fragmentation และรองรับ concurrency ที่สเกลได้ดี pidstat(1) — Linux manual page sysstat -r: RSS ของแต่ละโปรเซส (หน่วยความจำที่อยู่ใน RAM จริง)
ID mem-numa · ผู้รับผิดชอบหลัก อินฟราเซิร์ฟเวอร์ (ทีมอินฟรา)
บนเซิร์ฟเวอร์ที่มี CPU สองตัว ถ้าใช้หน่วยความจำที่ต่ออยู่กับ CPU อีกฝั่ง การเข้าถึงจะช้าลง
ทำไม เธรดกับหน่วยความจำถูกวางไว้คนละซ็อกเก็ต CPU → ผลคือ การเข้าถึงหน่วยความจำช้าลง (1.5–2 เท่า แล้วแต่เครื่อง) → บนหน้าจอ สเปกเดียวกันแต่ประสิทธิภาพต่างกันในแต่ละโปรเซส
อาการ สโลว์โมชั่น
ปัจจัย การหยุดชะงัก
ใครเจอ ทั้งเซิร์ฟเวอร์
เกิดเมื่อไร ตลอดเวลา
ผู้รับผิดชอบ ผู้รับผิดชอบหลัก อินฟราเซิร์ฟเวอร์ (ทีมอินฟรา)
งานฝั่งทีมอินฟรา ผูกโปรเซสและหน่วยความจำไว้กับซ็อกเก็ตเดียว (numactl), ถ้ามีสองซ็อกเก็ตให้แยกโปรเซสเซิร์ฟเวอร์เกมไปวางซ็อกเก็ตละชุด
บนกราฟ สูงเฉพาะบางกลุ่ม · เวลาต่อทิกแยกตามโปรเซส, หน่วยความจำแยกตามโหนด
จุดที่ต้องดู ใช้ numastat -p PID ดูว่าหน่วยความจำของโปรเซสเซิร์ฟเวอร์เกมอยู่บน NUMA โหนดไหน และ numa_miss กับ other_node ของ numastat เพิ่มขึ้นหรือไม่ แล้วเทียบกับโหนดของ CPU ที่โปรเซสนั้นรันอยู่ สัญญาณว่าใช่ เฉพาะโปรเซสที่ช้า หน่วยความจำส่วนใหญ่อยู่คนละโหนดกับ CPU ที่ตัวเองรัน และเมื่อใช้ numactl ผูก CPU กับหน่วยความจำไว้โหนดเดียวแล้วรันใหม่ ความต่างก็หายไป สัญญาณว่าไม่ใช่ การวางโหนดเหมือนกับโปรเซสที่เร็วแต่ยังช้า: น่าจะเป็นสาเหตุอื่น เช่น noisy neighbor, CPU throttling หรือโหลดของโปรเซสนั้น วิธีตรวจ ใช้เครื่องมือฝั่งอินฟรา (ไม่ต้องใช้โค้ดเกม)
แหล่งอ้างอิง 3 รายการ What is NUMA? Linux kernel หน่วยความจำใน cell เดียวกันเร็วกว่าและมีแบนด์วิดท์สูงกว่า ส่วนหน่วยความจำใน cell อื่น (remote) เข้าถึงช้ากว่า numactl(8) — Linux manual page numactl ใช้ --cpunodebind และ --membind ผูก CPU และหน่วยความจำของโปรเซสไว้กับ NUMA โหนดที่กำหนด numastat(8) — Linux manual page numactl ตัวนับ numa_miss (จัดสรรบนโหนดที่ไม่ใช่โหนดที่ต้องการ) และ other_node (โปรเซสที่รันบนโหนดอื่นมาจัดสรรบนโหนดนี้), -p แสดงหน่วยความจำแยกตามโหนดของโปรเซส
L11 ดิสก์
9 สาเหตุ · บทในฉบับหลัก
ID dk-sync-log · ผู้รับผิดชอบหลัก พัฒนาเซิร์ฟเวอร์ (ทีมพัฒนาเกม) · ร่วมกับ อินฟราเซิร์ฟเวอร์ (ทีมอินฟรา)
ถ้าเธรดเกมต้องรอให้ดิสก์เขียนเสร็จทุกครั้งที่เขียน log หนึ่งบรรทัด พอดิสก์ยุ่ง เกมก็หยุดเดินไปด้วย
ทำไม เขียน log การต่อสู้และการเทรดลงไฟล์โดยตรงจากเธรดเกม → ผลคือ ถ้าสั่งให้เขียนลงดิสก์แบบแน่นอน (fsync) หรือบัฟเฟอร์การเขียนของ OS (page cache) เต็มถึงขีดจำกัด ตอนที่ดิสก์ยุ่ง การเขียนหนึ่งครั้งจะใช้เวลาหลายสิบ ms → บนหน้าจอ หยุดแวบในการต่อสู้ที่มี log เยอะ
อาการ กระตุก , ค้าง
ปัจจัย การหยุดชะงัก
ใครเจอ บางจุด/บางแชนแนล, ทั้งเซิร์ฟเวอร์
เกิดเมื่อไร ตอนคนแห่มารวมกัน
ผู้รับผิดชอบ ผู้รับผิดชอบหลัก พัฒนาเซิร์ฟเวอร์ (ทีมพัฒนาเกม) · ร่วมกับ อินฟราเซิร์ฟเวอร์ (ทีมอินฟรา)
งานฝั่งทีมพัฒนาเกม ใช้ async logging (บัฟเฟอร์ในหน่วยความจำ + เธรดแยก), ลดปริมาณ log, ไม่เรียก fsync ในเธรดเกม
งานฝั่งทีมอินฟรา รัน log rotation และการบีบอัด log ด้วยลำดับความสำคัญ I/O ต่ำ, แยก log ไว้คนละดิสก์กับข้อมูล, มอนิเตอร์ดีเลย์การเขียนดิสก์
บนกราฟ พุ่งแบบสุ่มเป็นครั้งคราว · เวลาต่อทิกของเซิร์ฟเวอร์, ดีเลย์การเขียนดิสก์
จุดที่ต้องดู w_await และ aqu-sz จาก iostat -x 1 วางซ้อนกับเวลาต่อทิก และใช้ perf trace -p PID --duration 10 หาการเรียก write และ fsync ในเซิร์ฟเวอร์เกมที่ใช้เวลาเกิน 10 ms พร้อมเธรดที่เรียก สัญญาณว่าใช่ ช่วงที่ทิกพุ่ง การเรียก write และ fsync ของเธรดเกมใช้เวลาหลายสิบ ms และดีเลย์การเขียนดิสก์ก็พุ่งในจังหวะเดียวกัน มักตรงกับเวลาทำ log rotation หรือบีบอัด log สัญญาณว่าไม่ใช่ เธรดเกมไม่มี system call ที่ใช้เวลานานแต่ทิกยังพุ่ง: น่าจะเป็นสาเหตุอื่น เช่น GC, ล็อก หรือทิกเกินงบ ถ้านานเฉพาะเธรดที่เขียน log อย่างเดียว จะไม่กระทบการเดินของเกม วิธีตรวจ ใช้เครื่องมือฝั่งอินฟรา (ไม่ต้องใช้โค้ดเกม)
รายละเอียดเพิ่มเติม ปกติ OS จะรับการเขียนไว้ในหน่วยความจำ (page cache) ก่อนแล้วค่อยเขียนลงดิสก์ทีหลัง log หนึ่งบรรทัดจึงมักเสร็จทันที การหยุดเกิดขึ้นเมื่อสั่งให้เขียนแบบแน่นอนด้วย fsync, เมื่อการเขียนที่กองรอเกินขีดจำกัดจน OS บล็อกการเรียกเขียน และเมื่อทำ rotation หรือบีบอัดไฟล์ log ด้วยเหตุนี้ ปกติจึงไม่มีปัญหา แต่จะพุ่งเฉพาะตอนที่ดิสก์ยุ่ง
แหล่งอ้างอิง 5 รายการ
ID dk-fsync · ผู้รับผิดชอบหลัก พัฒนาเซิร์ฟเวอร์ (ทีมพัฒนาเกม) · ร่วมกับ อินฟราเซิร์ฟเวอร์ (ทีมอินฟรา), อินฟรา DB (ทีมอินฟรา)
ถ้าสั่งให้เขียนข้อมูลลงดิสก์ “แบบแน่นอน” แต่ละครั้งจะใช้เวลา 0.1 ms ถึงหลายสิบ ms แล้วแต่ดิสก์ และถ้ามาพร้อมกันมาก คิวจะยาวขึ้น
ทำไม คำขอเขียนแบบแน่นอนมากระจุกกันจากการเซฟตามรอบและผู้เล่นแห่ล็อกเอาต์ → ผลคือ คิวดิสก์ยาวขึ้น → บนหน้าจอ แลคทุกครั้งที่ถึงเวลาเซฟ, ล็อกเอาต์และย้ายแชนแนลช้า
อาการ กระตุก , อินพุตดีเลย์
ปัจจัย การหยุดชะงัก, ความหน่วง
ใครเจอ ทั้งเซิร์ฟเวอร์
เกิดเมื่อไร เป็นรอบสม่ำเสมอ, ตอนคนแห่มารวมกัน
ผู้รับผิดชอบ ผู้รับผิดชอบหลัก พัฒนาเซิร์ฟเวอร์ (ทีมพัฒนาเกม) · ร่วมกับ อินฟราเซิร์ฟเวอร์ (ทีมอินฟรา), อินฟรา DB (ทีมอินฟรา)
งานฝั่งทีมพัฒนาเกม รวมการเซฟให้ทำทีเดียว (หลายการเซฟต่อ fsync หนึ่งครั้ง), กระจายเวลาเซฟ
งานฝั่งทีมอินฟรา เครื่องเซิร์ฟเวอร์/OS: ใช้ SSD สำหรับเซิร์ฟเวอร์ที่มีระบบป้องกันไฟดับ, มอนิเตอร์ความยาวคิวดิสก์และดีเลย์ของ fsync เครื่อง DB: ถ้าการเซฟไปลง DB ให้ดิสก์ log ของ DB ใช้ SSD แบบเดียวกันด้วย, มอนิเตอร์ดีเลย์ของ commit
ตัวเลขที่ควรรู้ เวลาต่อครั้งต่างกันไปตามเครื่อง แต่โดยประมาณคือ SSD สำหรับเซิร์ฟเวอร์ (มีระบบป้องกันไฟดับ) 0.1 ms, SSD ทั่วไป 1 ms ถึงหลาย ms, ดิสก์คลาวด์ 1–2 ms และ HDD 10 ms ขึ้นไป ถ้าเธรดเดียวรอทีละครั้ง HDD จะทำได้ไม่ถึง 100 ครั้งใน 1 วินาที
บนกราฟ พุ่งเป็นรอบ · ความยาวคิวดิสก์, ดีเลย์ของ flush และการเขียน
จุดที่ต้องดู f/s และ f_await (จำนวน flush ที่ดิสก์ประมวลผลและเวลาที่ใช้), w/s, aqu-sz และ w_await จาก iostat -x 1 วางซ้อนกับเวลาเซฟตามรอบและเวลาล็อกเอาต์ sysstat รุ่นเก่าแสดง aqu-sz เป็น avgqu-sz ดิสก์คลาวด์ให้ดู VolumeQueueLength และ VolumeAvgWriteLatency ของ EBS สัญญาณว่าใช่ ทุกครั้งที่ถึงเวลาเซฟหรือมีคนแห่ล็อกเอาต์ จำนวน flush และความยาวคิวพุ่งพร้อมกัน และ w_await กับ f_await สูงเป็นหลายเท่าของปกติ ระหว่างนั้นการเซฟและการย้ายแชนแนลช้าลง สัญญาณว่าไม่ใช่ คิวพุ่งในช่วงที่ไม่เกี่ยวกับการเซฟหรือล็อกเอาต์: น่าจะเป็นการสำรองข้อมูลหรือการบีบอัด (dk-backup) หรือขีดจำกัด IOPS (dk-iops) ถ้าจำนวน flush เท่าเดิมแต่ช้าลง ให้ดู burst credit หมด (dk-burst) วิธีตรวจ ใช้เครื่องมือฝั่งอินฟรา (ไม่ต้องใช้โค้ดเกม)
แหล่งอ้างอิง 6 รายการ
ID dk-burst · ผู้รับผิดชอบหลัก อินฟราเซิร์ฟเวอร์ (ทีมอินฟรา) · ร่วมกับ อินฟรา DB (ทีมอินฟรา)
ดิสก์คลาวด์บางประเภทและเซิร์ฟเวอร์สเปกเล็กมี burst credit ที่ให้ทำงานเร็วกว่าประสิทธิภาพพื้นฐานได้ชั่วคราว ถ้าช่วงที่ยุ่งยาวนานจนเครดิตหมด ความเร็วจะตกลงกะทันหัน
ทำไม ใช้งานเกินประสิทธิภาพพื้นฐานเป็นเวลานาน → ผลคือ burst credit หมด ประสิทธิภาพจึงดิ่งลงไปเหลือระดับพื้นฐาน → บนหน้าจอ ทุกเย็นพอผ่านไปไม่กี่ชั่วโมงก็เริ่มแลค
อาการ กระตุก , สโลว์โมชั่น , อินพุตดีเลย์
ปัจจัย การหยุดชะงัก, ความหน่วง
ใครเจอ ทั้งเซิร์ฟเวอร์
เกิดเมื่อไร ช่วงพีคหัวค่ำ, ยิ่งเปิดไว้นานยิ่งเป็น
ผู้รับผิดชอบ ผู้รับผิดชอบหลัก อินฟราเซิร์ฟเวอร์ (ทีมอินฟรา) · ร่วมกับ อินฟรา DB (ทีมอินฟรา)
งานฝั่งทีมอินฟรา เครื่องเซิร์ฟเวอร์/OS: ใช้ดิสก์แบบรับประกันประสิทธิภาพ (gp3 หรือแบบกำหนด IOPS), ตั้ง alert เครดิตคงเหลือ, ตรวจขีดจำกัด burst ของแบนด์วิดท์ดิสก์ของอินสแตนซ์และ CPU credit ไปด้วย เครื่อง DB: เปลี่ยนดิสก์ DB รวมถึง managed DB เป็นแบบรับประกันประสิทธิภาพด้วย, ตั้ง alert เครดิตคงเหลือ
ตัวเลขที่ควรรู้ ดิสก์ AWS gp2 ขนาด 100 GB ปกติได้ 300 IOPS และ burst ได้ 3,000 IOPS ถ้าเครดิตเต็มจะอยู่ได้ประมาณ 30 นาที ส่วน gp3 ไม่มีเครดิตและได้ 3,000 เสมอ Premium SSD ขนาดเล็กของ Azure ก็ burst ด้วยเครดิตได้สูงสุด 30 นาทีเช่นกัน
บนกราฟ ชนเพดานแล้วแบนราบ · IOPS, burst credit คงเหลือ
จุดที่ต้องดู BurstBalance ของ EBS ใน CloudWatch (gp2, st1, sc1), EBSIOBalance% และ EBSByteBalance% ของอินสแตนซ์ (บางอินสแตนซ์ที่ burst ได้), CPUCreditBalance ของอินสแตนซ์แบบ burstable ส่วน Azure ดูเมตริกอัตราการใช้ burst credit เช่น Data Disk Used Burst IO Credits Percentage สัญญาณว่าใช่ ตั้งแต่ช่วงที่เครดิตคงเหลือลดลงใกล้ 0 IOPS (VolumeReadOps, VolumeWriteOps) แบนราบที่ระดับประสิทธิภาพพื้นฐาน และ VolumeQueueLength กับแลคเพิ่มขึ้นพร้อมกัน เริ่มหลังจากพีคต่อเนื่องมาแล้วหลายชั่วโมง สัญญาณว่าไม่ใช่ เครดิตคงเหลือทุกตัวยังมีพอแต่ IOPS แบนราบ: ขีดจำกัดคงที่ของ volume หรืออินสแตนซ์ (dk-iops) วิธีตรวจ ใช้เครื่องมือฝั่งอินฟรา (ไม่ต้องใช้โค้ดเกม)
รายละเอียดเพิ่มเติม แม้ดิสก์จะปกติ VM ขนาดเล็กก็มีขีดจำกัด burst ที่แบนด์วิดท์ดิสก์ของอินสแตนซ์เอง (เช่น อย่างน้อย 30 นาทีต่อวัน) จึงเกิดรูปแบบเดียวกันได้ เซิร์ฟเวอร์ราคาถูกที่ใช้ CPU credit ก็ช้าลงจนเหลือประสิทธิภาพพื้นฐานเมื่อเครดิตหมด
แหล่งอ้างอิง 7 รายการ Amazon EBS General Purpose SSD volumes AWS ประสิทธิภาพพื้นฐานของ gp2 คือ 3 IOPS ต่อ GiB (ขั้นต่ำ 100), burst ได้ถึง 3,000 IOPS ด้วย I/O credit, เครดิต 5,400,000 หน่วยอยู่ได้อย่างน้อย 30 นาที gp3 ไม่มี burst และได้ 3,000 IOPS เสมอ Managed disk bursting Microsoft Azure Premium SSD ตั้งแต่ P20 ลงไป burst ด้วยระบบเครดิต, ถ้าเครดิตเต็มจะ burst ที่ความเร็วสูงสุดได้ 30 นาที Amazon EBS-optimized instance types AWS บางอินสแตนซ์คงประสิทธิภาพ EBS สูงสุดได้เพียง 30 นาทีครั้งเดียวใน 24 ชั่วโมง จากนั้นกลับไปที่ประสิทธิภาพพื้นฐาน Standard mode for burstable performance instances AWS อินสแตนซ์แบบ burstable ในโหมด standard จะลดอัตราการใช้ CPU ลงสู่ระดับพื้นฐานเมื่อ CPU credit หมด (ค่อย ๆ ลดเพื่อไม่ให้ดิ่งลงทันที) Amazon CloudWatch metrics for Amazon EBS AWS BurstBalance: I/O credit คงเหลือของ gp2 และ throughput credit คงเหลือของ st1 และ sc1 (%), VolumeReadOps, VolumeWriteOps, VolumeQueueLength CloudWatch metrics that are available for your instances AWS EBSIOBalance% และ EBSByteBalance%: EBS credit คงเหลือของบางอินสแตนซ์ที่ burst ได้ 30 นาทีครั้งเดียวใน 24 ชั่วโมง, CPUCreditBalance: CPU credit คงเหลือของอินสแตนซ์แบบ burstable Disk metrics Microsoft Azure อัตราการใช้ burst credit ของดิสก์และ VM เช่น Data Disk Used Burst IO Credits Percentage (ทุก 5 นาที)
ID dk-iops · ผู้รับผิดชอบหลัก อินฟราเซิร์ฟเวอร์ (ทีมอินฟรา) · ร่วมกับ พัฒนาเซิร์ฟเวอร์ (ทีมพัฒนาเกม), อินฟรา DB (ทีมอินฟรา)
ถ้าคำขอเกินจำนวนที่ดิสก์ประมวลผลได้ใน 1 วินาที คิวจะยาวขึ้นและดีเลย์พุ่งสูง
ทำไม คำขออ่านและเขียนเข้าใกล้ขีดความสามารถของดิสก์ → ผลคือ คิวยาวขึ้น (มักพุ่งเมื่ออัตราการใช้งานเกิน 90%) → บนหน้าจอ เซฟและโหลดช้า ถ้าเป็น synchronous call เกมจะค้าง
อาการ อินพุตดีเลย์ , ค้าง
ปัจจัย ความหน่วง, การหยุดชะงัก
ใครเจอ ทั้งเซิร์ฟเวอร์
เกิดเมื่อไร ตอนคนแห่มารวมกัน, ช่วงพีคหัวค่ำ
ผู้รับผิดชอบ ผู้รับผิดชอบหลัก อินฟราเซิร์ฟเวอร์ (ทีมอินฟรา) · ร่วมกับ พัฒนาเซิร์ฟเวอร์ (ทีมพัฒนาเกม), อินฟรา DB (ทีมอินฟรา)
งานฝั่งทีมพัฒนาเกม รวมคำขอเข้าด้วยกัน, แคชข้อมูลที่อ่านบ่อย, ทำเป็น async เพื่อไม่ให้เธรดเกมรอดิสก์
งานฝั่งทีมอินฟรา เครื่องเซิร์ฟเวอร์/OS: ใช้ดิสก์ที่เร็วขึ้น, ตรวจขีดจำกัดแบนด์วิดท์ดิสก์และ IOPS ของแต่ละประเภทอินสแตนซ์, ตั้ง alert อัตราการใช้งานดิสก์และคิว, คัดลอกไฟล์ใหญ่ในช่วงที่ว่าง เครื่อง DB: ตั้ง alert อัตราการใช้ IOPS และ throughput ของดิสก์ DB ด้วย, ตรวจขีดจำกัดดิสก์ตามสเปกของอินสแตนซ์ DB
ตัวเลขที่ควรรู้ HDD ประมาณ 150, SATA SSD หลายหมื่น และ NVMe หลายแสน IOPS ดิสก์คลาวด์พื้นฐาน (AWS gp3) ได้ 3,000 IOPS และ 125 MiB ต่อวินาที ขีดจำกัดปริมาณรับส่งต่อวินาทีแยกจาก IOPS ถ้าการคัดลอกไฟล์ใหญ่ใช้จนเต็ม แม้การเขียนเล็ก ๆ ก็ต้องรอคิวไปด้วย
บนกราฟ ชนเพดานแล้วแบนราบ · IOPS, ความยาวคิวดิสก์
จุดที่ต้องดู r/s, w/s, rkB/s, wkB/s, aqu-sz, r_await และ w_await จาก iostat -x 1 บนคลาวด์ดู VolumeReadOps, VolumeWriteOps และ VolumeQueueLength ของ EBS กับตัวบอกว่าเกินขีดจำกัดหรือไม่ คือ VolumeIOPSExceededCheck และ VolumeThroughputExceededCheck ส่วนฝั่งอินสแตนซ์ดู InstanceEBSIOPSExceededCheck และ InstanceEBSThroughputExceededCheck สัญญาณว่าใช่ จำนวนคำขอต่อวินาทีหรือปริมาณรับส่งแบนราบที่ค่าขีดจำกัด และ aqu-sz กับ await พุ่งขึ้นพร้อมกัน บนคลาวด์เมตริกตรวจการเกินขีดจำกัดเป็น 1 สัญญาณว่าไม่ใช่ แม้ %util เป็น 100% ถ้า await ต่ำก็อาจยังมีกำลังเหลือ บน SSD และ RAID ที่ประมวลผลคำขอแบบขนาน %util ไม่ได้บอกขีดจำกัด ถ้ายังไม่ถึงขีดจำกัดแต่ await สูงอย่างเดียว น่าจะเป็นดีเลย์ของตัวดิสก์เอง (dk-hdd) หรือ fsync (dk-fsync) วิธีตรวจ ใช้เครื่องมือฝั่งอินฟรา (ไม่ต้องใช้โค้ดเกม)
รายละเอียดเพิ่มเติม บนคลาวด์ นอกจากขีดจำกัดของดิสก์แล้ว สเปกเซิร์ฟเวอร์แต่ละแบบ (ประเภทอินสแตนซ์) ยังมีขีดจำกัดแบนด์วิดท์ดิสก์และ IOPS ของตัวเอง ต่อให้ใช้ดิสก์ราคาแพง ถ้าเซิร์ฟเวอร์เล็กก็จะติดที่ขีดจำกัดของอินสแตนซ์
แหล่งอ้างอิง 8 รายการ Exos X18 Data Sheet Seagate HDD สำหรับเซิร์ฟเวอร์ 7,200 rpm อ่านแบบสุ่ม 4K ได้ 170 IOPS (QD16) D3-S4520 SSD Solidigm SATA SSD สำหรับเซิร์ฟเวอร์ อ่าน/เขียนแบบสุ่ม 4 KB สูงสุด 92K/48K IOPS Solidigm™ D7-P5520 and D7-P5620 Product Brief Solidigm NVMe SSD สำหรับเซิร์ฟเวอร์ อ่าน/เขียนแบบสุ่ม 1,000K/200K IOPS Amazon EBS General Purpose SSD volumes AWS ประสิทธิภาพพื้นฐานของ gp3 คือ 3,000 IOPS และ 125 MiB/s เป็นขีดจำกัดสองตัวที่แยกกันและเพิ่มแยกกันได้ Amazon EBS-optimized instance types AWS แต่ละประเภทอินสแตนซ์มีขีดจำกัดพื้นฐานและสูงสุดของแบนด์วิดท์ EBS, throughput และ IOPS แยกกัน iostat(1) — Linux manual page sysstat -x: r/s, w/s, rkB/s, wkB/s, aqu-sz (ชื่อเดิมคือ avgqu-sz), r_await, w_await, %util บน RAID และ SSD รุ่นใหม่ที่ประมวลผลคำขอแบบขนาน %util ไม่ได้บอกขีดจำกัดของประสิทธิภาพ Amazon CloudWatch metrics for Amazon EBS AWS VolumeIOPSExceededCheck และ VolumeThroughputExceededCheck: เป็น 1 ถ้ามีการพยายามใช้เกินขีดจำกัด IOPS หรือ throughput ของ volume (อินสแตนซ์ Nitro), VolumeQueueLength CloudWatch metrics that are available for your instances AWS InstanceEBSIOPSExceededCheck และ InstanceEBSThroughputExceededCheck: เป็น 1 ถ้ามีการพยายามใช้เกินขีดจำกัด EBS IOPS หรือ throughput ของอินสแตนซ์
ID dk-full · ผู้รับผิดชอบหลัก อินฟราเซิร์ฟเวอร์ (ทีมอินฟรา) · ร่วมกับ อินฟรา DB (ทีมอินฟรา), พัฒนาเซิร์ฟเวอร์ (ทีมพัฒนาเกม)
ถ้า log และ dump สะสมจนดิสก์เต็ม การเขียนจะล้มเหลว และถ้าไม่ได้เตรียมรับมือไว้ เซิร์ฟเวอร์จะล่ม
ทำไม log, dump และไฟล์ชั่วคราวสะสมจนถึง 100% → ผลคือ เขียนไม่สำเร็จ ถ้าไม่มีการจัดการข้อผิดพลาดจะแครช ถ้ามีก็เซฟไม่สำเร็จ → บนหน้าจอ หลุด, ความคืบหน้าถูกโรลแบ็ค
อาการ หลุด , กดไม่ติด/โรลแบ็ค
ปัจจัย การหยุดชะงัก
ใครเจอ ทั้งเซิร์ฟเวอร์
เกิดเมื่อไร ยิ่งเปิดไว้นานยิ่งเป็น
ผู้รับผิดชอบ ผู้รับผิดชอบหลัก อินฟราเซิร์ฟเวอร์ (ทีมอินฟรา) · ร่วมกับ อินฟรา DB (ทีมอินฟรา), พัฒนาเซิร์ฟเวอร์ (ทีมพัฒนาเกม)
งานฝั่งทีมพัฒนาเกม จัดการกรณีเขียนไม่สำเร็จให้ลองเซฟใหม่และแจ้ง alert แทนการแครช, ลด log และ dump ที่ไม่จำเป็น
งานฝั่งทีมอินฟรา เครื่องเซิร์ฟเวอร์/OS: ทำ log rotation, ตั้ง alert พื้นที่ดิสก์, แยกดิสก์ log กับดิสก์ข้อมูล เครื่อง DB: เฝ้าดูไม่ให้ transaction log ของ DB (WAL, binlog) สะสมเพราะ replication หยุดหรือขาดการสำรอง log
บนกราฟ ค่อย ๆ สูงขึ้น · อัตราการใช้พื้นที่ดิสก์
จุดที่ต้องดู อัตราการใช้พื้นที่จาก df -h และอัตราการใช้ inode จาก df -i และหาข้อผิดพลาด ENOSPC ใน log ของเซิร์ฟเวอร์และ DB ฝั่ง DB ดู slot ที่ active เป็น false ใน pg_replication_slots ของ PostgreSQL, จำนวนและขนาดไฟล์จาก SHOW BINARY LOGS ของ MySQL, log_reuse_wait_desc ใน sys.databases ของ SQL Server และ FreeStorageSpace ของ RDS สัญญาณว่าใช่ อัตราการใช้พื้นที่ค่อย ๆ สูงขึ้นตลอดหลายวัน ช่วงที่แตะ 100% ตรงกับช่วงที่แครชหรือเซฟไม่สำเร็จ และมี ENOSPC ใน log สัญญาณว่าไม่ใช่ พื้นที่ยังเหลือพอแต่เขียนไม่สำเร็จ: น่าจะเป็นสาเหตุอื่น เช่น สิทธิ์ (permission) หรือขีดจำกัดขนาดไฟล์ วิธีตรวจ ใช้เครื่องมือฝั่งอินฟรา (ไม่ต้องใช้โค้ดเกม)
รายละเอียดเพิ่มเติม transaction log ของ DB (WAL, binlog ฯลฯ) จะไม่ถูกลบและสะสมไปเรื่อย ๆ ถ้า replica หยุดหรือการสำรอง log ขาดไป ถ้าดิสก์นี้เต็ม การเขียนทั้งหมดของ DB จะหยุด การเซฟและการเทรดจึงล้มเหลวพร้อมกันทั้งหมด
แหล่งอ้างอิง 8 รายการ
ID dk-backup · ผู้รับผิดชอบหลัก อินฟราเซิร์ฟเวอร์ (ทีมอินฟรา) · ร่วมกับ อินฟรา DB (ทีมอินฟรา)
ถ้าการสำรองข้อมูลตอนเช้ามืด, การบีบอัด log หรือการสแกนความปลอดภัยยึดดิสก์ไว้ การอ่านและเขียนของเซิร์ฟเวอร์เกมจะล่าช้า
ทำไม งานสำรองข้อมูลหรือบีบอัดที่ตั้งเวลาไว้เริ่มทำงาน → ผลคือ ใช้แบนด์วิดท์และ IOPS ของดิสก์ไปเกือบหมด → บนหน้าจอ แลคเวลาเดิมทุกวัน
อาการ กระตุก , อินพุตดีเลย์
ปัจจัย การหยุดชะงัก, ความหน่วง
ใครเจอ ทั้งเซิร์ฟเวอร์
เกิดเมื่อไร เป็นรอบสม่ำเสมอ
ผู้รับผิดชอบ ผู้รับผิดชอบหลัก อินฟราเซิร์ฟเวอร์ (ทีมอินฟรา) · ร่วมกับ อินฟรา DB (ทีมอินฟรา)
งานฝั่งทีมอินฟรา เครื่องเซิร์ฟเวอร์/OS: ลดลำดับความสำคัญ I/O ของงานสำรองข้อมูล บีบอัด และสแกน, กระจายเวลา เครื่อง DB: สำรองข้อมูลจาก replica
บนกราฟ พุ่งเป็นรอบ · อัตราการใช้งานดิสก์, เวลารอของดิสก์
จุดที่ต้องดู ใช้ sar -d ดูค่า %util, await และ aqu-sz จากข้อมูลย้อนหลังหลายวัน (ไฟล์รายวันใน /var/log/sa โดย sadc ต้องเก็บข้อมูลดิสก์ด้วย -S DISK) วางซ้อนแยกตามวัน และในช่วงเวลานั้นใช้ pidstat -d 1 หาโปรเซสที่มี kB_rd/s และ kB_wr/s สูงสุด แล้วเทียบกับตารางเวลาของ cron และ systemd timer สัญญาณว่าใช่ await และ %util พุ่งเวลาเดิมทุกวัน และช่วงนั้นโปรเซสสำรองข้อมูล บีบอัด หรือสแกน กินการอ่านเขียนดิสก์ไปเกือบทั้งหมด สัญญาณว่าไม่ใช่ เวลาที่พุ่งไม่ตรงกันในแต่ละวัน: ไม่น่าใช่งานที่ตั้งเวลาไว้ ถ้า I/O ส่วนใหญ่ในช่วงนั้นมาจากเซิร์ฟเวอร์เกมเอง ให้ดูฝั่งการเซฟและ log (dk-fsync, dk-sync-log) วิธีตรวจ ใช้เครื่องมือฝั่งอินฟรา (ไม่ต้องใช้โค้ดเกม)
แหล่งอ้างอิง 4 รายการ
ID dk-lazy-load · ผู้รับผิดชอบหลัก พัฒนาเซิร์ฟเวอร์ (ทีมพัฒนาเกม) · ร่วมกับ อินฟราเซิร์ฟเวอร์ (ทีมอินฟรา)
ถ้าเซิร์ฟเวอร์อ่านข้อมูลดันเจี้ยนหรือแมพจากดิสก์ตอนที่ถูกขอเป็นครั้งแรก ทุกคนจะหยุดไปตลอดทิกนั้น
ทำไม มีคนเข้าดันเจี้ยนหรือพื้นที่นั้นเป็นคนแรก → ผลคือ เซิร์ฟเวอร์อ่านข้อมูลจากดิสก์ในเธรดเกม → บนหน้าจอ ทุกคนบนเซิร์ฟเวอร์นั้นค้างไปครู่หนึ่ง
อาการ ค้าง
ปัจจัย การหยุดชะงัก
ใครเจอ บางจุด/บางแชนแนล, ทั้งเซิร์ฟเวอร์
เกิดเมื่อไร ระหว่างเดินทาง/ย้ายแมพ
ผู้รับผิดชอบ ผู้รับผิดชอบหลัก พัฒนาเซิร์ฟเวอร์ (ทีมพัฒนาเกม) · ร่วมกับ อินฟราเซิร์ฟเวอร์ (ทีมอินฟรา)
งานฝั่งทีมพัฒนาเกม โหลดล่วงหน้าตอนเซิร์ฟเวอร์เริ่ม, โหลดแบบ async
งานฝั่งทีมอินฟรา เซิร์ฟเวอร์ที่เพิ่งสร้างจากสแนปช็อตให้วอร์มดิสก์ก่อนเปิดให้บริการ (อ่านทุกบล็อกหนึ่งรอบ) หรือใช้ฟีเจอร์ fast snapshot restore
บนกราฟ พุ่งแบบสุ่มเป็นครั้งคราว · เวลาต่อทิกของเซิร์ฟเวอร์, การอ่านดิสก์
จุดที่ต้องดู เทียบช่วงที่หยุดกับรายการเข้าดันเจี้ยนหรือพื้นที่ครั้งแรกใน log ของเซิร์ฟเวอร์เกม และดูการอ่านดิสก์ของเซิร์ฟเวอร์เกมในจังหวะนั้น (kB_rd/s ของ pidstat -d) กับการเรียก read และ open ที่ใช้เวลานานจาก perf trace --duration ถ้าเป็นเซิร์ฟเวอร์คลาวด์ที่เพิ่งเปิด ให้เทียบ VolumeAvgReadLatency ของ EBS กับเซิร์ฟเวอร์ที่เปิดมานาน สัญญาณว่าใช่ หยุดเฉพาะตอนเข้าครั้งแรก เข้าที่เดิมครั้งที่สองไม่หยุด ระหว่างที่หยุด เธรดเกมรอการอ่านไฟล์อยู่ สัญญาณว่าไม่ใช่ พื้นที่ที่โหลดไว้แล้วก็หยุดเหมือนกัน: น่าจะเป็นสาเหตุอื่น เช่น ทิกเกินงบหรือ GC วิธีตรวจ ต้องมี log หรือเมตริกจากเซิร์ฟเวอร์/ไคลเอนต์เกม
รายละเอียดเพิ่มเติม บนคลาวด์ เซิร์ฟเวอร์ที่เพิ่งสร้างจากสแนปช็อต (สำเนาดิสก์) ต้องดึงทุกบล็อกที่อ่านครั้งแรกมาจากสตอเรจระยะไกล จึงช้ากว่าปกติมาก ถ้าการเข้าครั้งแรกนานผิดปกติเฉพาะบนเซิร์ฟเวอร์ที่เพิ่งเปิดขึ้นจาก autoscaling ให้สงสัยสาเหตุนี้
แหล่งอ้างอิง 5 รายการ
ID dk-coredump · ผู้รับผิดชอบหลัก อินฟราเซิร์ฟเวอร์ (ทีมอินฟรา) · ร่วมกับ พัฒนาเซิร์ฟเวอร์ (ทีมพัฒนาเกม)
ตอนเซิร์ฟเวอร์ล่ม ต้องเขียนหน่วยความจำหลาย GB ลงดิสก์ บางครั้งการรีสตาร์ตจึงล่าช้าไปหลายนาที
ทำไม เซิร์ฟเวอร์แครช จึงเขียนหน่วยความจำทั้งหมดลงไฟล์ → ผลคือ รีสตาร์ตไม่ได้ระหว่างเขียนหลาย GB → บนหน้าจอ เซิร์ฟเวอร์ล่มจนผู้เล่นหลุด แล้วเข้าเกมไม่ได้อยู่นาน
อาการ เข้าเกมไม่ได้/โหลดไม่จบ
ปัจจัย การหยุดชะงัก
ใครเจอ ทั้งเซิร์ฟเวอร์
เกิดเมื่อไร สุ่มเป็นครั้งคราว
ผู้รับผิดชอบ ผู้รับผิดชอบหลัก อินฟราเซิร์ฟเวอร์ (ทีมอินฟรา) · ร่วมกับ พัฒนาเซิร์ฟเวอร์ (ทีมพัฒนาเกม)
งานฝั่งทีมพัฒนาเกม พิจารณาใช้ dump ขนาดเล็กที่เก็บเฉพาะหน่วยความจำที่จำเป็น (minidump), แก้ต้นเหตุของการแครช
งานฝั่งทีมอินฟรา จำกัดขนาด dump (ตั้งค่า core dump ของ OS), ใช้ดิสก์ที่เร็ว, แยกการรีสตาร์ตออกจากการทำ dump (บีบอัดและอัปโหลด dump แยกทำหลังรีสตาร์ต)
บนกราฟ การเชื่อมต่อหลุดพร้อมกัน · จำนวนการเชื่อมต่อ, เวลารีสตาร์ตเซิร์ฟเวอร์
จุดที่ต้องดู วางเวลาที่แครช ขนาดไฟล์ core (coredumpctl list และ info หรือไฟล์ในตำแหน่งที่ core_pattern ชี้ไว้) เวลาที่เขียนไฟล์เสร็จ และเวลาที่เซอร์วิสกลับมาทำงานเรียงคู่กัน แล้วดู wkB/s ของ iostat -x ในช่วงนั้น สัญญาณว่าใช่ หลังแครช ระหว่างเขียนไฟล์ core ขนาดหลาย GB การเขียนดิสก์อยู่ใกล้ขีดจำกัดตลอด และรีสตาร์ตเริ่มหลังเขียนเสร็จแล้วเท่านั้น สัญญาณว่าไม่ใช่ core dump ปิดอยู่หรือจบเร็วเพราะไฟล์เล็ก แต่รีสตาร์ตยังช้า: น่าจะเป็นขั้นตอนเริ่มเซิร์ฟเวอร์ เช่น การโหลดแมพ หรือ cold cache ของ DB (db-cold-cache) วิธีตรวจ ใช้เครื่องมือฝั่งอินฟรา (ไม่ต้องใช้โค้ดเกม)
แหล่งอ้างอิง 4 รายการ core(5) — Linux manual page Linux man-pages RLIMIT_CORE กำหนดเพดานขนาดไฟล์ core, coredump_filter เลือกส่วนของหน่วยความจำที่จะเก็บ, ส่ง core dump ผ่าน pipe ไปให้โปรแกรมจัดการแยก Minidump Files Microsoft minidump เก็บเฉพาะข้อมูลส่วนที่มีประโยชน์ของ crash dump จึงสร้างได้เร็วและเล็ก coredumpctl(1) — Linux manual page systemd list: รายการ core dump ที่เหลืออยู่ใน journal (TIME คือเวลาแครชที่เคอร์เนลรายงาน), info: รายละเอียดของแต่ละ dump และขนาดที่เขียนลงดิสก์ iostat(1) — Linux manual page sysstat -x: wkB/s (ปริมาณเขียนดิสก์ต่อวินาที)
ID dk-hdd · ผู้รับผิดชอบหลัก อินฟราเซิร์ฟเวอร์ (ทีมอินฟรา) · ร่วมกับ อินฟรา DB (ทีมอินฟรา), พัฒนาเซิร์ฟเวอร์ (ทีมพัฒนาเกม)
HDD ต้องเลื่อนหัวอ่านไปบนจานแม่เหล็ก (seek) การอ่านเขียนข้อมูลที่กระจัดกระจายจึงใช้เวลาเกือบ 10 ms ต่อครั้ง
ทำไม ใช้ HDD บนเซิร์ฟเวอร์เก่าหรือสตอเรจราคาถูก → ผลคือ อ่านเขียนแบบกระจัดกระจายครั้งละประมาณ 10 ms → บนหน้าจอ เซฟและโหลดช้าโดยรวม
อาการ อินพุตดีเลย์
ปัจจัย ความหน่วง
ใครเจอ ทั้งเซิร์ฟเวอร์
เกิดเมื่อไร ตลอดเวลา
ผู้รับผิดชอบ ผู้รับผิดชอบหลัก อินฟราเซิร์ฟเวอร์ (ทีมอินฟรา) · ร่วมกับ อินฟรา DB (ทีมอินฟรา), พัฒนาเซิร์ฟเวอร์ (ทีมพัฒนาเกม)
งานฝั่งทีมพัฒนาเกม ออกแบบให้เน้นการเขียนแบบต่อเนื่อง (sequential write)
งานฝั่งทีมอินฟรา เครื่องเซิร์ฟเวอร์/OS: เปลี่ยนเป็น SSD (เริ่มจากดิสก์เก็บข้อมูลที่อ่านเขียนแบบกระจัดกระจายมาก) เครื่อง DB: เปลี่ยนดิสก์ DB ที่อ่านเขียนแบบกระจัดกระจายมากที่สุดเป็น SSD ก่อน
บนกราฟ สูงตลอดตั้งแต่แรก · ดีเลย์การอ่านและเขียนดิสก์ (r_await, w_await)
จุดที่ต้องดู ใช้ lsblk -d -o NAME,ROTA ตรวจว่าเป็นดิสก์หมุน (HDD) หรือไม่ และดู r/s, w/s, r_await และ w_await จาก iostat -x 1 ถ้าเป็น VM ให้ตรวจประเภทดิสก์จากสเปกของคลาวด์หรือสตอเรจ สัญญาณว่าใช่ เป็นดิสก์หมุน และแม้คำขอต่อวินาทีอยู่แค่ระดับหลายสิบถึงร้อยกว่า r_await และ w_await ก็อยู่ที่หลาย ms ถึงหลายสิบ ms ตลอด สัญญาณว่าไม่ใช่ เป็น SSD แต่ดีเลย์สูง: ให้ดูคิวดิสก์อิ่มตัว (dk-iops) หรือ burst credit หมด (dk-burst) วิธีตรวจ ใช้เครื่องมือฝั่งอินฟรา (ไม่ต้องใช้โค้ดเกม)
แหล่งอ้างอิง 5 รายการ
L12 ฐานข้อมูล
16 สาเหตุ · บทในฉบับหลัก
ID db-no-index · ผู้รับผิดชอบหลัก พัฒนาเซิร์ฟเวอร์ (ทีมพัฒนาเกม) · ร่วมกับ อินฟรา DB (ทีมอินฟรา)
ถ้าไม่มีอินเด็กซ์ การหาแถวที่ตรงเงื่อนไขต้องอ่านทั้งตาราง (full table scan)
ทำไม deploy ฟีเจอร์ใหม่ที่เพิ่มการค้นหาด้วยเงื่อนไขที่ไม่มีอินเด็กซ์ → ผลคือ สแกนทุกแถวหลายล้านแถว คิวรีเดียวใช้เวลาหลายร้อย ms ถึงหลายวินาที → บนหน้าจอ กล่องจดหมายและประวัติการเทรดโหลดช้า, connection ถูกถือครองไว้จนคำขออื่นต้องรอไปด้วย
อาการ อินพุตดีเลย์ , เข้าเกมไม่ได้/โหลดไม่จบ
ปัจจัย ความหน่วง, การหยุดชะงัก
ใครเจอ เฉพาะบางฟีเจอร์, ทั้งเซิร์ฟเวอร์
เกิดเมื่อไร ตอนทำแอ็กชันบางอย่าง
ผู้รับผิดชอบ ผู้รับผิดชอบหลัก พัฒนาเซิร์ฟเวอร์ (ทีมพัฒนาเกม) · ร่วมกับ อินฟรา DB (ทีมอินฟรา)
งานฝั่งทีมพัฒนาเกม ตรวจ query plan ของคิวรีใหม่ก่อน deploy, เพิ่มอินเด็กซ์, ตรวจว่าคิวรีที่แก้ข้อมูล (UPDATE, DELETE) ใช้อินเด็กซ์ด้วย
งานฝั่งทีมอินฟรา เฝ้าดู slow query log, หาคิวรีที่ทำ full table scan แล้วแชร์ให้ทีมพัฒนาเกม, เพิ่มอินเด็กซ์ระหว่างให้บริการด้วยวิธี online ที่ล็อกเพียงสั้น ๆ
ตัวเลขที่ควรรู้ ถ้ามีอินเด็กซ์ใช้เวลาหลาย ms ถ้าไม่มีจะช้าลงตามขนาดข้อมูล บนตารางใหญ่อาจช้ากว่าหลายร้อยถึงหลายหมื่นเท่า
บนกราฟ ขึ้นเป็นขั้นบันไดจากจุดหนึ่ง · ดีเลย์ของคิวรี DB, จำนวนแถวที่อ่าน
จุดที่ต้องดู MySQL ดู Rows_examined และ Rows_sent ใน slow query log (ถ้าเปิด log_queries_not_using_indexes จะบันทึกคิวรีที่ไม่ใช้อินเด็กซ์ด้วย) และ SUM_NO_INDEX_USED กับ SUM_ROWS_EXAMINED ใน events_statements_summary_by_digest ของ performance_schema แล้วรัน EXPLAIN ส่วน PostgreSQL ดู seq_scan และ seq_tup_read ใน pg_stat_user_tables แล้วรัน EXPLAIN สัญญาณว่าใช่ คิวรีที่เพิ่งโผล่หลัง deploy อ่านแถว (Rows_examined) มากกว่าแถวที่ส่งกลับ (Rows_sent) หลายพันเท่า และ EXPLAIN แสดงการสแกนทั้งตาราง (MySQL type ALL, PostgreSQL Seq Scan) seq_tup_read ของตารางใหญ่เพิ่มชันตั้งแต่เวลาที่ deploy สัญญาณว่าไม่ใช่ ใช้อินเด็กซ์แล้วแต่ยังช้า: น่าจะเป็นการรอล็อก (db-hot-row, db-ddl-lock) หรือ query plan เปลี่ยน (db-plan-flip) การสแกนทั้งตารางบนตารางเล็กอาจเป็นเรื่องปกติ วิธีตรวจ ใช้เครื่องมือฝั่งอินฟรา (ไม่ต้องใช้โค้ดเกม)
รายละเอียดเพิ่มเติม ผลกระทบมีมากกว่าการอ่านที่ช้าลง คิวรีที่แก้ข้อมูล (UPDATE, DELETE) โดยไม่มีอินเด็กซ์ ใน DB บางตัวจะล็อกแถวที่สแกนผ่านทั้งหมดด้วย จนอาจขวางการเซฟของผู้เล่นที่ไม่เกี่ยวข้อง
แหล่งอ้างอิง 8 รายการ
ID db-hot-row · ผู้รับผิดชอบหลัก พัฒนาเซิร์ฟเวอร์ (ทีมพัฒนาเกม) · ร่วมกับ อินฟรา DB (ทีมอินฟรา)
ถ้าทุกคนพยายามแก้แถวเดียวกัน (โกดังกิลด์, ไอเทมฮิตในตลาดประมูล, ตัวนับของทั้งเซิร์ฟเวอร์) จะได้ล็อกทีละคนเท่านั้น
ทำไม การแก้ไขมากระจุกที่แถวเดียวกันเพราะอีเวนต์หรือไอเทมฮิต → ผลคือ คำขอต้องรอจนกว่าจะได้ล็อก → บนหน้าจอ เทรดไม่สำเร็จ, “โปรดลองใหม่ภายหลัง”, ไทม์เอาต์
อาการ กดไม่ติด/โรลแบ็ค , อินพุตดีเลย์
ปัจจัย การหยุดชะงัก, ความหน่วง
ใครเจอ เฉพาะบางฟีเจอร์
เกิดเมื่อไร ตอนคนแห่มารวมกัน
ผู้รับผิดชอบ ผู้รับผิดชอบหลัก พัฒนาเซิร์ฟเวอร์ (ทีมพัฒนาเกม) · ร่วมกับ อินฟรา DB (ทีมอินฟรา)
งานฝั่งทีมพัฒนาเกม แบ่งแถว (sharded counter), ทำทรานแซกชันให้สั้น, รวมในหน่วยความจำแล้วเขียนลงทีเดียว
งานฝั่งทีมอินฟรา มอนิเตอร์เวลาและจำนวนครั้งที่รอ row lock เพื่อหาแถวที่มีการแย่งกันมากแล้วแชร์ผล
ตัวเลขที่ควรรู้ ถ้าคำขอหนึ่งถือล็อกไว้ 10 ms แถวนั้นจะแก้ได้สูงสุด 100 ครั้งใน 1 วินาที ถ้ามีการเรียกไปกลับเซิร์ฟเวอร์อื่นแทรกอยู่ในทรานแซกชัน ก็จะลดลงไปอีกตามเวลานั้น
บนกราฟ สูงตามจำนวนคนและโหลด · จำนวนและเวลารอ row lock
จุดที่ต้องดู MySQL ดูค่าที่เพิ่มขึ้นของ Innodb_row_lock_waits และ Innodb_row_lock_time กับ Innodb_row_lock_current_waits และใช้ sys.innodb_lock_waits หาว่าใครรอใคร PostgreSQL ดูเซสชันที่ wait_event_type เป็น Lock ใน pg_stat_activity และคำขอที่ granted เป็น false ใน pg_locks ถ้าเปิด log_lock_waits (ค่าเริ่มต้นปิด) ล็อกที่รอนานจะถูกบันทึกใน log สัญญาณว่าใช่ การรอล็อกเพิ่มชันตามอีเวนต์และจำนวนผู้เล่น และคำขอที่รออยู่ส่วนใหญ่ชี้ไปที่แถวเดียวกัน (คีย์เดียวกัน) ในตารางเดียวกัน สัญญาณว่าไม่ใช่ การรอกระจายเท่า ๆ กันในหลายตารางและหลายแถว: น่าจะเป็นดิสก์หรือ CPU อิ่มตัว ถ้าเซสชันเดียวถือล็อกไว้นานไม่ปล่อย ให้ดูทรานแซกชันที่เปิดทิ้งไว้นาน (db-long-tx) วิธีตรวจ ใช้เครื่องมือฝั่งอินฟรา (ไม่ต้องใช้โค้ดเกม)
แหล่งอ้างอิง 7 รายการ
ID db-deadlock · ผู้รับผิดชอบหลัก พัฒนาเซิร์ฟเวอร์ (ทีมพัฒนาเกม) · ร่วมกับ อินฟรา DB (ทีมอินฟรา)
ถ้าสองทรานแซกชัน (งาน DB ที่ประมวลผลเป็นชุดเดียว) ต่างรอแถวที่อีกฝ่ายล็อกไว้ DB จะบังคับยกเลิกฝั่งหนึ่ง
ทำไม การเทรด A ล็อกตามลำดับไอเทม→เงินในเกม ส่วน B ล็อกตามลำดับเงินในเกม→ไอเทม → ผลคือ DB ตรวจพบเดดล็อกแล้วโรลแบ็คฝั่งหนึ่ง → บนหน้าจอ เทรดและคราฟต์ล้มเหลวเป็นบางครั้ง, ไอเทมย้อนกลับ
อาการ กดไม่ติด/โรลแบ็ค , อินพุตดีเลย์
ปัจจัย แพ็กเก็ตหาย, การหยุดชะงัก
ใครเจอ เฉพาะบางฟีเจอร์
เกิดเมื่อไร ตอนคนแห่มารวมกัน, ตอนทำแอ็กชันบางอย่าง
ผู้รับผิดชอบ ผู้รับผิดชอบหลัก พัฒนาเซิร์ฟเวอร์ (ทีมพัฒนาเกม) · ร่วมกับ อินฟรา DB (ทีมอินฟรา)
งานฝั่งทีมพัฒนาเกม ใช้ลำดับการล็อกเดียวกันทุกที่, ทำทรานแซกชันให้สั้น, ลองใหม่อัตโนมัติเมื่อล้มเหลว
งานฝั่งทีมอินฟรา เปิดการตรวจจับเดดล็อกไว้และเก็บบันทึกเดดล็อกมาแชร์, เซิร์ฟเวอร์ MySQL ที่ปิดการตรวจจับให้ลดขีดจำกัดการรอล็อก (ค่าเริ่มต้น 50 วินาที)
ตัวเลขที่ควรรู้ MySQL (InnoDB) ตรวจพบได้แทบทันที PostgreSQL ใช้เวลา 1 วินาทีตามค่าเริ่มต้น และ SQL Server ใช้นานสุดราว 5 วินาที ระหว่างนั้นคำขอทั้งสองหยุดรออยู่ ถ้าเป็นเซิร์ฟเวอร์ MySQL ที่ปิดการตรวจจับไว้เพราะคำขอพร้อมกันมากเป็นพิเศษ จะต้องรอจนถึงขีดจำกัดการรอล็อก (ค่าเริ่มต้น 50 วินาที)
บนกราฟ พุ่งแบบสุ่มเป็นครั้งคราว · จำนวนเดดล็อก, จำนวนการเทรดที่ล้มเหลว
จุดที่ต้องดู MySQL ดู LATEST DETECTED DEADLOCK ใน SHOW ENGINE INNODB STATUS (เฉพาะรายการล่าสุด 1 รายการ), เดดล็อกทั้งหมดที่บันทึกใน error log เมื่อเปิด innodb_print_all_deadlocks และ lock_deadlocks ใน INFORMATION_SCHEMA.INNODB_METRICS ส่วน PostgreSQL ดู deadlocks ใน pg_stat_database และ SQL Server ดู xml_deadlock_report ของเซสชัน system_health ที่เปิดไว้เป็นค่าเริ่มต้น รหัสข้อผิดพลาดฝั่งเซิร์ฟเวอร์เกมคือ MySQL 1213, PostgreSQL 40P01, SQL Server 1205 สัญญาณว่าใช่ ช่วงที่เทรดหรือคราฟต์ล้มเหลว จำนวนเดดล็อกเพิ่มขึ้น และสองทรานแซกชันที่บันทึกไว้ล็อกตารางชุดเดียวกันในลำดับตรงข้ามกัน สัญญาณว่าไม่ใช่ จำนวนเดดล็อกเท่าเดิมแต่ยังล้มเหลว: น่าจะเป็นการรอล็อกเกินขีดจำกัด (MySQL ข้อผิดพลาด 1205) หรือ hot row (db-hot-row) วิธีตรวจ ใช้เครื่องมือฝั่งอินฟรา (ไม่ต้องใช้โค้ดเกม)
แหล่งอ้างอิง 10 รายการ
ID db-pool · ผู้รับผิดชอบหลัก พัฒนาเซิร์ฟเวอร์ (ทีมพัฒนาเกม) · ร่วมกับ อินฟรา DB (ทีมอินฟรา)
จำนวนการเชื่อมต่อที่เปิดไว้กับ DB มีจำกัด ถ้าคิวรีที่ช้าถือครองการเชื่อมต่อไว้ คำขอที่เหลือต้องรอ
ทำไม ทุกการเชื่อมต่อถูกใช้หมดเพราะคิวรีช้าหรือคำขอทะลัก → ผลคือ คำขอใหม่ต้องรอจนกว่าจะมีการเชื่อมต่อว่าง → บนหน้าจอ ล็อกอินโหลดไม่จบ, เซฟช้า, ไทม์เอาต์
อาการ เข้าเกมไม่ได้/โหลดไม่จบ , อินพุตดีเลย์
ปัจจัย การหยุดชะงัก, ความหน่วง
ใครเจอ ทั้งเซิร์ฟเวอร์, เฉพาะบางฟีเจอร์
เกิดเมื่อไร หลังล็อกอิน/หลังปิดปรับปรุง, ตอนคนแห่มารวมกัน
ผู้รับผิดชอบ ผู้รับผิดชอบหลัก พัฒนาเซิร์ฟเวอร์ (ทีมพัฒนาเกม) · ร่วมกับ อินฟรา DB (ทีมอินฟรา)
งานฝั่งทีมพัฒนาเกม กำจัดคิวรีที่ช้า, ปรับขนาด pool และไทม์เอาต์การรอ (อย่าขยาย pool ไปเรื่อย ๆ), แยก pool ตามฟีเจอร์
งานฝั่งทีมอินฟรา ตรวจจำนวนการเชื่อมต่อสูงสุดของ DB และ CPU กับ IOPS ที่เหลือ, ก่อนเพิ่มเครื่องหรือทำ autoscaling ให้ตรวจว่าจำนวนเซิร์ฟเวอร์ × ขนาด pool ไม่เกินจำนวนการเชื่อมต่อสูงสุด, เพิ่มเมตริกการรอ connection และการรอล็อกเข้าในการมอนิเตอร์
ตัวเลขที่ควรรู้ จำนวนการเชื่อมต่อที่ต้องใช้ประมาณได้จาก “คำขอต่อวินาที × เวลาที่คำขอหนึ่งถือครองการเชื่อมต่อ” ถ้า 2,000 รายการใน 1 วินาที รายการละ 5 ms จะมีการเชื่อมต่อที่ยุ่งตลอดเฉลี่ย 10 ตัว เพื่อเผื่อช่วงที่คำขอแห่เข้ามา ปกติจะตั้งไว้สองสามเท่าของค่านั้น ถ้าคิวรีช้าลงเป็น 150 ms คำขอปริมาณเท่าเดิมจะต้องใช้ 300 ตัว
บนกราฟ ชนเพดานแล้วแบนราบ · จำนวนการเชื่อมต่อ DB ที่ใช้อยู่, เวลารอ connection
จุดที่ต้องดู นับสถานะการเชื่อมต่อแยกตามเซิร์ฟเวอร์เกมจากฝั่ง DB MySQL ดู Host, Command (การเชื่อมต่อที่ว่างคือ Sleep) และ Time ใน SHOW PROCESSLIST กับ Threads_connected, Threads_running และจำนวนการเชื่อมต่อที่ถูกปฏิเสธ Connection_errors_max_connections ส่วน PostgreSQL นับ pg_stat_activity โดยจัดกลุ่มตาม client_addr และ state ถ้าไลบรารี connection pool ของเซิร์ฟเวอร์เกมส่งออกจำนวนที่รอและเวลารอ ให้ดูคู่กันด้วย สัญญาณว่าใช่ การเชื่อมต่อของเซิร์ฟเวอร์เกมตัวหนึ่งกำลังรันคิวรีครบเท่าขนาด pool และการเชื่อมต่อว่างเป็น 0 ระหว่างนั้นล็อกอินและเซฟต้องรอ หรือจำนวนการเชื่อมต่อทั้งหมดของ DB แตะ max_connections จนการเชื่อมต่อใหม่ถูกปฏิเสธ สัญญาณว่าไม่ใช่ มีการเชื่อมต่อว่างเหลือพอแต่ยังช้า: น่าจะเป็นดีเลย์ของตัวคิวรีเอง (db-no-index, db-hot-row) หรือทรัพยากร DB อิ่มตัว วิธีตรวจ ใช้เครื่องมือฝั่งอินฟรา (ไม่ต้องใช้โค้ดเกม)
รายละเอียดเพิ่มเติม ถ้าขยาย pool ไปเรื่อย ๆ จะมีแต่ CPU ของ DB และการแย่งล็อกที่เพิ่มขึ้น จนทุกอย่างช้าลงพร้อมกัน และถ้าจำนวนเซิร์ฟเวอร์ × ขนาด pool เกินจำนวนการเชื่อมต่อสูงสุดของ DB เซิร์ฟเวอร์ที่เพิ่มเข้ามาหรือเพิ่งรีสตาร์ตจะเชื่อมต่อไม่ได้เลย มักเกิดตอน autoscaling หรือทันทีหลังปิดปรับปรุง
แหล่งอ้างอิง 6 รายการ
ID db-replica-lag · ผู้รับผิดชอบหลัก อินฟรา DB (ทีมอินฟรา) · ร่วมกับ พัฒนาเซิร์ฟเวอร์ (ทีมพัฒนาเกม)
การเขียนไปที่ DB หลัก ส่วนการอ่านทำจาก replica ถ้า replica ตามไม่ทัน ข้อมูลที่เพิ่งเขียนจะยังมองไม่เห็น
ทำไม การเขียนกระจุกที่ DB หลักจน replica ตามหลังไปหลายวินาที → ผลคือ อ่านข้อมูลที่เพิ่งเซฟจาก replica แล้วยังไม่มี → บนหน้าจอ ไอเทมที่เพิ่งซื้อไม่ขึ้น, ราคาในตลาดซื้อขายเป็นค่าเก่า, บั๊กแจกของซ้ำ
อาการ กดไม่ติด/โรลแบ็ค
ปัจจัย ความหน่วง
ใครเจอ เฉพาะบางฟีเจอร์
เกิดเมื่อไร ตอนคนแห่มารวมกัน, ช่วงพีคหัวค่ำ
ผู้รับผิดชอบ ผู้รับผิดชอบหลัก อินฟรา DB (ทีมอินฟรา) · ร่วมกับ พัฒนาเซิร์ฟเวอร์ (ทีมพัฒนาเกม)
งานฝั่งทีมพัฒนาเกม อ่านข้อมูลที่เพิ่งเขียนจาก DB หลัก, ตรวจว่าแจกไปแล้วหรือยังและแจกของใน DB หลักภายในทรานแซกชันเดียว (กันการแจกซ้ำด้วย unique key หรือ UPDATE แบบมีเงื่อนไข)
งานฝั่งทีมอินฟรา ตั้ง alert replication lag, ให้ replica มีสเปกเท่า DB หลักหรือสูงกว่าและใช้ parallel replication, แบ่งการลบข้อมูลจำนวนมากเป็นชุดเล็ก ๆ, ดูแลคิวรีสรุปผลที่รันนานบน replica
บนกราฟ สูงตามจำนวนคนและโหลด · replication lag (วินาที)
จุดที่ต้องดู MySQL ดู Seconds_Behind_Source ของ SHOW REPLICA STATUS บน replica (เวอร์ชันก่อน 8.0.22 ใช้ SHOW SLAVE STATUS) PostgreSQL ดู write_lag, flush_lag และ replay_lag ใน pg_stat_replication บนเซิร์ฟเวอร์หลัก ส่วน RDS ดู ReplicaLag สัญญาณว่าใช่ ช่วงที่มีคนแจ้งว่า “มองไม่เห็น” ค่า lag อยู่ที่หลายวินาทีขึ้นไป และเมื่อ lag หายแล้วดูอีกครั้งก็ปกติ lag เพิ่มขึ้นช่วงที่การเขียนทะลัก ลบข้อมูลจำนวนมาก หรือมีคิวรีสรุปผลยาว ๆ บน replica สัญญาณว่าไม่ใช่ lag ใกล้ 0 แต่ยังมองไม่เห็น: น่าจะเป็นแคชของเซิร์ฟเวอร์เกมหรือการซิงก์ วิธีตรวจ ใช้เครื่องมือฝั่งอินฟรา (ไม่ต้องใช้โค้ดเกม)
รายละเอียดเพิ่มเติม แม้การเขียนไม่มาก replica ก็ตามหลังได้ การลบข้อมูลจำนวนมากครั้งเดียวที่ใช้เวลา 10 นาทีบน DB หลัก จะทำให้ replica ตามหลังไปนานเท่ากันระหว่างที่รันซ้ำบน replica และคิวรีสรุปผลที่รันนานบน replica ก็ทำให้ตามช้าลงด้วย
แหล่งอ้างอิง 6 รายการ
ID db-checkpoint · ผู้รับผิดชอบหลัก อินฟรา DB (ทีมอินฟรา)
จังหวะที่ DB เขียนส่วนที่เปลี่ยนแปลงในหน่วยความจำลงดิสก์รวดเดียวตามรอบ คิวรีจะช้าลง
ทำไม ส่วนที่เปลี่ยนแปลงสะสมแล้วถูกเขียนลงดิสก์ตามรอบ → ผลคือ ช่วงนั้นดิสก์ยุ่ง คิวรีจึงช้า → บนหน้าจอ เซฟและโหลดช้าลงเป็นรอบ
อาการ อินพุตดีเลย์ , กระตุก
ปัจจัย ความหน่วง
ใครเจอ ทั้งเซิร์ฟเวอร์, เฉพาะบางฟีเจอร์
เกิดเมื่อไร เป็นรอบสม่ำเสมอ
ผู้รับผิดชอบ ผู้รับผิดชอบหลัก อินฟรา DB (ทีมอินฟรา)
งานฝั่งทีมอินฟรา แบ่ง checkpoint เป็นช่วงเล็ก ๆ ให้สม่ำเสมอ, ตั้ง transaction log (redo log, WAL) ให้ใหญ่พอ, ใช้ดิสก์ที่เร็ว
บนกราฟ พุ่งเป็นรอบ · ดีเลย์ของคิวรี DB, ปริมาณการเขียนดิสก์
จุดที่ต้องดู PostgreSQL ดูเวลา checkpoint และจำนวนบัฟเฟอร์ที่เขียนจาก log ของ log_checkpoints (เวอร์ชันใหม่เปิดเป็นค่าเริ่มต้น), จำนวนครั้งของ checkpoint (ตั้งแต่ 17 คือ num_timed และ num_requested ใน pg_stat_checkpointer, 16 ลงไปคือ checkpoints_timed และ checkpoints_req ใน pg_stat_bgwriter) และคำเตือน checkpoint_warning ส่วน MySQL ดูส่วนต่างระหว่าง Log sequence number กับ Last checkpoint at ในส่วน LOG ของ SHOW ENGINE INNODB STATUS วางซ้อนกับปริมาณการเขียนและดีเลย์การเขียนดิสก์ของเซิร์ฟเวอร์ สัญญาณว่าใช่ ช่วงที่ดีเลย์ของคิวรีพุ่งตรงกับเวลา checkpoint และตอนนั้นปริมาณการเขียนกับดีเลย์การเขียนดิสก์พุ่งขึ้น ใน PostgreSQL ถ้า checkpoint ตามคำขอ (num_requested) มากกว่า checkpoint ตามเวลา (num_timed) มาก ถือว่า WAL แตะ max_wal_size บ่อยจน checkpoint มาเร็วกว่ากำหนด สัญญาณว่าไม่ใช่ พุ่งเป็นรอบที่ไม่เกี่ยวกับเวลา checkpoint: น่าจะเป็นการสำรองข้อมูลหรืองาน batch (dk-backup, db-batch) วิธีตรวจ ใช้เครื่องมือฝั่งอินฟรา (ไม่ต้องใช้โค้ดเกม)
รายละเอียดเพิ่มเติม ถ้าตั้ง transaction log ที่เก็บบันทึกการเปลี่ยนแปลง (redo log ของ MySQL, WAL ของ PostgreSQL) เล็กเกินไป ทุกครั้งที่ log เต็ม DB ต้องรีบทำ checkpoint รวดเดียว throughput การเขียนจึงตกฮวบเป็นพัก ๆ
แหล่งอ้างอิง 7 รายการ
ID db-cold-cache · ผู้รับผิดชอบหลัก อินฟรา DB (ทีมอินฟรา) · ร่วมกับ พัฒนาเซิร์ฟเวอร์ (ทีมพัฒนาเกม)
เมื่อรีสตาร์ต DB แคชในหน่วยความจำจะว่างเปล่า ช่วงหนึ่งข้อมูลทุกอย่างที่ดึงจึงต้องอ่านจากดิสก์
ทำไม รีสตาร์ต DB ตอนปิดปรับปรุง → ผลคือ ข้อมูลที่ใช้บ่อยไม่อยู่ในหน่วยความจำ จึงต้องอ่านจากดิสก์ → บนหน้าจอ หลังปิดปรับปรุงใหม่ ๆ ล็อกอินและโหลดช้าอยู่พักหนึ่ง
อาการ เข้าเกมไม่ได้/โหลดไม่จบ , อินพุตดีเลย์
ปัจจัย ความหน่วง
ใครเจอ ทั้งเซิร์ฟเวอร์
เกิดเมื่อไร หลังล็อกอิน/หลังปิดปรับปรุง
ผู้รับผิดชอบ ผู้รับผิดชอบหลัก อินฟรา DB (ทีมอินฟรา) · ร่วมกับ พัฒนาเซิร์ฟเวอร์ (ทีมพัฒนาเกม)
งานฝั่งทีมพัฒนาเกม เปิดให้เข้าแบบค่อยเป็นค่อยไป (ใช้คิวล็อกอินเพิ่มจำนวนคนที่ล็อกอินทีละขั้น)
งานฝั่งทีมอินฟรา วอร์มแคชหลังรีสตาร์ต (warming, ตรวจการตั้งค่าบันทึกและกู้คืน buffer pool), DB ที่กู้มาจากสแนปช็อตให้อ่านดิสก์ล่วงหน้าด้วย
บนกราฟ พุ่งทันทีหลังเปิดเซิร์ฟ/ปิดปรับปรุง · การอ่านดิสก์, อัตรา hit ของ buffer cache
จุดที่ต้องดู MySQL ดูอัตราส่วนระหว่าง Innodb_buffer_pool_reads (จำนวนครั้งที่ไม่มีใน buffer pool จนต้องอ่านจากดิสก์) กับ Innodb_buffer_pool_read_requests และความคืบหน้าการวอร์ม Innodb_buffer_pool_load_status ส่วน PostgreSQL ดู blks_read และ blks_hit ใน pg_stat_database และดูจำนวนการอ่านดิสก์ของเซิร์ฟเวอร์ DB ประกอบ สัญญาณว่าใช่ หลังรีสตาร์ตใหม่ ๆ การอ่านดิสก์พุ่งและอัตรา hit ต่ำ แล้วค่อย ๆ ฟื้นตามเวลา และช่วงนั้นล็อกอินและโหลดช้า สัญญาณว่าไม่ใช่ อัตรา hit เท่าปกติแต่หลังปิดปรับปรุงยังช้า: น่าจะเป็นคนแห่ล็อกอินและ N+1 (db-login-storm) หรือ connection pool (db-pool) วิธีตรวจ ใช้เครื่องมือฝั่งอินฟรา (ไม่ต้องใช้โค้ดเกม)
รายละเอียดเพิ่มเติม MySQL จะบันทึกรายการ page ใน buffer pool ตอนปิด แล้วอ่านกลับเข้ามาเบื้องหลังตอนเปิด แต่ต้องใช้เวลากว่าจะเต็ม ถ้ากู้ DB บนคลาวด์มาจากสแนปช็อต (สำเนาดิสก์) ตัวดิสก์เองก็ช้าในทุกบล็อกที่อ่านครั้งแรก อาการจึงนานขึ้นไปอีก
กรณีจริง Roblox 2021: Roblox ล่ม 73 ชั่วโมง: การแย่งทรัพยากรในคลัสเตอร์ service discovery (Consul)
แหล่งอ้างอิง 5 รายการ
ID db-login-storm · ผู้รับผิดชอบหลัก พัฒนาเซิร์ฟเวอร์ (ทีมพัฒนาเกม) · ร่วมกับ อินฟรา DB (ทีมอินฟรา)
ถ้าการโหลดตัวละครหนึ่งตัวต้องดึงข้อมูลแยกกันหลายสิบครั้ง ผู้เล่นหลายหมื่นคนที่ล็อกอินพร้อมกันจะกลายเป็นคิวรีหลายล้านคิวรี
ทำไม ตอนโหลดตัวละคร ดึงไอเทม สกิล และเควสต์แยกกันทีละอย่าง → ผลคือ หลังปิดปรับปรุงใหม่ ๆ คนล็อกอินพร้อมกันจนคิวรีพุ่ง → บนหน้าจอ ล็อกอินโหลดไม่จบ, การเซฟของคนที่กำลังเล่นอยู่ก็ล่าช้าไปด้วย
อาการ เข้าเกมไม่ได้/โหลดไม่จบ , อินพุตดีเลย์
ปัจจัย การหยุดชะงัก, ความหน่วง
ใครเจอ ทั้งเซิร์ฟเวอร์
เกิดเมื่อไร หลังล็อกอิน/หลังปิดปรับปรุง
ผู้รับผิดชอบ ผู้รับผิดชอบหลัก พัฒนาเซิร์ฟเวอร์ (ทีมพัฒนาเกม) · ร่วมกับ อินฟรา DB (ทีมอินฟรา)
งานฝั่งทีมพัฒนาเกม ดึงข้อมูลรวมทีเดียว, คิวล็อกอิน, แคช, ตรวจจำนวนคิวรีที่เกิดจาก lazy loading ของ ORM
งานฝั่งทีมอินฟรา จัดอันดับคิวรีที่ถูกเรียกบ่อยแล้วแชร์, มอนิเตอร์จำนวนคิวรีและจำนวน connection ช่วงล็อกอินหลังปิดปรับปรุง
บนกราฟ พุ่งทันทีหลังเปิดเซิร์ฟ/ปิดปรับปรุง · จำนวนคิวรีต่อวินาทีของ DB, จำนวนการล็อกอิน
จุดที่ต้องดู วางจำนวนการล็อกอินหลังปิดปรับปรุงซ้อนกับจำนวนคิวรีต่อวินาทีของ DB (MySQL คือค่าที่เพิ่มขึ้นของ Questions) แล้วคำนวณจำนวนคิวรีต่อการล็อกอินหนึ่งครั้ง คิวรีที่ถูกเรียกบ่อยที่สุดดึงได้จาก COUNT_STAR ใน events_statements_summary_by_digest ของ MySQL และ calls ใน pg_stat_statements ของ PostgreSQL สัญญาณว่าใช่ การล็อกอินหนึ่งครั้งใช้คิวรีหลายสิบคิวรี และคิวรีอันดับต้น ๆ เป็นคิวรีสั้น ๆ หน้าตาเดียวกันที่ดึงข้อมูลด้วย ID ตัวละครตัวเดียว ถ้าจำนวนคิวรีต่อการล็อกอินเพิ่มขึ้นหลังแพตช์ แพตช์นั้นคือจุดเริ่มต้น สัญญาณว่าไม่ใช่ จำนวนคิวรีต่อการล็อกอินน้อยแต่แต่ละคิวรีช้า: น่าจะเป็น cold cache (db-cold-cache) หรืออินเด็กซ์ (db-no-index) วิธีตรวจ ใช้เครื่องมือฝั่งอินฟรา (ไม่ต้องใช้โค้ดเกม)
รายละเอียดเพิ่มเติม lazy loading ของ ORM (ไลบรารีที่สร้างคิวรี DB ให้) สร้างคิวรีแบบนี้โดยที่นักพัฒนาเองก็ไม่รู้ตัว บนเซิร์ฟเวอร์ dev มีตัวละครไม่กี่ตัวจึงไม่เห็นผล แล้วมาโผล่ครั้งแรกตอนคนล็อกอินพร้อมกันบนเซิร์ฟเวอร์ live
แหล่งอ้างอิง 5 รายการ
ID db-batch · ผู้รับผิดชอบหลัก พัฒนาเซิร์ฟเวอร์ (ทีมพัฒนาเกม) · ร่วมกับ อินฟรา DB (ทีมอินฟรา)
ถ้ารันการสรุปอันดับ, การส่งจดหมายในเกมแบบรวดเดียว หรือการล้างข้อมูลเก่าระหว่างให้บริการ งานเหล่านี้จะยึดล็อกและดิสก์ไว้
ทำไม รันงานขนาดใหญ่ในช่วงเวลาให้บริการ → ผลคือ ล็อกเป็นช่วงกว้าง, ถือครองดิสก์และ CPU → บนหน้าจอ เทรดและเซฟล้มเหลวในบางช่วงเวลา, โหลดช้า
อาการ อินพุตดีเลย์ , กดไม่ติด/โรลแบ็ค
ปัจจัย ความหน่วง, การหยุดชะงัก
ใครเจอ เฉพาะบางฟีเจอร์, ทั้งเซิร์ฟเวอร์
เกิดเมื่อไร เป็นรอบสม่ำเสมอ
ผู้รับผิดชอบ ผู้รับผิดชอบหลัก พัฒนาเซิร์ฟเวอร์ (ทีมพัฒนาเกม) · ร่วมกับ อินฟรา DB (ทีมอินฟรา)
งานฝั่งทีมพัฒนาเกม แบ่งเป็นชุดเล็ก ๆ ทำทีละน้อย, สรุปผลบน replica
งานฝั่งทีมอินฟรา จัด replica สำหรับงานสรุปผล, ตั้งเวลา batch ไว้ช่วงที่ว่าง, เฝ้าดู lock escalation และการรอ gap lock
บนกราฟ พุ่งเป็นรอบ · ดีเลย์ของคิวรี DB, การรอล็อก
จุดที่ต้องดู หาคิวรียาวที่รันอยู่ในช่วงที่แลค MySQL ดู slow query log ส่วน PostgreSQL ดู query_start และ query ใน pg_stat_activity แล้วเทียบกับเมตริกการรอล็อกในช่วงเดียวกันและตารางเวลา batch (cron, event scheduler ของ DB) SQL Server บันทึก lock escalation ด้วย extended event lock_escalation สัญญาณว่าใช่ คิวรี UPDATE, DELETE หรือสรุปผลขนาดใหญ่รันเวลาเดิมทุกครั้ง และระหว่างนั้นการรอล็อกกับอัตราการใช้งานดิสก์สูงขึ้นพร้อมกัน สัญญาณว่าไม่ใช่ ช่วงนั้นไม่มีคิวรียาว: น่าจะเป็น checkpoint (db-checkpoint) หรือการสำรองข้อมูลของเซิร์ฟเวอร์ (dk-backup) วิธีตรวจ ใช้เครื่องมือฝั่งอินฟรา (ไม่ต้องใช้โค้ดเกม)
รายละเอียดเพิ่มเติม SQL Server จะเปลี่ยนเป็นล็อกทั้งตารางเมื่อคำสั่งเดียวถือ row lock เกินประมาณ 5,000 ตัว (lock escalation) ทันทีนั้นทุกคำขอที่ใช้ตารางเดียวกันจะหยุด MySQL ก็เช่นกัน ด้วยการตั้งค่าเริ่มต้น ถ้าแก้ข้อมูลด้วยเงื่อนไขแบบช่วง จะล็อกไปถึงช่องว่างระหว่างแถว (gap lock) ทำให้เพิ่มแถวใหม่ไม่ได้
แหล่งอ้างอิง 4 รายการ
ID db-failover · ผู้รับผิดชอบหลัก อินฟรา DB (ทีมอินฟรา) · ร่วมกับ พัฒนาเซิร์ฟเวอร์ (ทีมพัฒนาเกม)
ระหว่างที่ DB หลักล่มและสลับไปใช้ DB สำรอง จะเขียนข้อมูลไม่ได้ และข้อมูลช่วงท้ายที่ยัง replicate ไม่ทันอาจหายไป
ทำไม DB หลักขัดข้อง DB สำรองจึงถูกยกขึ้นเป็นตัวหลัก (promote) → ผลคือ ระหว่างสลับ เขียนไม่ได้หลายวินาทีถึงไม่กี่นาที ถ้าเป็น asynchronous replication ข้อมูลที่ยังไม่ได้ replicate อาจหาย → บนหน้าจอ เซฟไม่สำเร็จทั้งหมดชั่วครู่, ไอเทมและค่าประสบการณ์ถูกโรลแบ็ค
อาการ กดไม่ติด/โรลแบ็ค , ค้าง , หลุด , เข้าเกมไม่ได้/โหลดไม่จบ
ปัจจัย การหยุดชะงัก, แพ็กเก็ตหาย
ใครเจอ ทั้งเซิร์ฟเวอร์
เกิดเมื่อไร สุ่มเป็นครั้งคราว
ผู้รับผิดชอบ ผู้รับผิดชอบหลัก อินฟรา DB (ทีมอินฟรา) · ร่วมกับ พัฒนาเซิร์ฟเวอร์ (ทีมพัฒนาเกม)
งานฝั่งทีมพัฒนาเกม ทำให้การเซฟลองใหม่ได้, ตั้งค่าให้ทิ้งการเชื่อมต่อที่ขาดอย่างรวดเร็วแล้วเชื่อมต่อใหม่ไปยังที่อยู่ใหม่ (connection pool, DNS cache), ตรวจการเชื่อมต่อใหม่ตอนซ้อม failover
งานฝั่งทีมอินฟรา ใช้ synchronous หรือ semi-synchronous replication (แลกกับดีเลย์การเขียน), ซ้อม failover, มอนิเตอร์เวลา failover และ replication lag
ตัวเลขที่ควรรู้ การ failover อัตโนมัติของ managed DB ปกติใช้เวลาหลายสิบวินาทีถึง 2 นาที ถ้าเป็น asynchronous replication อาจเสียการเซฟล่าสุดไปเท่ากับ replication lag (ไม่ถึง 1 วินาทีถึงหลายวินาที)
บนกราฟ การเชื่อมต่อหลุดพร้อมกัน · จำนวนการเชื่อมต่อ DB, จำนวนข้อผิดพลาดในการเขียน
จุดที่ต้องดู วางบันทึก failover ฝั่ง DB (RDS คืออีเวนต์ RDS-EVENT-0013 เริ่ม failover และ RDS-EVENT-0049 failover เสร็จ ส่วน DB ที่ดูแลเองคือ log การ promote) กับจำนวนการเชื่อมต่อ DB และจำนวนข้อผิดพลาดในการเชื่อมต่อของเซิร์ฟเวอร์เกมไว้บนกราฟเดียวกัน ถ้าเป็น asynchronous replication ให้ดู replication lag ก่อนเกิดเหตุด้วย (RDS ReplicaLag, replay_lag ใน pg_stat_replication ของ PostgreSQL) สัญญาณว่าใช่ เซฟไม่สำเร็จกระจุกอยู่ในช่วงหนึ่ง และช่วงนั้นอยู่ระหว่างเวลาเริ่มและเวลาเสร็จ failover ปริมาณที่ย้อนกลับใกล้เคียงกับ replication lag ก่อนเกิดเหตุ เซิร์ฟเวอร์เกมที่ยัง error ต่อหลัง failover เสร็จ คือยังใช้การเชื่อมต่อที่ต่อไว้กับที่อยู่เดิม สัญญาณว่าไม่ใช่ การเชื่อมต่อขาดในช่วงที่ไม่มีบันทึก failover: น่าจะเป็นเครือข่ายหรือ DB โหลดเกิน วิธีตรวจ ใช้เครื่องมือฝั่งอินฟรา (ไม่ต้องใช้โค้ดเกม)
กรณีจริง Riot Games 2021: League of Legends EUW ขัดข้อง 5 ชั่วโมง: DB เสริมตัวเดียวทำให้ทั้งเซิร์ฟเวอร์หยุด
แหล่งอ้างอิง 7 รายการ
ID db-save-interval · ผู้รับผิดชอบหลัก พัฒนาเซิร์ฟเวอร์ (ทีมพัฒนาเกม) · ร่วมกับ อินฟรา DB (ทีมอินฟรา)
ถ้าเซฟแค่ทุกไม่กี่นาทีเพื่อลดโหลด เมื่อเซิร์ฟเวอร์ล่มในระหว่างนั้น ความคืบหน้าจะหายไป
ทำไม เซฟสถานะตัวละครทุกไม่กี่นาที → ผลคือ เซิร์ฟเวอร์แครชหรือขัดข้องในระหว่างนั้น → บนหน้าจอ เข้าเกมใหม่แล้วกลับไปเป็นสถานะเมื่อไม่กี่นาทีก่อน (โรลแบ็ค)
อาการ กดไม่ติด/โรลแบ็ค
ปัจจัย แพ็กเก็ตหาย
ใครเจอ ทั้งเซิร์ฟเวอร์, บางจุด/บางแชนแนล
เกิดเมื่อไร สุ่มเป็นครั้งคราว
ผู้รับผิดชอบ ผู้รับผิดชอบหลัก พัฒนาเซิร์ฟเวอร์ (ทีมพัฒนาเกม) · ร่วมกับ อินฟรา DB (ทีมอินฟรา)
งานฝั่งทีมพัฒนาเกม เซฟทันทีเมื่อเกิดเหตุการณ์สำคัญ (เทรด, ได้ของหายาก), บันทึก log การเปลี่ยนแปลง
งานฝั่งทีมอินฟรา ตรวจว่า DB มี IOPS และ CPU เหลือพอรองรับการเขียนที่เพิ่มขึ้นเมื่อลดรอบเซฟ
บนกราฟ การเชื่อมต่อหลุดพร้อมกัน · จำนวนการเชื่อมต่อ, จำนวนการแจ้งโรลแบ็ค
จุดที่ต้องดู วางเวลาที่แครชหรือขัดข้องคู่กับเวลาเซฟล่าสุดของตัวละครที่แจ้งโรลแบ็ค (log การเซฟของเซิร์ฟเวอร์เกมหรือคอลัมน์เวลาแก้ไขใน DB) สัญญาณว่าใช่ จุดที่ย้อนกลับตรงกับเวลาเซฟล่าสุดก่อนแครช และเวลาที่หายไปสั้นกว่ารอบเซฟ สัญญาณว่าไม่ใช่ log ของเซิร์ฟเวอร์เกมบอกว่าเซฟเสร็จแล้วแต่ยังย้อนกลับ: น่าจะเป็นข้อมูลหายจาก failover ของ DB (db-failover) หรือค่าเก่าที่อ่านจาก replica (db-replica-lag) วิธีตรวจ ต้องมี log หรือเมตริกจากเซิร์ฟเวอร์/ไคลเอนต์เกม
แหล่งอ้างอิง 2 รายการ
แคชสแตมปีด Cache stampede / thundering herd
ID db-cache-stampede · ผู้รับผิดชอบหลัก พัฒนาเซิร์ฟเวอร์ (ทีมพัฒนาเกม) · ร่วมกับ อินฟรา DB (ทีมอินฟรา)
ถ้าแคชของข้อมูลยอดนิยมหมดอายุพร้อมกัน คำขอหลายพันรายการจะแห่ไปที่ DB พร้อมกัน
ทำไม ข้อมูลยอดนิยมที่เก็บใน Redis หรือที่อื่นหมดอายุพร้อมกัน → ผลคือ คำขอที่พยายามสร้างข้อมูลเดียวกันใหม่แห่ไปที่ DB พร้อมกัน → บนหน้าจอ DB โหลดเกิน หลายฟีเจอร์จึงช้าลงหรือค้างต่อ ๆ กันไป
อาการ อินพุตดีเลย์ , ค้าง , เข้าเกมไม่ได้/โหลดไม่จบ
ปัจจัย การหยุดชะงัก, ความหน่วง
ใครเจอ ทั้งเซิร์ฟเวอร์
เกิดเมื่อไร เป็นรอบสม่ำเสมอ, ตอนคนแห่มารวมกัน
ผู้รับผิดชอบ ผู้รับผิดชอบหลัก พัฒนาเซิร์ฟเวอร์ (ทีมพัฒนาเกม) · ร่วมกับ อินฟรา DB (ทีมอินฟรา)
งานฝั่งทีมพัฒนาเกม สุ่มกระจายเวลาหมดอายุ, ให้คำขอเดียวรีเฟรช ที่เหลือใช้ค่าเก่า
งานฝั่งทีมอินฟรา จัด replica และ failover อัตโนมัติไม่ให้แคชว่างทั้งก้อนเมื่อ Redis รีสตาร์ตหรือขัดข้อง, ตรวจว่า DB มีกำลังเหลือพอรับได้แม้แคชว่าง
บนกราฟ พุ่งเป็นรอบ · อัตรา hit ของแคช, จำนวนคิวรีต่อวินาทีของ DB
จุดที่ต้องดู keyspace_hits และ keyspace_misses (อัตรา hit), expired_keys และการรีสตาร์ต (uptime_in_seconds) จาก INFO ของ Redis วางซ้อนกับจำนวนคิวรีต่อวินาทีของ DB และนับว่าในจังหวะนั้นมีคิวรีเดียวกันรันพร้อมกันบน DB กี่ตัว (MySQL SHOW PROCESSLIST, PostgreSQL pg_stat_activity) สัญญาณว่าใช่ ช่วงที่ cache miss พุ่งขึ้นทันที จำนวนคิวรี DB พุ่งตาม และคิวรีที่รันพร้อมกันส่วนใหญ่เป็นคิวรีเดียวกันที่อ่านข้อมูลเดียวกัน ตรงกับรอบหมดอายุของคีย์ยอดนิยมหรือเวลาที่ Redis รีสตาร์ต สัญญาณว่าไม่ใช่ cache miss เท่าปกติแต่คิวรี DB เพิ่มอย่างเดียว: น่าจะเป็นคนแห่ล็อกอิน (db-login-storm) หรืองาน batch (db-batch) วิธีตรวจ ใช้เครื่องมือฝั่งอินฟรา (ไม่ต้องใช้โค้ดเกม)
รายละเอียดเพิ่มเติม ถ้า Redis รีสตาร์ตหรือขัดข้องจนแคชว่างทั้งก้อน ก็เกิดเรื่องเดียวกัน ยิ่งระบบที่วางใจแคชจนตั้ง DB ไว้เล็กยิ่งเสี่ยง
แหล่งอ้างอิง 6 รายการ
ID db-long-tx · ผู้รับผิดชอบหลัก พัฒนาเซิร์ฟเวอร์ (ทีมพัฒนาเกม) · ร่วมกับ อินฟรา DB (ทีมอินฟรา)
ถ้าทรานแซกชันหนึ่งเปิดทิ้งไว้นาน จะถือล็อกไว้ตลอด และ DB ล้างข้อมูลเวอร์ชันเก่า (purge) ไม่ได้ ทั้งระบบจึงค่อย ๆ ช้าลง
ทำไม เปิดทรานแซกชันไว้แล้วรอคำตอบจากเซิร์ฟเวอร์อื่น หรือรันคิวรีสรุปผลยาว ๆ บน DB หลักระหว่างให้บริการ → ผลคือ ล็อกที่ถือไว้ไม่ถูกปล่อย และข้อมูลเวอร์ชันเก่าที่ต้องล้างสะสมเรื่อย ๆ → บนหน้าจอ ฟีเจอร์ที่ใช้แถวนั้นไทม์เอาต์, การเซฟและการอ่านข้อมูลโดยรวมช้าลงตลอดหลายชั่วโมง
อาการ อินพุตดีเลย์ , กดไม่ติด/โรลแบ็ค
ปัจจัย ความหน่วง, การหยุดชะงัก
ใครเจอ เฉพาะบางฟีเจอร์, ทั้งเซิร์ฟเวอร์
เกิดเมื่อไร ยิ่งเปิดไว้นานยิ่งเป็น, สุ่มเป็นครั้งคราว
ผู้รับผิดชอบ ผู้รับผิดชอบหลัก พัฒนาเซิร์ฟเวอร์ (ทีมพัฒนาเกม) · ร่วมกับ อินฟรา DB (ทีมอินฟรา)
งานฝั่งทีมพัฒนาเกม ไม่รอ network call หรืออินพุตจากผู้ใช้ภายในทรานแซกชัน, รันคิวรีสรุปผลบน replica
งานฝั่งทีมอินฟรา ตั้ง alert และบังคับปิดทรานแซกชันที่เปิดนาน, จัด replica สำหรับงานสรุปผล, เฝ้าดูการเพิ่มของ undo log และ dead tuple
บนกราฟ ค่อย ๆ สูงขึ้น · ความยาว undo log (History list length), จำนวน dead tuple
จุดที่ต้องดู MySQL หาทรานแซกชันที่เก่าที่สุดจาก trx_started ใน INFORMATION_SCHEMA.INNODB_TRX และดู History list length (ปริมาณ undo log ที่ยังล้างไม่ได้) ในส่วน TRANSACTIONS ของ SHOW ENGINE INNODB STATUS ส่วน PostgreSQL ดู xact_start และเซสชันที่ state เป็น idle in transaction ใน pg_stat_activity และ n_dead_tup ใน pg_stat_user_tables สัญญาณว่าใช่ มีทรานแซกชันที่เปิดมาไม่กี่นาทีถึงหลายชั่วโมง ระหว่างนั้น History list length หรือ n_dead_tup สูงขึ้นเรื่อย ๆ และลดลงเมื่อปิดทรานแซกชันนั้นแล้วการล้าง (purge, VACUUM) ได้ทำงาน สัญญาณว่าไม่ใช่ ไม่มีทรานแซกชันเก่าแต่ช้าโดยรวม: น่าจะเป็น checkpoint (db-checkpoint) หรือดิสก์ วิธีตรวจ ใช้เครื่องมือฝั่งอินฟรา (ไม่ต้องใช้โค้ดเกม)
รายละเอียดเพิ่มเติม DB เก็บเวอร์ชันเก่าไว้เพื่อให้ฝั่งที่อ่านเห็นข้อมูลก่อนถูกแก้ (MVCC) และลบบันทึกนี้ได้ก็ต่อเมื่อทรานแซกชันที่เก่าที่สุดจบแล้ว ถ้าทรานแซกชันเดียวเปิดอยู่หลายชั่วโมง MySQL จะมี undo log สะสม ส่วน PostgreSQL จะมีแถวที่ตายแล้ว (dead tuple) ซึ่ง VACUUM ล้างไม่ได้สะสมอยู่ ส่วน SQL Server บางครั้ง transaction log ไม่ลดขนาดลงจนดิสก์เต็ม
แหล่งอ้างอิง 7 รายการ
คำสั่ง Redis ที่ช้า Redis blocking commands (single-threaded)
ID db-redis-block · ผู้รับผิดชอบหลัก พัฒนาเซิร์ฟเวอร์ (ทีมพัฒนาเกม) · ร่วมกับ อินฟรา DB (ทีมอินฟรา)
Redis ประมวลผลคำสั่งทีละคำสั่ง คำสั่งที่ช้าเพียงคำสั่งเดียวจึงขวางทุกคำขอที่ตามมา
ทำไม ใช้ KEYS ค้นทั้งหมดระหว่างให้บริการ, อ่านหรือลบอันดับหรือลิสต์ที่มีสมาชิกหลายล้านตัวทั้งก้อน → ผลคือ คำขออื่นทั้งหมดต้องรอจนคำสั่งนั้นเสร็จ (หลายสิบ ms ถึงหลายวินาที) → บนหน้าจอ ฟีเจอร์ที่ใช้เซสชัน อันดับ และแคชหยุดแวบพร้อมกัน, ล็อกอินช้า
อาการ ค้าง , อินพุตดีเลย์ , เข้าเกมไม่ได้/โหลดไม่จบ
ปัจจัย การหยุดชะงัก, ความหน่วง
ใครเจอ ทั้งเซิร์ฟเวอร์, เฉพาะบางฟีเจอร์
เกิดเมื่อไร สุ่มเป็นครั้งคราว, เป็นรอบสม่ำเสมอ
ผู้รับผิดชอบ ผู้รับผิดชอบหลัก พัฒนาเซิร์ฟเวอร์ (ทีมพัฒนาเกม) · ร่วมกับ อินฟรา DB (ทีมอินฟรา)
งานฝั่งทีมพัฒนาเกม ใช้ SCAN แทน KEYS, แบ่งคีย์ใหญ่, ลบด้วย UNLINK (ลบเบื้องหลัง), กระจายเวลาหมดอายุที่กระจุกอยู่ในวินาทีเดียวกัน
งานฝั่งทีมอินฟรา เฝ้าดูบันทึกคำสั่งช้า (SLOWLOG), บล็อกคำสั่งอันตรายอย่าง KEYS บนเซิร์ฟเวอร์ที่ให้บริการจริง, ตรวจคีย์ใหญ่เป็นประจำ, ปิด THP และกันหน่วยความจำไว้พอสำหรับ fork, ทำการบันทึก RDB และ AOF บน replica
ตัวเลขที่ควรรู้ คำสั่งทั่วไปใช้ไม่ถึง 1 ms ถ้าจัดการสมาชิกหลายล้านตัวในครั้งเดียว อาจใช้ตั้งแต่หลายร้อย ms ไปจนถึงหลายวินาที
บนกราฟ พุ่งแบบสุ่มเป็นครั้งคราว · ดีเลย์การตอบของ Redis, จำนวนคำสั่งที่ช้า
จุดที่ต้องดู ดูคำสั่งที่เกิน slowlog-log-slower-than ด้วย SLOWLOG GET และเปิด latency monitor (ค่าเริ่มต้นปิด) ด้วย CONFIG SET latency-monitor-threshold แล้วดูดีเลย์แยกตามอีเวนต์ เช่น fork และ expire-cycle ด้วย LATENCY LATEST และ LATENCY DOCTOR ตรวจเวลา fork และคีย์ใหญ่ด้วย latest_fork_usec ใน INFO และ redis-cli --bigkeys สัญญาณว่าใช่ ช่วงที่หยุด SLOWLOG มีคำสั่ง KEYS หรือคำสั่งที่จัดการคีย์ใหญ่ทั้งก้อน หรือ LATENCY บันทึกอีเวนต์ fork หรือ expire-cycle ในช่วงเดียวกันนานตั้งแต่หลายสิบ ms ขึ้นไป สัญญาณว่าไม่ใช่ SLOWLOG และ LATENCY ว่างแต่ช้าเฉพาะฝั่งเซิร์ฟเวอร์เกม: น่าจะเป็นเครือข่ายหรือการรอภายในเซิร์ฟเวอร์เกม (SLOWLOG วัดแค่เวลารันคำสั่ง ไม่รวมเวลารับส่งกับไคลเอนต์) วิธีตรวจ ใช้เครื่องมือฝั่งอินฟรา (ไม่ต้องใช้โค้ดเกม)
รายละเอียดเพิ่มเติม ตอน fork โปรเซสเพื่อสร้างไฟล์บันทึก (RDB snapshot) หรือเขียน AOF ใหม่ ก็หยุดเช่นกัน บนเซิร์ฟเวอร์ปัจจุบันใช้ราว 10 ms ต่อหน่วยความจำ 1 GB ถ้า 30 GB ก็ประมาณ 300 ms ถ้าเปิด huge page (THP) ไว้ หลัง fork การเขียนแต่ละครั้งจะคัดลอก huge page ทั้งหน้า (copy-on-write) ทำให้ทั้งเวลาหยุดและการใช้หน่วยความจำเพิ่มขึ้นมาก จึงมักปิด THP และกันหน่วยความจำเหลือไว้มาก ๆ ตอนที่คีย์จำนวนมากหมดอายุในวินาทีเดียวกัน Redis ก็หยุดแวบเพราะต้องลบคีย์เหล่านั้น
แหล่งอ้างอิง 7 รายการ Diagnosing latency issues Redis เธรดเดียวประมวลผลคำขอตามลำดับ คำสั่งที่ช้าจึงขวางทุกคำขอที่ตามมา, ใช้ SCAN แทน KEYS, fork วัดจริงบนเครื่อง physical และ VM รุ่นใหม่ได้ราว 9–13 ms ต่อ 1 GB, THP ทำให้ดีเลย์และหน่วยความจำพุ่งจากการคัดลอกหลัง fork, คีย์จำนวนมากหมดอายุในวินาทีเดียวกันทำให้หยุด KEYS Redis ใช้บน production ด้วยความระมัดระวังอย่างยิ่ง อาจทำลายประสิทธิภาพบน DB ขนาดใหญ่ได้ (บนโน้ตบุ๊กระดับทั่วไป คีย์ 1,000,000 ตัวใช้ 40 ms) UNLINK Redis การลบแบบ asynchronous ที่ถอดคีย์ออกทันทีแล้วไปคืนหน่วยความจำในเธรดอื่น SLOWLOG Redis log คำสั่งช้าที่บันทึกคำสั่งที่เกิน slowlog-log-slower-than, เวลารันไม่รวม I/O รับส่งกับไคลเอนต์ Redis latency monitoring Redis latency-monitor-threshold ค่าเริ่มต้น 0 (ปิด), LATENCY LATEST และ LATENCY DOCTOR, บันทึกดีเลย์แยกตามอีเวนต์ เช่น fork และ expire-cycle INFO Redis latest_fork_usec: เวลาที่ fork ครั้งล่าสุดใช้ (ไมโครวินาที) Redis CLI Redis --bigkeys: ไล่ดู keyspace เพื่อหาคีย์ใหญ่
ID db-plan-flip · ผู้รับผิดชอบหลัก อินฟรา DB (ทีมอินฟรา) · ร่วมกับ พัฒนาเซิร์ฟเวอร์ (ทีมพัฒนาเกม)
โค้ดเหมือนเดิม แต่ถ้า DB เปลี่ยนวิธีประมวลผลคิวรีเดิม (query plan) คิวรีที่เมื่อวานใช้ 2 ms วันนี้อาจกลายเป็นหลายร้อย ms
ทำไม สถิติอัปเดตอัตโนมัติ, DB รีสตาร์ต หรือการกระจายของข้อมูลเปลี่ยน ทำให้ DB วาง query plan ใหม่ → ผลคือ DB เลือก plan ที่ไม่ใช้อินเด็กซ์ คิวรีเดิมจึงช้าลงหลายสิบถึงหลายร้อยเท่า และ connection ถูกถือครองไว้ → บนหน้าจอ ไม่มี deploy อะไรเลย แต่การโหลดของบางฟีเจอร์ช้าลงทันที และคำขออื่นต้องรอไปด้วย
อาการ อินพุตดีเลย์ , เข้าเกมไม่ได้/โหลดไม่จบ
ปัจจัย ความหน่วง, การหยุดชะงัก
ใครเจอ เฉพาะบางฟีเจอร์, ทั้งเซิร์ฟเวอร์
เกิดเมื่อไร สุ่มเป็นครั้งคราว
ผู้รับผิดชอบ ผู้รับผิดชอบหลัก อินฟรา DB (ทีมอินฟรา) · ร่วมกับ พัฒนาเซิร์ฟเวอร์ (ทีมพัฒนาเกม)
งานฝั่งทีมพัฒนาเกม คิวรีที่จำนวนผลลัพธ์ต่างกันมากตามค่าที่ส่งเข้าไปให้แยกเขียนหรือพิจารณาใช้ plan hint, ออกแบบคิวรีให้ใช้อินเด็กซ์แน่นอน
งานฝั่งทีมอินฟรา เฝ้าดูคิวรีที่ช้าและบันทึก query plan, ตรึง plan ที่ดีไว้ (Query Store ของ SQL Server ฯลฯ), จัดการเวลาอัปเดตสถิติ
บนกราฟ ขึ้นเป็นขั้นบันไดจากจุดหนึ่ง · เวลารันเฉลี่ยแยกตามคิวรี
จุดที่ต้องดู เก็บเวลาเฉลี่ยของคิวรีรูปแบบเดียวกันเป็นระยะแล้วดูแนวโน้ม MySQL คือ AVG_TIMER_WAIT ใน events_statements_summary_by_digest, PostgreSQL คือ mean_exec_time ใน pg_stat_statements (12 ลงไปคือ mean_time) เทียบ query plan ก่อนและหลังช้าด้วย EXPLAIN หรือ auto_explain ของ PostgreSQL ส่วน SQL Server ใช้หน้า Regressed Queries ของ Query Store สัญญาณว่าใช่ ในช่วงที่ไม่มี deploy เวลาเฉลี่ยของคิวรีหนึ่งขึ้นเป็นขั้นบันไดหลายสิบเท่า จุดนั้นตรงกับการอัปเดตสถิติหรือการรีสตาร์ต DB และ query plan เปลี่ยนไปแล้ว สัญญาณว่าไม่ใช่ query plan เหมือนเดิมแต่ช้าลง: น่าจะเป็นข้อมูลที่เพิ่มขึ้น, การรอล็อก (db-hot-row) หรือดิสก์ วิธีตรวจ ใช้เครื่องมือฝั่งอินฟรา (ไม่ต้องใช้โค้ดเกม)
รายละเอียดเพิ่มเติม SQL Server จะใช้ plan ที่วางตามค่าที่เข้ามาครั้งแรกซ้ำ (parameter sniffing) ถ้า plan ที่วางจากตัวละครใหม่ที่มีไอเทมไม่กี่ชิ้นถูกใช้กับตัวละครเก่าที่มีไอเทมหลายหมื่นชิ้น จะช้าลงมาก และกรณีกลับกันก็พบบ่อย บางครั้งรีสตาร์ตแล้ว plan ถูกล้างจนกลับมาปกติ ก่อนจะแย่ลงอีกครั้ง
แหล่งอ้างอิง 7 รายการ
ID db-ddl-lock · ผู้รับผิดชอบหลัก อินฟรา DB (ทีมอินฟรา) · ร่วมกับ พัฒนาเซิร์ฟเวอร์ (ทีมพัฒนาเกม)
ถ้าเพิ่มคอลัมน์หรืออินเด็กซ์ให้ตารางระหว่างให้บริการ ล็อกที่ต้องใช้เพียงชั่วครู่ตัวเดียวอาจทำให้ทุกคำขอที่ใช้ตารางนั้นต้องรอ
ทำไม เพิ่มคอลัมน์หรืออินเด็กซ์ให้ตารางที่ใช้งานอยู่ผ่าน hotfix → ผลคือ การเปลี่ยนสคีมารอทรานแซกชันยาวที่เปิดอยู่ก่อน และทุกคำขอที่ตามมาต้องรอการเปลี่ยนสคีมานั้น → บนหน้าจอ ฟีเจอร์ที่ใช้ตารางนั้น (กระเป๋า, จดหมาย ฯลฯ) ค้างทั้งหมดแล้วไทม์เอาต์
อาการ อินพุตดีเลย์ , กดไม่ติด/โรลแบ็ค , เข้าเกมไม่ได้/โหลดไม่จบ
ปัจจัย การหยุดชะงัก
ใครเจอ เฉพาะบางฟีเจอร์, ทั้งเซิร์ฟเวอร์
เกิดเมื่อไร สุ่มเป็นครั้งคราว, หลังล็อกอิน/หลังปิดปรับปรุง
ผู้รับผิดชอบ ผู้รับผิดชอบหลัก อินฟรา DB (ทีมอินฟรา) · ร่วมกับ พัฒนาเซิร์ฟเวอร์ (ทีมพัฒนาเกม)
งานฝั่งทีมพัฒนาเกม hotfix ที่มีการเปลี่ยนสคีมาให้นัดเวลากับอินฟรา DB, deploy โค้ดที่ทำงานได้แม้ยังไม่มีคอลัมน์ใหม่ก่อน
งานฝั่งทีมอินฟรา ตั้งขีดจำกัดการรอล็อกให้สั้นแล้วลองใหม่เมื่อล้มเหลว, รันตอนที่ไม่มีทรานแซกชันยาว, ใช้เครื่องมือ online schema change, ตารางใหญ่ให้ทำช่วงปิดปรับปรุง
บนกราฟ ขึ้นเป็นขั้นบันไดจากจุดหนึ่ง · จำนวนเซสชันที่รอล็อก, ดีเลย์ของคิวรีบนตารางนั้น
จุดที่ต้องดู MySQL นับเซสชันที่ State เป็น Waiting for table metadata lock ใน SHOW PROCESSLIST และหาเซสชันที่ขวางอยู่ (blocking_pid) ด้วย sys.schema_table_lock_waits ส่วน PostgreSQL ดูคำขอที่ granted เป็น false และ AccessExclusiveLock ใน pg_locks และหาเซสชันที่ขวางอยู่ด้วย pg_blocking_pids() สัญญาณว่าใช่ ตั้งแต่เวลาที่เริ่มเปลี่ยนสคีมา ทุกคิวรีที่ใช้ตารางนั้นกองรอล็อก และหัวแถวคือทรานแซกชันที่ยังไม่จบหรือคำสั่งเปลี่ยนสคีมา สัญญาณว่าไม่ใช่ การรอกระจุกเฉพาะบางแถว และแถวอื่นในตารางเดียวกันยังประมวลผลได้ดี: น่าจะเป็น hot row (db-hot-row) วิธีตรวจ ใช้เครื่องมือฝั่งอินฟรา (ไม่ต้องใช้โค้ดเกม)
รายละเอียดเพิ่มเติม ตอนเปลี่ยนสคีมา MySQL ถือ metadata lock ส่วน PostgreSQL ถือล็อกตารางที่แรงที่สุดชั่วครู่ แม้ตัวการเปลี่ยนจะเสร็จในพริบตา แต่ถ้ามีทรานแซกชันที่ยังไม่จบอยู่ข้างหน้าแม้แต่ตัวเดียว ทุกคำขอที่ตามมาจะต้องรอ
แหล่งอ้างอิง 8 รายการ
L13 สถาปัตยกรรมเซิร์ฟเวอร์และการดูแลระบบ
13 สาเหตุ · บทในฉบับหลัก
ID in-gateway · ผู้รับผิดชอบหลัก พัฒนาเซิร์ฟเวอร์ (ทีมพัฒนาเกม) · ร่วมกับ อินฟราเซิร์ฟเวอร์ (ทีมอินฟรา), พัฒนาไคลเอนต์ (ทีมพัฒนาเกม)
ถ้าวางเซิร์ฟเวอร์คั่นกลางระหว่างไคลเอนต์กับเซิร์ฟเวอร์เกม ทุกครั้งที่ผ่านจะมีเวลาประมวลผลเพิ่มขึ้น และเซิร์ฟเวอร์ตัวนั้นจะกลายเป็น single point of failure (จุดเดียวที่ล่มแล้วกระทบทั้งระบบ)
ทำไม โครงสร้างแบบ ไคลเอนต์ ↔ เกตเวย์ ↔ เซิร์ฟเวอร์เกม → ผลคือ มีเวลาประมวลผลและเวลารอที่เซิร์ฟเวอร์คั่นกลางเพิ่มเข้ามา ถ้าโหลดเกินจะกระทบทุกคน → บนหน้าจอ ปิงสูงขึ้นทั้งหมด ถ้าเกตเวย์ล่ม ผู้เล่นทุกคนที่ผ่านเกตเวย์นั้นหลุด
อาการ อินพุตดีเลย์ , หลุด
ปัจจัย ความหน่วง, การหยุดชะงัก
ใครเจอ ทั้งเซิร์ฟเวอร์
เกิดเมื่อไร ตอนคนแห่มารวมกัน, ตลอดเวลา
ผู้รับผิดชอบ ผู้รับผิดชอบหลัก พัฒนาเซิร์ฟเวอร์ (ทีมพัฒนาเกม) · ร่วมกับ อินฟราเซิร์ฟเวอร์ (ทีมอินฟรา), พัฒนาไคลเอนต์ (ทีมพัฒนาเกม)
งานฝั่งทีมพัฒนาเกม เซิร์ฟเวอร์: ออกแบบให้เพิ่มเกตเวย์เป็นหลายเครื่องได้, ออกแบบให้เมื่อเกตเวย์ล่มแล้วต่อเข้าเกตเวย์อื่นใหม่ ตัวละครยังอยู่ต่อจากเดิม (เชื่อมต่อเซสชันใหม่) ไคลเอนต์: เชื่อมต่อใหม่อัตโนมัติเมื่อเกตเวย์หลุด
งานฝั่งทีมอินฟรา ขยายเกตเวย์แนวนอน (เพิ่มจำนวนเครื่อง), มอนิเตอร์ CPU, จำนวนการเชื่อมต่อ และดีเลย์การประมวลผลของเกตเวย์แต่ละตัว
ตัวเลขที่ควรรู้ เพราะอยู่ในดาต้าเซ็นเตอร์เดียวกัน ปกติการผ่านแต่ละครั้งใช้เวลาไม่ถึง 1 ms แต่ถ้าเกตเวย์โหลดเกินจะเพิ่มเป็นหลายสิบถึงหลายร้อย ms
บนกราฟ สูงตามจำนวนคนและโหลด · ดีเลย์การประมวลผลของเกตเวย์, CPU/จำนวนการเชื่อมต่อของเกตเวย์
จุดที่ต้องดู CPU และจำนวนการเชื่อมต่อของเกตเวย์ กับ Recv-Q ของซ็อกเก็ตบนเกตเวย์ (ss, netstat), ส่วนต่างของดีเลย์ก่อนและหลังผ่านเกตเวย์ ถ้าเป็นการเรียก HTTP/gRPC ที่ผ่าน service mesh ให้เทียบเมตริกมาตรฐานของ Istio istio_request_duration_milliseconds แยกฝั่งผู้ส่ง (reporter=source) กับฝั่งผู้รับ (reporter=destination) สัญญาณว่าใช่ เวลาประมวลผลของเซิร์ฟเวอร์เกมเท่าเดิม แต่ดีเลย์ช่วงเกตเวย์เพิ่มขึ้นอย่างเดียว และช่วงนั้น CPU ของเกตเวย์อิ่มตัวหรือ Recv-Q สะสม สัญญาณว่าไม่ใช่ เส้นทางที่ไม่ผ่านเกตเวย์ (ต่อตรง, เกตเวย์อื่น) ก็ช้าเท่ากัน: น่าจะเป็นที่เครือข่ายหรือเซิร์ฟเวอร์เกม วิธีตรวจ ใช้เครื่องมือฝั่งอินฟรา (ไม่ต้องใช้โค้ดเกม)
รายละเอียดเพิ่มเติม ถ้าใช้ service mesh (เช่น Istio) sidecar proxy (Envoy) ที่ติดอยู่ข้างเซิร์ฟเวอร์ทุกตัวจะเพิ่มเข้ามาอีกหนึ่งขั้น คำขอระหว่างเซอร์วิสต้องผ่าน sidecar ฝั่งผู้ส่งแล้วจึงผ่าน sidecar ฝั่งผู้รับ และยิ่งเพิ่มฟีเจอร์ให้พร็อกซี เช่น การเก็บ log และเมตริก เวลาประมวลผลและเวลารอก็ยิ่งเพิ่มขึ้น
กรณีจริง Riot Games 2020: โฮสต์ edge ของเซิร์ฟเวอร์ League of Legends ยุโรปและบราซิลโหลดเกิน
แหล่งอ้างอิง 7 รายการ
ID in-zone-transfer · ผู้รับผิดชอบหลัก พัฒนาเซิร์ฟเวอร์ (ทีมพัฒนาเกม) · ร่วมกับ อินฟราเซิร์ฟเวอร์ (ทีมอินฟรา)
เมื่อเข้าพื้นที่หรือดันเจี้ยนอื่น ขั้นตอนส่งข้อมูลตัวละครไปยังเซิร์ฟเวอร์อื่นทำให้เกิดดีเลย์และความล้มเหลว
ทำไม เข้าดันเจี้ยนหรือข้ามทวีป ทำให้เซิร์ฟเวอร์ที่ดูแลตัวละครเปลี่ยนไป → ผลคือ บันทึก → ส่งต่อ → โหลด ถ้าเซิร์ฟเวอร์ปลายทางแน่นหรือไม่มีอินสแตนซ์ดันเจี้ยนว่าง ต้องรอ → บนหน้าจอ โหลดนาน, เข้าไม่สำเร็จ, หลุดระหว่างย้าย
อาการ เข้าเกมไม่ได้/โหลดไม่จบ , ค้าง , หลุด , ดีดกลับ
ปัจจัย ความหน่วง, การหยุดชะงัก
ใครเจอ เราคนเดียว, บางจุด/บางแชนแนล
เกิดเมื่อไร ระหว่างเดินทาง/ย้ายแมพ
ผู้รับผิดชอบ ผู้รับผิดชอบหลัก พัฒนาเซิร์ฟเวอร์ (ทีมพัฒนาเกม) · ร่วมกับ อินฟราเซิร์ฟเวอร์ (ทีมอินฟรา)
งานฝั่งทีมพัฒนาเกม ลดข้อมูลที่ต้องส่งต่อ, จองเซิร์ฟเวอร์ปลายทางไว้ล่วงหน้า, ถ้าล้มเหลวให้กลับไปที่เดิม
งานฝั่งทีมอินฟรา มอนิเตอร์จำนวนอินสแตนซ์ว่างที่เหลือของเซิร์ฟเวอร์ดันเจี้ยนและโซน, เตรียมจำนวนเครื่องให้พอก่อนช่วงพีค
บนกราฟ สูงตามจำนวนคนและโหลด · เวลาที่ใช้ย้ายโซน, จำนวนครั้งที่ล้มเหลว
จุดที่ต้องดู เวลาที่ใช้ในแต่ละขั้นของการส่งต่อ (บันทึก, ส่งต่อ, โหลด) และสาเหตุที่ล้มเหลวที่เซิร์ฟเวอร์บันทึกไว้, จำนวนผู้เล่นและจำนวนอินสแตนซ์ว่างของเซิร์ฟเวอร์ปลายทาง สัญญาณว่าใช่ ช่วงที่มีการแจ้งว่าโหลดนานหรือเข้าไม่สำเร็จ เวลาส่งต่อเพิ่มขึ้นหรือความล้มเหลวกระจุกตัว และเซิร์ฟเวอร์ปลายทางแน่นหรืออินสแตนซ์ว่างหมด สัญญาณว่าไม่ใช่ ส่งต่อเสร็จเร็วแต่เกมค้างหลังไปถึง: น่าจะเป็น spawn ทะลักเมื่อเข้าพื้นที่คนหนาแน่น หรือการโหลดฝั่งไคลเอนต์ วิธีตรวจ ต้องมี log หรือเมตริกจากเซิร์ฟเวอร์/ไคลเอนต์เกม
รายละเอียดเพิ่มเติม แม้เป็นโลกแบบ seamless ที่เดินต่อกันโดยไม่มีหน้าโหลด เมื่อข้ามขอบเขตของเซิร์ฟเวอร์ เซิร์ฟเวอร์ที่ดูแลก็เปลี่ยนเช่นกัน ใกล้ขอบเขตจึงอาจหยุดแวบหรือโดนดีดกลับไปด้านหลังได้
แหล่งอ้างอิง 1 รายการ
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 ขัดข้อง และการกู้คืนที่ยืดเยื้อ
แหล่งอ้างอิง 4 รายการ
ID in-subservice · ผู้รับผิดชอบหลัก พัฒนาเซิร์ฟเวอร์ (ทีมพัฒนาเกม) · ร่วมกับ อินฟราเซิร์ฟเวอร์ (ทีมอินฟรา)
ถ้าเซิร์ฟเวอร์ที่รันแยกจากเซิร์ฟเวอร์เกม เช่น แชต, ปาร์ตี้ หรือตลาดประมูล ขัดข้อง จะใช้งานไม่ได้เฉพาะฟีเจอร์นั้น
ทำไม เซิร์ฟเวอร์เฉพาะฟีเจอร์ช้าลงหรือล่ม → ผลคือ เฉพาะคำขอของฟีเจอร์นั้นที่ไม่ได้รับคำตอบ → บนหน้าจอ แชตไม่ได้, เชิญปาร์ตี้แล้วไม่มีอะไรเกิดขึ้น, ตลาดซื้อขายโหลดไม่จบ (การต่อสู้ปกติ)
อาการ กดไม่ติด/โรลแบ็ค , เข้าเกมไม่ได้/โหลดไม่จบ
ปัจจัย การหยุดชะงัก, แพ็กเก็ตหาย
ใครเจอ เฉพาะบางฟีเจอร์
เกิดเมื่อไร สุ่มเป็นครั้งคราว, ตอนคนแห่มารวมกัน
ผู้รับผิดชอบ ผู้รับผิดชอบหลัก พัฒนาเซิร์ฟเวอร์ (ทีมพัฒนาเกม) · ร่วมกับ อินฟราเซิร์ฟเวอร์ (ทีมอินฟรา)
งานฝั่งทีมพัฒนาเกม ออกแบบให้เกมเล่นต่อได้แม้ฟีเจอร์นั้นล้มเหลว, แสดงสถานะแยกตามฟีเจอร์, ไม่รวมหลายฟีเจอร์ไว้ที่เซิร์ฟเวอร์กลางเครื่องเดียว
งานฝั่งทีมอินฟรา health check และ alert แยกตามเซิร์ฟเวอร์เสริม, ทำระบบสำรอง (redundancy) และรีสตาร์ตอัตโนมัติ
บนกราฟ การเชื่อมต่อหลุดพร้อมกัน · อัตราความสำเร็จของคำขอแยกตามฟีเจอร์, จำนวนการเชื่อมต่อ/health check ของเซิร์ฟเวอร์เสริม
จุดที่ต้องดู health check, สถานะโปรเซส และจำนวนการเชื่อมต่อของเซิร์ฟเวอร์เสริมแต่ละตัว เช่น แชต, ปาร์ตี้ และตลาดประมูล, อัตราความสำเร็จและเวลาตอบสนองของคำขอแยกตามฟีเจอร์ ถ้าอยู่หลังโหลดบาลานเซอร์ ให้ดู UnHealthyHostCount ของ target group สัญญาณว่าใช่ เฉพาะเซิร์ฟเวอร์ที่ดูแลฟีเจอร์ที่ถูกแจ้งมาไม่ผ่าน health check หรือจำนวนการเชื่อมต่อดิ่งลง ขณะที่ทิกของเซิร์ฟเวอร์เกมและการต่อสู้ปกติ สัญญาณว่าไม่ใช่ หลายฟีเจอร์หยุดพร้อมกัน: น่าจะเป็นเซิร์ฟเวอร์กลางที่ส่งต่อฟีเจอร์เหล่านั้นร่วมกัน หรือความล้มเหลวแบบลูกโซ่ วิธีตรวจ ใช้เครื่องมือฝั่งอินฟรา (ไม่ต้องใช้โค้ดเกม)
รายละเอียดเพิ่มเติม ถ้าใช้โครงสร้างที่เซิร์ฟเวอร์กลางเครื่องเดียว (เซิร์ฟเวอร์ world/manager) เป็นตัวกลางส่งต่อทั้งปาร์ตี้, กิลด์, กระซิบ และการย้ายข้ามเซิร์ฟเวอร์ เพียงเซิร์ฟเวอร์นั้นช้าลงเครื่องเดียว หลายฟีเจอร์จะหยุดทำงานพร้อมกัน
แหล่งอ้างอิง 3 รายการ
ID in-deploy · ผู้รับผิดชอบหลัก พัฒนาเซิร์ฟเวอร์ (ทีมพัฒนาเกม) · ร่วมกับ อินฟราเซิร์ฟเวอร์ (ทีมอินฟรา)
ถ้ารีสตาร์ตเซิร์ฟเวอร์เพื่ออัปเดตโดยไม่ย้ายการเชื่อมต่อ ผู้เล่นที่อยู่บนเซิร์ฟเวอร์นั้นจะหลุด และการบันทึกข้อมูลก่อนปิดกับการเชื่อมต่อใหม่จะทะลักเข้ามาพร้อมกัน
ทำไม deploy hotfix โดยรีสตาร์ตเซิร์ฟเวอร์ทีละเครื่องตามลำดับ → ผลคือ ปิดเซิร์ฟเวอร์โดยไม่ย้ายการเชื่อมต่อไปเซิร์ฟเวอร์อื่น การบันทึกของผู้เล่นทุกคนบนเซิร์ฟเวอร์นั้นจึงไปกองที่ DB → บนหน้าจอ หลุดโดยไม่มีประกาศ, คนแห่เชื่อมต่อใหม่
อาการ หลุด , เข้าเกมไม่ได้/โหลดไม่จบ , อินพุตดีเลย์
ปัจจัย การหยุดชะงัก
ใครเจอ ทั้งเซิร์ฟเวอร์, บางจุด/บางแชนแนล
เกิดเมื่อไร สุ่มเป็นครั้งคราว, หลังล็อกอิน/หลังปิดปรับปรุง
ผู้รับผิดชอบ ผู้รับผิดชอบหลัก พัฒนาเซิร์ฟเวอร์ (ทีมพัฒนาเกม) · ร่วมกับ อินฟราเซิร์ฟเวอร์ (ทีมอินฟรา)
งานฝั่งทีมพัฒนาเกม ทำฟีเจอร์ drain (กันเฉพาะการเชื่อมต่อใหม่ แล้วรอจนคนเดิมออกไป), ย้ายตัวละครไปเซิร์ฟเวอร์อื่น, ทยอยบันทึกก่อนปิด, หลังรีสตาร์ตให้โหลดแคชและ JIT warm-up ให้เสร็จก่อนแจ้งว่าพร้อม, hot reload ให้อ่านไว้ล่วงหน้าในเธรดแยกแล้วสลับทีเดียวระหว่างทิก
งานฝั่งทีมอินฟรา ให้เครื่องมือ deploy รอ drain ทีละเครื่องก่อนรีสตาร์ต, ให้เซิร์ฟเวอร์ที่รีสตาร์ตแล้วรับทราฟฟิกหลังยืนยันว่าพร้อม (warm-up เสร็จ), ประกาศเวลา deploy
ตัวเลขที่ควรรู้ ถ้าเซิร์ฟเวอร์หนึ่งเครื่องมี 5,000 คน ในไม่กี่วินาทีก่อนปิดจะมีการบันทึก 5,000 รายการพุ่งเข้า DB พร้อมกัน
บนกราฟ การเชื่อมต่อหลุดพร้อมกัน · จำนวนการเชื่อมต่อแยกตามเซิร์ฟเวอร์, จำนวนการเขียน DB
จุดที่ต้องดู วางประวัติงานของเครื่องมือ deploy (เวลารีสตาร์ตของแต่ละเซิร์ฟเวอร์) เป็นเส้นแนวตั้ง (annotation) บนกราฟจำนวนการเชื่อมต่อ, จำนวนการหลุด, การเขียน DB และคำขอล็อกอิน สัญญาณว่าใช่ จำนวนการเชื่อมต่อของแต่ละเซิร์ฟเวอร์ดิ่งลงทีละเครื่องตามเวลารีสตาร์ต การเขียน DB พุ่งก่อนหน้านั้น และคำขอล็อกอินพุ่งหลังจากนั้น สัญญาณว่าไม่ใช่ เวลาที่หลุดไม่ตรงกับประวัติ deploy หรือรีสตาร์ต: น่าจะเป็นเซิร์ฟเวอร์แครชหรืออุปกรณ์เครือข่าย วิธีตรวจ ใช้เครื่องมือฝั่งอินฟรา (ไม่ต้องใช้โค้ดเกม)
รายละเอียดเพิ่มเติม ช่วงไม่กี่นาทีหลังเปิดใหม่ก็ยังช้า เพราะแคชว่างจึงมีการอ่าน DB ทะลักเข้ามา และเซิร์ฟเวอร์ Java หรือ C# ยังไม่เสร็จขั้นตอน optimize โค้ดระหว่างรัน (JIT warm-up) งานเดิมจึงใช้เวลามากขึ้น การโหลดสคริปต์หรือตารางข้อมูลใหม่โดยไม่ปิดเซิร์ฟเวอร์ (hot reload) ก็ทำให้ทิกหยุดระหว่างอ่าน จึงเกิดการหยุดสั้น ๆ
แหล่งอ้างอิง 3 รายการ
ID in-autoscale · ผู้รับผิดชอบหลัก อินฟราเซิร์ฟเวอร์ (ทีมอินฟรา) · ร่วมกับ พัฒนาเซิร์ฟเวอร์ (ทีมพัฒนาเกม)
เมื่อคนแห่เข้ามา ระบบจะเพิ่มเซิร์ฟเวอร์อัตโนมัติ แต่ต้องใช้เวลาเตรียมหลายนาที และระหว่างนั้นเซิร์ฟเวอร์เดิมรับโหลดเกิน
ทำไม อีเวนต์เริ่มแล้วผู้เล่นแห่เชื่อมต่อเข้ามา → ผลคือ กว่าเซิร์ฟเวอร์ใหม่จะเปิดและพร้อมใช้ต้องใช้เวลาหลายนาที → บนหน้าจอ ไม่กี่นาทีแรกหลังอีเวนต์เริ่ม เกิดสโลว์โมชั่นและเข้าเกมไม่ได้
อาการ สโลว์โมชั่น , เข้าเกมไม่ได้/โหลดไม่จบ
ปัจจัย การหยุดชะงัก
ใครเจอ ทั้งเซิร์ฟเวอร์
เกิดเมื่อไร ตอนคนแห่มารวมกัน, หลังล็อกอิน/หลังปิดปรับปรุง
ผู้รับผิดชอบ ผู้รับผิดชอบหลัก อินฟราเซิร์ฟเวอร์ (ทีมอินฟรา) · ร่วมกับ พัฒนาเซิร์ฟเวอร์ (ทีมพัฒนาเกม)
งานฝั่งทีมพัฒนาเกม กระจายผู้เล่นตามแชนแนล (คนที่อยู่ในแชนแนลที่แน่นอยู่แล้วย้ายไปเซิร์ฟเวอร์ใหม่ไม่ได้), ลดเวลาเริ่มทำงานและเวลาโหลดข้อมูลของเซิร์ฟเวอร์ใหม่
งานฝั่งทีมอินฟรา ขยายไว้ก่อนอีเวนต์, เตรียมเซิร์ฟเวอร์สำรองที่ warm-up แล้ว, เวลาลดเครื่องให้รอคนที่เหลือออกไปก่อนแล้วค่อยปิด
ตัวเลขที่ควรรู้ ใช้เวลา 1 นาทีถึงไม่กี่นาทีกว่าจะตรวจพบโหลด (เพราะดูค่าเฉลี่ยของเมตริกหลายนาที) และอีกหลายนาทีเพื่อเปิดเซิร์ฟเวอร์ใหม่ อ่านข้อมูลเกม และเติมแคช
บนกราฟ พุ่งทันทีหลังเปิดเซิร์ฟ/ปิดปรับปรุง · จำนวนอินสแตนซ์, อัตราการใช้ CPU, จำนวนผู้เล่นที่รอเข้าเกม
จุดที่ต้องดู วางประวัติกิจกรรมของ autoscaling (เวลาที่ตัดสินใจขยาย, เวลาที่อินสแตนซ์ใหม่เริ่มให้บริการ) บนกราฟอัตราการใช้ CPU และจำนวนการเชื่อมต่อ บน AWS ใช้เมตริกของ Auto Scaling group (ต้องเปิดก่อนจึงจะเห็น) GroupDesiredCapacity (จำนวนเป้าหมาย), GroupPendingInstances (กำลังเตรียม), GroupInServiceInstances (กำลังให้บริการ) สัญญาณว่าใช่ หลังการเชื่อมต่อพุ่ง มีหลายนาทีที่เพิ่มขึ้นเฉพาะจำนวนเป้าหมายและอินสแตนซ์ที่กำลังเตรียม ขณะที่ CPU ของเซิร์ฟเวอร์เดิมชนเพดาน แล้วอาการคลายลงตั้งแต่ตอนที่จำนวนอินสแตนซ์ที่ให้บริการเพิ่มขึ้น สัญญาณว่าไม่ใช่ อินสแตนซ์ใหม่เข้ามาแล้วยังช้า: น่าจะเป็นสาเหตุที่ไม่เกี่ยวกับจำนวนเซิร์ฟเวอร์ (ทรัพยากรที่ใช้ร่วมกันอย่าง DB, ความล้มเหลวแบบลูกโซ่) วิธีตรวจ ใช้เครื่องมือฝั่งอินฟรา (ไม่ต้องใช้โค้ดเกม)
รายละเอียดเพิ่มเติม autoscaling มักใช้กับส่วนที่แค่ให้เซิร์ฟเวอร์ใหม่รับคนใหม่ก็พอ เช่น ล็อกอิน, เกตเวย์ และดันเจี้ยน ตอนลดเครื่องก็เกิดปัญหาได้ ถ้าลดเซิร์ฟเวอร์ตอนเช้ามืดที่คนบางตาแล้วปิดเลยโดยไม่รอคนที่เหลือออก คนเหล่านั้นจะหลุด
กรณีจริง AWS 2021: เครือข่ายภายในของ AWS us-east-1 แออัด AWS 2025: DNS ของ DynamoDB ใน AWS us-east-1 ขัดข้อง และการกู้คืนที่ยืดเยื้อ
แหล่งอ้างอิง 4 รายการ
ID in-monitoring · ผู้รับผิดชอบหลัก พัฒนาเซิร์ฟเวอร์ (ทีมพัฒนาเกม) · ร่วมกับ อินฟราเซิร์ฟเวอร์ (ทีมอินฟรา)
เมื่อเกิดเหตุขัดข้อง log จะพุ่งขึ้นมาก และเซิร์ฟเวอร์ที่ส่ง log แบบ synchronous จะยิ่งช้าลงเพราะ log
ทำไม เกิด error แล้วปริมาณ log และเมตริกที่ส่งออกพุ่ง → ผลคือ log collector รับไม่ทัน เซิร์ฟเวอร์ที่ส่งแบบ synchronous ต้องรอ → บนหน้าจอ ตอนเกิดเหตุขัดข้อง อาการกระตุกและค้างยิ่งหนักขึ้นเพราะ log
อาการ กระตุก , ค้าง
ปัจจัย การหยุดชะงัก
ใครเจอ ทั้งเซิร์ฟเวอร์
เกิดเมื่อไร ตอนคนแห่มารวมกัน, สุ่มเป็นครั้งคราว
ผู้รับผิดชอบ ผู้รับผิดชอบหลัก พัฒนาเซิร์ฟเวอร์ (ทีมพัฒนาเกม) · ร่วมกับ อินฟราเซิร์ฟเวอร์ (ทีมอินฟรา)
งานฝั่งทีมพัฒนาเกม ส่งแบบ async, ทำ sampling, ทิ้งเมื่อบัฟเฟอร์ล้น, รวม log ของ error เดียวกันแล้วส่งครั้งเดียว
งานฝั่งทีมอินฟรา เตรียมความจุของ log collector โดยคิดจากปริมาณที่พุ่งตอนเกิดเหตุขัดข้อง, ตั้ง alert เมื่อ log collector มีงานสะสม
บนกราฟ พุ่งแบบสุ่มเป็นครั้งคราว · ปริมาณ log ที่ส่ง, คิวของ log collector
จุดที่ต้องดู จำนวนบรรทัดและไบต์ของ log ต่อวินาทีบนเซิร์ฟเวอร์ กับคิวและจำนวนที่ถูกทิ้งของ agent เก็บ log ดูคู่กับเวลาต่อทิก ถ้ามีเธรดที่หยุดอยู่ ใช้ bcc offcputime -p ดูว่ารอที่การเขียนหรือส่ง log หรือไม่ สัญญาณว่าใช่ ช่วงที่ทิกพุ่ง ปริมาณ log พุ่งเป็นหลายสิบเท่าของปกติ และเวลารอของเธรดเกมกระจุกอยู่ที่ call stack ของการเขียนหรือส่ง log สัญญาณว่าไม่ใช่ ปริมาณ log เท่าปกติ หรือเธรดเกมไม่ได้รอที่ฝั่ง log: log ที่พุ่งเป็นแค่ผลของเหตุขัดข้อง ให้หาสาเหตุที่ทำให้เกิด error แรกแยกต่างหาก วิธีตรวจ ใช้เครื่องมือฝั่งอินฟรา (ไม่ต้องใช้โค้ดเกม)
แหล่งอ้างอิง 3 รายการ Logging in C# Microsoft เมธอด log ของ .NET เป็นแบบ synchronous ถ้าที่เก็บช้า แนะนำให้เขียนลงที่เก็บที่เร็วก่อนแล้วค่อยย้ายทีหลัง Asynchronous loggers Apache Software Foundation async logging ดูดซับ log ที่พุ่งช่วงสั้น ๆ ด้วยคิว แต่ถ้าปลายทาง (output) ช้าต่อเนื่อง คิวจะเต็มแล้วความเร็วลดลงเหลือเท่าปลายทางที่ช้าที่สุด หรือทิ้ง log ตามนโยบาย (Discard) Demonstrations of offcputime, the Linux eBPF/bcc version IO Visor รวมเวลาที่เธรดหยุดอยู่นอก CPU (off-CPU) แยกตาม call stack, -p ระบุโปรเซส
ID in-clock-skew · ผู้รับผิดชอบหลัก อินฟราเซิร์ฟเวอร์ (ทีมอินฟรา) · ร่วมกับ พัฒนาเซิร์ฟเวอร์ (ทีมพัฒนาเกม)
ถ้านาฬิกาของแต่ละเซิร์ฟเวอร์ต่างกันเล็กน้อย การตัดสินคูลดาวน์, บัฟ และเวลาเริ่มอีเวนต์จะไม่ตรงกันระหว่างเซิร์ฟเวอร์
ทำไม นาฬิกาของเซิร์ฟเวอร์ที่การซิงก์เวลาหยุดทำงาน ห่างจากเซิร์ฟเวอร์อื่นหลายร้อย ms ถึงหลายวินาที → ผลคือ ถ้าส่งเวลาสัมบูรณ์ เช่น เวลาที่บัฟหมด ข้ามเซิร์ฟเวอร์ การตัดสินจะคลาดเคลื่อน → บนหน้าจอ ย้ายเซิร์ฟเวอร์แล้วบัฟหายไป หรือคูลดาวน์กลับมานับใหม่
อาการ กดไม่ติด/โรลแบ็ค
ปัจจัย ความหน่วง
ใครเจอ เราคนเดียว
เกิดเมื่อไร ระหว่างเดินทาง/ย้ายแมพ
ผู้รับผิดชอบ ผู้รับผิดชอบหลัก อินฟราเซิร์ฟเวอร์ (ทีมอินฟรา) · ร่วมกับ พัฒนาเซิร์ฟเวอร์ (ทีมพัฒนาเกม)
งานฝั่งทีมพัฒนาเกม ส่งเวลาที่เหลือระหว่างเซิร์ฟเวอร์ แทนเวลาสัมบูรณ์
งานฝั่งทีมอินฟรา มอนิเตอร์การซิงก์เวลา (NTP, chrony), ตั้ง alert เมื่อนาฬิการะหว่างเซิร์ฟเวอร์ต่างกัน
ตัวเลขที่ควรรู้ ถ้าการซิงก์เวลา (NTP, chrony) ปกติ เซิร์ฟเวอร์ในดาต้าเซ็นเตอร์เดียวกันมักต่างกันไม่เกินไม่กี่ ms แต่ถ้าการซิงก์หยุด หรือ VM หยุดไปนานแล้วกลับมาทำงาน จะห่างกันหลายร้อย ms ถึงหลายวินาที
บนกราฟ ค่อย ๆ สูงขึ้น · offset ของนาฬิกาแยกตามเซิร์ฟเวอร์
จุดที่ต้องดู รวบรวม System time (ส่วนต่างระหว่างนาฬิการะบบกับนาฬิกา NTP), Last offset และ Ref time (เวลาที่นำค่าวัดล่าสุดจากแหล่งเวลามาใช้) จาก chronyc tracking ของแต่ละเซิร์ฟเวอร์มาเทียบกัน สัญญาณว่าใช่ offset ของเซิร์ฟเวอร์ที่มีปัญหาห่างจากเซิร์ฟเวอร์อื่นตั้งแต่หลายร้อย ms ขึ้นไป หรือ Ref time หยุดอยู่ที่เวลานานมาแล้ว และการตัดสินคลาดเคลื่อนเกิดเฉพาะเมื่อย้ายเข้าออกเซิร์ฟเวอร์นั้น สัญญาณว่าไม่ใช่ offset ของทุกเซิร์ฟเวอร์อยู่ในหลักหน่วย ms: น่าจะเป็นการคำนวณเวลาฝั่งเกม หรือซิงก์นาฬิกาคลาดเคลื่อนฝั่งไคลเอนต์ วิธีตรวจ ใช้เครื่องมือฝั่งอินฟรา (ไม่ต้องใช้โค้ดเกม)
รายละเอียดเพิ่มเติม กรณีที่นาฬิกาของเซิร์ฟเวอร์เครื่องหนึ่งกระโดดไปข้างหน้าหรือถอยหลังทีเดียว อธิบายไว้ในการ์ด “นาฬิการะบบกระโดด (NTP step)” ของชั้น OS ของเซิร์ฟเวอร์
แหล่งอ้างอิง 4 รายการ
ID in-bots · ผู้รับผิดชอบหลัก พัฒนาเซิร์ฟเวอร์ (ทีมพัฒนาเกม) · ร่วมกับ อินฟราเครือข่าย (ทีมอินฟรา)
บอทส่งคำขอถี่กว่าคนมาก จึงกินกำลังประมวลผลของเซิร์ฟเวอร์
ทำไม บอทจำนวนมากเชื่อมต่อเข้ามา ฟาร์มมอน, เดิน และเทรดซ้ำไม่หยุด → ผลคือ ปริมาณงานที่เซิร์ฟเวอร์ต้องประมวลผลและโหลดของ DB เพิ่มขึ้น → บนหน้าจอ บางจุดฟาร์มหรือทั้งเซิร์ฟเวอร์ช้าลง (สโลว์โมชั่น, อินพุตดีเลย์)
อาการ สโลว์โมชั่น , อินพุตดีเลย์
ปัจจัย การหยุดชะงัก
ใครเจอ ทั้งเซิร์ฟเวอร์, บางจุด/บางแชนแนล
เกิดเมื่อไร ตลอดเวลา, ช่วงพีคหัวค่ำ
ผู้รับผิดชอบ ผู้รับผิดชอบหลัก พัฒนาเซิร์ฟเวอร์ (ทีมพัฒนาเกม) · ร่วมกับ อินฟราเครือข่าย (ทีมอินฟรา)
งานฝั่งทีมพัฒนาเกม ตรวจจับบอท, จำกัดความถี่คำขอต่อบัญชีและตัวละคร
งานฝั่งทีมอินฟรา จำกัดความถี่การเชื่อมต่อและคำขอต่อ IP (ร้านเกมและเครือข่ายมือถือมีหลายคนใช้ IP เดียวกัน จึงต้องเผื่อไว้), บล็อกช่วง IP ของบอทด้วยไฟร์วอลล์หรือ WAF
บนกราฟ สูงเฉพาะบางกลุ่ม · จำนวนคำขอต่อวินาทีแยกตามบัญชี/IP
จุดที่ต้องดู ใช้ log ของเซิร์ฟเวอร์เกมดูการกระจายและรายชื่ออันดับต้นของจำนวนคำขอต่อวินาทีแยกตามบัญชีและตัวละคร ถ้าไม่มีเมตริกจากโค้ด ให้ดูจำนวนคำขอแยกตาม IP จากไฟร์วอลล์หรือ WAF สัญญาณว่าใช่ บัญชีหรือ IP ส่วนน้อยส่งคำขอไม่หยุดด้วยความถี่ที่คนทำไม่ได้ และเมื่อจำกัดกลุ่มนี้ โหลดของเซิร์ฟเวอร์ลดลงชัดเจน สัญญาณว่าไม่ใช่ คำขอกระจายเท่า ๆ กันทุกบัญชี: น่าจะเป็นจำนวนผู้เล่นปกติที่เพิ่มขึ้น (ทิกเกินงบเวลา, autoscaling เพิ่มเครื่องไม่ทัน) วิธีตรวจ ต้องมี log หรือเมตริกจากเซิร์ฟเวอร์/ไคลเอนต์เกม
แหล่งอ้างอิง 2 รายการ
การพึ่งพาเซอร์วิสภายนอก External dependencies (auth, billing, platform)
ID in-external · ผู้รับผิดชอบหลัก ภายนอก (ภายนอก) · ร่วมกับ พัฒนาเซิร์ฟเวอร์ (ทีมพัฒนาเกม)
ถ้าเซอร์วิสภายนอก เช่น ล็อกอินผ่านแพลตฟอร์ม, การชำระเงิน หรือการยืนยันตัวตน ช้าหรือหยุดทำงาน ผู้เล่นจะติดอยู่ที่ขั้นตอนนั้น
ทำไม เซอร์วิสยืนยันตัวตนหรือชำระเงินภายนอกขัดข้องหรือช้า → ผลคือ รอคำตอบอยู่ที่ขั้นตอนนั้น → บนหน้าจอ ล็อกอินไม่ได้, ชำระเงินไม่สำเร็จ คนที่อยู่ในเกมแล้วเล่นได้ปกติ
อาการ เข้าเกมไม่ได้/โหลดไม่จบ , กดไม่ติด/โรลแบ็ค
ปัจจัย การหยุดชะงัก
ใครเจอ ทั้งเซิร์ฟเวอร์, เฉพาะบางฟีเจอร์
เกิดเมื่อไร หลังล็อกอิน/หลังปิดปรับปรุง, ตอนทำแอ็กชันบางอย่าง
ผู้รับผิดชอบ ผู้รับผิดชอบหลัก ภายนอก (ภายนอก) · ร่วมกับ พัฒนาเซิร์ฟเวอร์ (ทีมพัฒนาเกม)
งานฝั่งทีมพัฒนาเกม ตั้งไทม์เอาต์ให้การเรียกภายนอกพร้อมข้อความแจ้งที่เข้าใจง่าย, แคชผลการยืนยันตัวตน, ทำขั้นตอนลองชำระเงินใหม่และชดเชย
งานฝั่งภายนอก แจ้งผู้ให้บริการยืนยันตัวตน, ชำระเงิน และแพลตฟอร์มให้ตรวจสอบเหตุขัดข้องและกู้ระบบ, แจ้งผู้เล่นว่าเป็นเหตุขัดข้องของเซอร์วิสภายนอก
บนกราฟ ขึ้นเป็นขั้นบันไดจากจุดหนึ่ง · เวลาตอบสนอง/อัตราข้อผิดพลาดของการเรียกภายนอก, จำนวนล็อกอินที่สำเร็จ
จุดที่ต้องดู เวลาตอบสนอง, อัตราข้อผิดพลาด และจำนวนไทม์เอาต์ของการเรียกภายนอกแต่ละประเภท เช่น ล็อกอินผ่านแพลตฟอร์ม, การชำระเงิน และการยืนยันตัวตน กับหน้าสถานะ (status page) ของผู้ให้บริการ สัญญาณว่าใช่ ตั้งแต่ช่วงที่ล็อกอินหรือชำระเงินล้มเหลวกระจุกตัว error และไทม์เอาต์ของการเรียกภายนอกบางตัวเท่านั้นที่ขึ้นเป็นขั้นแล้วทรงตัวอยู่ระดับนั้น และหน้าสถานะของผู้ให้บริการมีเหตุขัดข้องในเวลาเดียวกัน สัญญาณว่าไม่ใช่ การเรียกภายนอกปกติแต่ล็อกอินไม่ได้: น่าจะเป็นที่ตัวเซิร์ฟเวอร์ล็อกอินเอง (thread pool หมด, DB) หรือคิวรอเชื่อมต่อ (backlog) ของระบบปฏิบัติการ วิธีตรวจ ต้องมี log หรือเมตริกจากเซิร์ฟเวอร์/ไคลเอนต์เกม
กรณีจริง Fastly 2021: Fastly CDN เกิด error ทั่วโลก AWS 2021: เครือข่ายภายในของ AWS us-east-1 แออัด AWS 2025: DNS ของ DynamoDB ใน AWS us-east-1 ขัดข้อง และการกู้คืนที่ยืดเยื้อ
แหล่งอ้างอิง 3 รายการ
ID in-region-match · ผู้รับผิดชอบหลัก พัฒนาเซิร์ฟเวอร์ (ทีมพัฒนาเกม) · ร่วมกับ พัฒนาไคลเอนต์ (ทีมพัฒนาเกม), อินฟราเครือข่าย (ทีมอินฟรา), ภายนอก (ภายนอก)
ถ้าถูกจัดไปเซิร์ฟเวอร์ในรีเจียนที่ไกลแทนรีเจียนที่ใกล้ ผู้เล่นคนนั้นจะปิงสูงตลอดแม้เน็ตจะปกติ
ทำไม ข้อมูล GeoIP ผิด, VPN, จัดทั้งปาร์ตี้ตามปิงเฉลี่ยของสมาชิก, กฎที่ขยายไปถึงรีเจียนไกลเมื่อคนไม่พอ, การจัดตามตำแหน่งของ DNS resolver → ผลคือ มีรีเจียนที่ใกล้อยู่แล้ว แต่ไปเชื่อมต่อกับเซิร์ฟเวอร์ในรีเจียนข้ามทะเล → บนหน้าจอ ในเกมที่มีเซิร์ฟเวอร์หลายรีเจียน เราคนเดียว (หรือแค่ปาร์ตี้เรา) ปิงสูงตลอด และมีอินพุตดีเลย์, โดนดีดกลับ, สกิลไม่ออก
อาการ อินพุตดีเลย์ , ดีดกลับ , กดไม่ติด/โรลแบ็ค
ปัจจัย ความหน่วง
ใครเจอ เราคนเดียว, บางพื้นที่/บาง ISP
เกิดเมื่อไร ตลอดเวลา, หลังล็อกอิน/หลังปิดปรับปรุง
ผู้รับผิดชอบ ผู้รับผิดชอบหลัก พัฒนาเซิร์ฟเวอร์ (ทีมพัฒนาเกม) · ร่วมกับ พัฒนาไคลเอนต์ (ทีมพัฒนาเกม), อินฟราเครือข่าย (ทีมอินฟรา), ภายนอก (ภายนอก)
งานฝั่งทีมพัฒนาเกม เซิร์ฟเวอร์: จัดรีเจียนตามปิงแต่ละรีเจียนที่ไคลเอนต์วัดได้แทน GeoIP, ใส่เพดานปิงในกฎที่ขยายไปรีเจียนไกล, ปาร์ตี้ให้ดูปิงของสมาชิกที่สูงที่สุดด้วยนอกจากค่าเฉลี่ย, เก็บ log รีเจียนที่จัดให้และปิงในตอนนั้น ไคลเอนต์: วัดปิงแต่ละรีเจียนด้วย UDP แล้วส่งไปพร้อมคำขอจับคู่, แสดงรีเจียนที่เชื่อมต่อและปิงบนหน้าจอ, มีตัวเลือกให้เลือกรีเจียนเอง
งานฝั่งทีมอินฟรา ถ้าใช้ DNS เลือกรีเจียน ให้ตรวจว่า authoritative DNS รองรับ EDNS Client Subnet หรือไม่ (ถ้า resolver ที่ผู้เล่นใช้ไม่ส่งมา จะจัดตามตำแหน่งของ resolver), อัปเดตฐานข้อมูล GeoIP เป็นประจำ, ใส่ประเทศและ ASN จาก GeoIP ลงใน log การเชื่อมต่อของเซิร์ฟเวอร์แต่ละรีเจียน เพื่อหาประเทศและ ISP ที่ไปลงรีเจียนไกล
งานฝั่งภายนอก แนะนำให้ผู้เล่นปิด VPN หรือโปรแกรมลดปิงแล้วลองเชื่อมต่อใหม่, แนะนำผู้เล่นที่ใช้ DNS ของบริษัทหรือของต่างประเทศให้ลองเปลี่ยนไปใช้ DNS ของ ISP, แจ้งผู้ให้บริการ GeoIP ให้แก้ตำแหน่งที่ผิด
ตัวเลขที่ควรรู้ ถ้าผู้เล่นในโซลถูกจัดไปรีเจียนสหรัฐฯ ฝั่งตะวันตกแทนโตเกียว ปิงจะเพิ่มจากประมาณ 30 ms เป็นประมาณ 130 ms GeoIP ถูกต้องระดับประเทศประมาณ 99.8% แต่ระดับเมือง แม้ในสหรัฐฯ สัดส่วนที่อยู่ในรัศมี 50 กิโลเมตรมีเพียงประมาณ 66% และถ้าใช้ VPN จะได้ตำแหน่งของเซิร์ฟเวอร์ VPN แทนตำแหน่งผู้เล่น
บนกราฟ สูงเฉพาะบางกลุ่ม · RTT (ปิง) แยกตามผู้เล่น, การกระจายของรีเจียนที่ถูกจัดให้
จุดที่ต้องดู ใส่ประเทศและ ASN จาก GeoIP ให้ IP ของไคลเอนต์ใน log การเชื่อมต่อของเซิร์ฟเวอร์แต่ละรีเจียน (access log ของโหลดบาลานเซอร์, VPC flow log) แล้วนับว่าแต่ละประเทศและ ISP เชื่อมต่อไปรีเจียนไหน ถ้าเป็นผู้เล่นคนเดียว ให้เทียบรีเจียนที่ผู้เล่นคนนั้นเชื่อมต่อจริงกับปิงไปยังรีเจียนที่ใกล้ (ให้ผู้เล่นวัดเอง หรือ mtr จากเซิร์ฟเวอร์ในรีเจียนนั้นไปยัง IP ของผู้เล่น) สัญญาณว่าใช่ ผู้เล่นหรือประเทศที่ RTT สูงเชื่อมต่ออยู่กับรีเจียนไกลแทนรีเจียนใกล้ และปิงที่วัดไปยังรีเจียนใกล้ต่ำ สัญญาณว่าไม่ใช่ ถูกจัดไปรีเจียนใกล้ถูกต้องแล้วแต่ปิงยังสูง: น่าจะเป็นเส้นทางวิ่งอ้อม หรือเน็ต/Wi-Fi ของผู้เล่นคนนั้น วิธีตรวจ ใช้เครื่องมือฝั่งอินฟรา (ไม่ต้องใช้โค้ดเกม)
รายละเอียดเพิ่มเติม วิธีเลือกรีเจียนด้วย DNS (DNS ที่อิงตำแหน่งหรือความหน่วง) จะเดาตำแหน่งจากที่อยู่ของ DNS resolver ที่ผู้เล่นใช้แทนที่อยู่ของผู้เล่นเอง ถ้า resolver ไม่รองรับ EDNS Client Subnet ที่ส่งที่อยู่บางส่วนของผู้เล่นต่อไป ผู้เล่นที่ใช้ DNS ของบริษัทหรือ DNS ที่อยู่ไกลจะถูกจัดตามตำแหน่งของ resolver ระบบจับคู่เองก็อาจตัดสินปาร์ตี้จากค่าเฉลี่ยปิงของสมาชิก หรือขยายเกณฑ์ปิงเมื่อรอนานจนจัดไปรีเจียนไกล AWS GameLift Servers ก็ใช้ค่าเฉลี่ยเป็นเกณฑ์ปิงของปาร์ตี้โดยค่าเริ่มต้น และยกตัวอย่างการตั้งค่าที่ขยายเพดานปิงจาก 50 ms เป็น 100 ms และ 200 ms ผู้เล่นที่เปิด VPN อาจเจอทั้งดีเลย์ที่เพิ่มจากการผ่านเซิร์ฟเวอร์ตัวกลาง (“เชื่อมต่อผ่าน VPN/โปรแกรมลดปิง”) และการถูกจัดไปรีเจียนไกลซ้อนกัน จึงแยกได้จากการดูว่าเมื่อปิด VPN แล้วเชื่อมต่อใหม่ รีเจียนที่ถูกจัดให้เปลี่ยนหรือไม่ กรณีที่ไม่มีรีเจียนใกล้เลยจนต้องต่อไปรีเจียนไกล อธิบายไว้ใน “ความหน่วงในการแพร่สัญญาณ (ระยะทางจริง)”
แหล่งอ้างอิง 8 รายการ RFC 7871: Client Subnet in DNS Queries IETF DNS ที่ตอบต่างกันตามตำแหน่งจะเดาตำแหน่งจากที่อยู่ของ resolver ที่ส่งคำถามมา และถ้าใช้ resolver ส่วนกลางที่อยู่ไกลจากผู้เล่น จะได้คำตอบที่ไม่เหมาะสม ส่งที่อยู่บางส่วนของผู้เล่นต่อไปด้วย EDNS Client Subnet (ฟีเจอร์ทางเลือก) How Amazon Route 53 uses EDNS0 to estimate the location of a user AWS ถ้า resolver ไม่รองรับ edns-client-subnet จะเดาตำแหน่งผู้เล่นจากที่อยู่ของ resolver และตอบตามตำแหน่งของ resolver (เหมือนกันทั้ง routing แบบอิงตำแหน่งและแบบอิงความหน่วง) Geolocation accuracy MaxMind ระดับประเทศประมาณ 99.8%, ระดับเมืองในสหรัฐฯ (ในรัศมี 50 กิโลเมตร) ประมาณ 66%, ถ้าใช้ VPN จะได้ตำแหน่งเซิร์ฟเวอร์ VPN แทนผู้ใช้ปลายทาง, IP ของเครือข่ายมือถือใช้กันในพื้นที่กว้างจึงระบุตำแหน่งละเอียดไม่ได้, ฐานข้อมูลต้องอัปเดตอย่างต่อเนื่อง, ขอแก้ไขข้อมูลได้ FlexMatch rule types AWS กฎความหน่วง (maxLatency) ดูความหน่วงของผู้เล่นแยกตามตำแหน่ง, ปาร์ตี้ใช้ค่าเฉลี่ยของสมาชิก (partyAggregation avg) เป็นค่าเริ่มต้น, คิวอาจวางไปรีเจียนที่ไม่ตรงกฎความหน่วงก็ได้ Create a player latency policy AWS วางไว้ในตำแหน่งที่ความหน่วงเฉลี่ยของผู้เล่นทุกคนต่ำที่สุด แต่ผู้เล่นที่ความหน่วงสูงแบบสุดโต่งก็ถูกวางด้วย, ตัวอย่างนโยบายที่ขยายเพดานปิงจาก 50 ms เป็น 100 ms และ 200 ms Amazon GameLift Servers UDP ping beacons AWS ไคลเอนต์เกมวัดความหน่วงด้วย UDP endpoint ที่มีในแต่ละตำแหน่งโฮสต์ แล้วใช้ในการวางเซิร์ฟเวอร์และจับคู่, ใกล้เคียงทราฟฟิกเกมจริงมากกว่า ICMP ping Azure network round-trip latency statistics Microsoft Azure ค่ามัธยฐานเวลาไปกลับที่วัดจริงจากโซล (Korea Central): โตเกียว (Japan East) 29 ms, สหรัฐฯ ฝั่งตะวันตก 124–136 ms Flow log records AWS srcaddr ใน record ของ VPC flow log: ถ้าเป็นทราฟฟิกขาเข้า คือ IP ของฝั่งผู้ส่ง
ID in-cert · ผู้รับผิดชอบหลัก อินฟราเครือข่าย (ทีมอินฟรา) · ร่วมกับ อินฟราเซิร์ฟเวอร์ (ทีมอินฟรา), พัฒนาไคลเอนต์ (ทีมพัฒนาเกม)
ถ้าใบรับรองของเซิร์ฟเวอร์ล็อกอิน, API หรือแพตช์หมดอายุ หรือขาดใบรับรองกลาง (intermediate certificate) ไคลเอนต์ที่เชื่อมต่อใหม่ตั้งแต่วินาทีนั้นจะเชื่อมต่อ TLS ไม่สำเร็จ
ทำไม ใบรับรองพ้นวันหมดอายุ, เซิร์ฟเวอร์ส่งใบรับรองมาโดยไม่มีใบรับรองกลาง หรือวันที่/เวลาในเครื่องผู้เล่นผิด → ผลคือ ไคลเอนต์ตรวจใบรับรองไม่ผ่านแล้วตัดการเชื่อมต่อ TLS → บนหน้าจอ เข้าเกมไม่ได้/โหลดไม่จบที่ขั้นตอนล็อกอินหรือแพตช์, ใช้ไม่ได้เฉพาะฟีเจอร์ HTTPS อย่างร้านค้า คนที่เชื่อมต่ออยู่แล้วส่วนใหญ่เล่นได้ปกติ
อาการ เข้าเกมไม่ได้/โหลดไม่จบ , กดไม่ติด/โรลแบ็ค
ปัจจัย การหยุดชะงัก
ใครเจอ ทั้งเซิร์ฟเวอร์, เฉพาะบางฟีเจอร์, เราคนเดียว
เกิดเมื่อไร หลังล็อกอิน/หลังปิดปรับปรุง, ตอนทำแอ็กชันบางอย่าง
ผู้รับผิดชอบ ผู้รับผิดชอบหลัก อินฟราเครือข่าย (ทีมอินฟรา) · ร่วมกับ อินฟราเซิร์ฟเวอร์ (ทีมอินฟรา), พัฒนาไคลเอนต์ (ทีมพัฒนาเกม)
งานฝั่งทีมพัฒนาเกม บันทึกข้อผิดพลาดของใบรับรองด้วย error code ที่แยกจากการเชื่อมต่อล้มเหลวแบบอื่นแล้วแจ้งผู้เล่น, ถ้าวันที่ผิดให้แนะนำให้ตั้งวันที่/เวลาของเครื่องเป็นอัตโนมัติ, ถ้าใช้ certificate pinning ให้ใส่คีย์สำรองไว้ด้วยและนัดกำหนดการเปลี่ยนใบรับรองกับทีมอินฟรา
งานฝั่งทีมอินฟรา เครือข่าย: ถ้า terminate TLS ที่โหลดบาลานเซอร์หรือ CDN ให้ตั้ง alert สถานะการต่ออายุอัตโนมัติของใบรับรองแบบ managed และจำนวนวันที่เหลือ (ACM คือ DaysToExpiry), คง DNS record สำหรับการยืนยันไว้ เครื่องเซิร์ฟเวอร์/OS: ถ้า terminate TLS ที่เซิร์ฟเวอร์ ให้ตั้งการต่ออายุอัตโนมัติและโหลดคอนฟิกใหม่หลังต่ออายุ, ตั้งค่าเป็น chain ที่รวมใบรับรองกลางด้วย, ตรวจอายุที่เหลือของทุกที่อยู่ล็อกอิน, API และแพตช์จากภายนอกเป็นระยะแล้วตั้ง alert
ตัวเลขที่ควรรู้ ใบรับรอง Let’s Encrypt มีอายุ 90 วัน จึงแนะนำให้ต่ออายุทุก 60 วัน ส่วน AWS Certificate Manager ตรวจใบรับรองที่ยืนยันด้วย DNS ตั้งแต่ 45 วันก่อนหมดอายุแล้วต่ออายุอัตโนมัติ ถ้าการต่ออายุอัตโนมัติล้มเหลวเงียบ ๆ การเชื่อมต่อใหม่จะถูกปิดกั้นพร้อมกันตรงเวลาหมดอายุพอดี
บนกราฟ การเชื่อมต่อหลุดพร้อมกัน · จำนวนล็อกอินที่สำเร็จ, จำนวน error ของ TLS handshake
จุดที่ต้องดู ใช้ openssl s_client -connect HOST:443 -showcerts ดูรายการใบรับรองที่เซิร์ฟเวอร์ส่งจริง แล้วตรวจวันหมดอายุ (notAfter) ของแต่ละใบด้วย openssl x509 -noout -enddate ถ้า terminate TLS ที่โหลดบาลานเซอร์ ให้ดูจำนวน error ในการเจรจา TLS (AWS ALB/NLB คือ ClientTLSNegotiationErrorCount) และจำนวนล็อกอินที่สำเร็จ สัญญาณว่าใช่ เลยวันหมดอายุแล้ว หรือรายการที่เซิร์ฟเวอร์ส่งมาไม่มีใบรับรองกลาง และเวลาที่ error เริ่มเพิ่มตรงกับเวลาหมดอายุหรือเวลาที่เปลี่ยนใบรับรอง สัญญาณว่าไม่ใช่ รายการใบรับรองและวันหมดอายุปกติ แต่ล้มเหลวเฉพาะผู้เล่นบางคน: ให้ดูวันที่/เวลาในเครื่องของผู้เล่นคนนั้น หรือรายการ root certificate ของ OS รุ่นเก่า วิธีตรวจ ใช้เครื่องมือฝั่งอินฟรา (ไม่ต้องใช้โค้ดเกม)
รายละเอียดเพิ่มเติม คอนฟิกที่ขาดใบรับรองกลางอาจดูปกติเมื่อเปิดด้วยเบราว์เซอร์บน PC เพราะเบราว์เซอร์จำใบรับรองกลางที่เคยได้รับจากเว็บไซต์อื่นไว้แล้วเติมส่วนที่ขาดให้ แต่ไคลเอนต์ที่ไม่ได้จำไว้แบบนั้น เช่น แอป Android จะล้มเหลว อายุใบรับรองก็กำลังสั้นลง Let’s Encrypt มีแผนลดอายุเริ่มต้นเหลือ 64 วันในปี 2027 และ 45 วันในปี 2028 คอนฟิกที่ตั้งตายตัวให้ต่ออายุทุก 60 วัน จะเหลือเวลาเผื่อแค่สี่วันกับใบรับรอง 64 วัน และจะเลยวันหมดอายุไปกับใบรับรอง 45 วัน AWS Certificate Manager เองก็ไม่ต่ออายุอัตโนมัติให้ใบรับรองที่นำเข้า (import) และถ้าลบ DNS record สำหรับการยืนยัน การต่ออายุจะล้มเหลว ลักษณะที่ล็อกอินไม่ได้คล้ายกับ “DNS ขัดข้อง/ช้า” แต่ปัญหาใบรับรองจะล้มเหลวที่ TLS handshake หลังหาที่อยู่เซิร์ฟเวอร์เจอแล้ว และเวลาเริ่มเกิดตรงกับเวลาหมดอายุหรือเวลาที่เปลี่ยนใบรับรอง
แหล่งอ้างอิง 12 รายการ
ID in-login-queue · ผู้รับผิดชอบหลัก พัฒนาเซิร์ฟเวอร์ (ทีมพัฒนาเกม) · ร่วมกับ พัฒนาไคลเอนต์ (ทีมพัฒนาเกม), อินฟราเซิร์ฟเวอร์ (ทีมอินฟรา)
เมื่อคนแห่เข้ามาทันทีหลังเปิดตัวเกมหรือปิดปรับปรุง คิวล็อกอินจะชนเพดานจนปฏิเสธคนที่จะเข้าคิวใหม่ และผู้เล่นที่รออยู่ถ้าหลุดไปแป๊บเดียวก็เสียลำดับคิวแล้วต้องกลับไปต่อท้าย
ทำไม คนที่จะเข้าเกมมีมากกว่าที่เซิร์ฟเวอร์ล็อกอินรับได้ในครั้งเดียว จึงต้องมีคิว และถ้าคิวยาวเกินไปก็ปฏิเสธการเข้าคิวใหม่เพื่อปกป้องเซิร์ฟเวอร์ → ผลคือ ยิ่งคิวยาว เวลารอยิ่งนาน และระหว่างนั้นถ้า Wi-Fi หรือเครือข่ายมือถือหลุดแค่แป๊บเดียวก็เสียลำดับคิว → บนหน้าจอ เข้าเกมไม่ได้/โหลดไม่จบ, เกมปิดตัวพร้อม error ระหว่างรอ, ต้องกลับไปรอท้ายคิวใหม่
อาการ เข้าเกมไม่ได้/โหลดไม่จบ , หลุด
ปัจจัย การหยุดชะงัก
ใครเจอ ทั้งเซิร์ฟเวอร์, เราคนเดียว
เกิดเมื่อไร หลังล็อกอิน/หลังปิดปรับปรุง, ช่วงพีคหัวค่ำ
ผู้รับผิดชอบ ผู้รับผิดชอบหลัก พัฒนาเซิร์ฟเวอร์ (ทีมพัฒนาเกม) · ร่วมกับ พัฒนาไคลเอนต์ (ทีมพัฒนาเกม), อินฟราเซิร์ฟเวอร์ (ทีมอินฟรา)
งานฝั่งทีมพัฒนาเกม เซิร์ฟเวอร์: ตั้งเพดานคิวให้ตรงกับปริมาณที่เซิร์ฟเวอร์ล็อกอินประมวลผลได้จริง, เก็บลำดับคิวของผู้เล่นที่หลุดระหว่างรอไว้ช่วงหนึ่ง (grace period ตอนเชื่อมต่อใหม่), แสดงลำดับคิวและเวลารอโดยประมาณ, เก็บความยาวคิว, จำนวนที่ถูกปฏิเสธ และจำนวนที่หลุดระหว่างรอเป็นเมตริก ไคลเอนต์: ถ้าหลุดระหว่างรอ ให้เชื่อมต่อกลับเข้าตำแหน่งเดิมอัตโนมัติโดยไม่ปิดเกม, กระจายช่วงห่างของการลองใหม่ด้วย exponential backoff และ jitter
งานฝั่งทีมอินฟรา เครื่องเซิร์ฟเวอร์/OS: ทดสอบโหลดก่อนเปิดตัวเพื่อวัดขีดจำกัดการประมวลผลของเซิร์ฟเวอร์ล็อกอินและล็อบบี้, ตอนเปิดตัวเตรียมให้เพิ่มเครื่องสำรองได้ทันที, ดูเมตริกคิวบนกราฟเดียวกับจำนวนครั้งที่พยายามเชื่อมต่อ
ตัวเลขที่ควรรู้ ตอนเปิดตัวภาคเสริม FINAL FANTASY XIV ในปี 2021 ถ้าจำนวนคนรอในแต่ละ logical data center เกิน 17,000 คน จะปฏิเสธการเข้าคิวใหม่ (Error 2002) และถ้าหลุดระหว่างรอ lobby server จะรอให้หลายสิบวินาทีถึง 1 นาที ถ้าต่อกลับเข้ามาภายในเวลานั้น จะได้ต่อคิวจากตำแหน่งเดิมกลางคิว
บนกราฟ ชนเพดานแล้วแบนราบ · ความยาวคิวล็อกอิน, จำนวนที่ถูกปฏิเสธเพราะชนเพดาน, จำนวนที่หลุดระหว่างรอ
จุดที่ต้องดู วางความยาวคิว, เวลารอเฉลี่ย, จำนวนที่ถูกปฏิเสธเพราะชนเพดาน และจำนวนที่หลุดระหว่างรอ ที่เซิร์ฟเวอร์ล็อกอินและล็อบบี้บันทึกไว้ บนกราฟเดียวกับจำนวนครั้งที่พยายามเชื่อมต่อ สัญญาณว่าใช่ ทันทีหลังเปิดตัวหรือปิดปรับปรุง ระหว่างที่ความยาวคิวชนเพดานแล้วแบนราบ จำนวนที่ถูกปฏิเสธเพิ่มขึ้น และการหลุดระหว่างรอกระจุกอยู่ที่ผู้เล่น Wi-Fi และเครือข่ายมือถือ สัญญาณว่าไม่ใช่ คิวสั้นแต่ล็อกอินช้า: น่าจะเป็น DB (db-login-storm) หรือคิวรอเชื่อมต่อของ OS (so-backlog) วิธีตรวจ ต้องมี log หรือเมตริกจากเซิร์ฟเวอร์/ไคลเอนต์เกม
รายละเอียดเพิ่มเติม กรณีที่คนแห่ล็อกอินจน DB ช้า อธิบายไว้ใน “คนแห่ล็อกอินและคิวรี N+1” และกรณีที่คิวรอเชื่อมต่อของ OS ล้น อธิบายไว้ใน “คิวรอเชื่อมต่อ (backlog) ล้น” การ์ดนี้เป็นปัญหาการออกแบบคิวล็อกอินที่เกมตั้งใจสร้างไว้ เพดานคิวเป็นกลไกป้องกันเซิร์ฟเวอร์ล็อกอินจึงเอาออกไม่ได้ เพราะต้องปฏิเสธคำขอส่วนเกินแต่เนิ่น ๆ จึงจะประมวลผลคำขอที่รับไหวต่อไปได้ สิ่งสำคัญคือลดความเสียหายที่การปฏิเสธและการหลุดสร้างให้ผู้เล่น และยิ่งคิวยาว error ยิ่งไปกระจุกที่ผู้เล่นที่เน็ตไม่นิ่ง เช่น Wi-Fi และเครือข่ายมือถือ
กรณีจริง Square Enix 2021: FINAL FANTASY XIV แออัดช่วงเปิดตัวภาคเสริม และ error ในคิวล็อกอิน
แหล่งอ้างอิง 2 รายการ Response to Congestion (as of Dec. 11) Square Enix ถ้าจำนวนคนรอในแต่ละ logical data center เกิน 17,000 คน จะปฏิเสธการเข้าคิวใหม่เพื่อไม่ให้เซิร์ฟเวอร์ล็อกอินล่ม (Error 2002), ถ้าหลุดระหว่างรอ lobby server จะรอหลายสิบวินาทีถึง 1 นาที ถ้าต่อกลับมาภายในเวลานั้นได้ต่อจากตำแหน่งเดิมกลางคิว ถ้าเกินจะไปต่อท้าย Using load shedding to avoid overload Amazon Builders' Library load shedding ที่ปฏิเสธคำขอส่วนเกินแต่เนิ่น ๆ เพื่อให้ประมวลผลคำขอที่รับไหวต่อไปได้
การออกแบบการซิงก์
16 สาเหตุ · บทในฉบับหลัก
ID sy-request-response · ผู้รับผิดชอบหลัก พัฒนาไคลเอนต์ (ทีมพัฒนาเกม) · ร่วมกับ พัฒนาเซิร์ฟเวอร์ (ทีมพัฒนาเกม)
กดปุ่มแล้วไม่มีทั้งแอนิเมชันและเสียงจนกว่าคำตอบจากเซิร์ฟเวอร์จะมาถึง ปิงจึงกลายเป็นความเร็วในการตอบสนองโดยตรง
ทำไม แสดงผลสกิล, การเดิน และการเก็บของ หลังจากเซิร์ฟเวอร์ยืนยันแล้ว → ผลคือ ตั้งแต่วินาทีที่กดจะไม่มีปฏิกิริยาใด ๆ เป็นเวลาเท่ากับเวลาไปกลับ + เวลารอทิก → บนหน้าจอ ถ้าปิง 150 ms ทุกการกระทำจะตอบสนองช้าไปครั้งละ 0.2 วินาที
อาการ อินพุตดีเลย์
ปัจจัย ความหน่วง
ใครเจอ เราคนเดียว
เกิดเมื่อไร ตลอดเวลา, ตอนทำแอ็กชันบางอย่าง
ผู้รับผิดชอบ ผู้รับผิดชอบหลัก พัฒนาไคลเอนต์ (ทีมพัฒนาเกม) · ร่วมกับ พัฒนาเซิร์ฟเวอร์ (ทีมพัฒนาเกม)
งานฝั่งทีมพัฒนาเกม ไคลเอนต์: เริ่มแอนิเมชัน, เสียง และเอฟเฟกต์ทันทีที่กด (การแสดงผลล่วงหน้า), แสดงเฉพาะผลลัพธ์ (ดาเมจ, ของรางวัล) หลังเซิร์ฟเวอร์ยืนยัน, การเดินและการโจมตีปกติให้ใช้ prediction แสดงผลทันที, เมื่อได้รับตำแหน่งที่เซิร์ฟเวอร์แก้มา ให้ใช้อินพุตที่ยังไม่ได้รับการยืนยันซ้ำจากตำแหน่งนั้น เซิร์ฟเวอร์: คำนวณการเคลื่อนที่เองจากอินพุตที่ได้รับ และส่งค่าแก้กลับไปเฉพาะเมื่อตำแหน่งต่างจากที่ไคลเอนต์คาดการณ์เกินเกณฑ์
ตัวเลขที่ควรรู้ เวลาตอบสนอง ≈ ปิง + ครึ่งหนึ่งของช่วงห่างระหว่างทิก + หนึ่งเฟรม ที่ 20 ทิกและปิง 150 ms จะได้ประมาณ 190 ms
บนกราฟ สูงตลอดตั้งแต่แรก · เวลาตั้งแต่อินพุตจนเริ่มแสดงผล, RTT (ปิง)
จุดที่ต้องดู บันทึกเวลาที่กดปุ่ม, เวลาที่แอนิเมชันหรือเสียงแรกเริ่ม และเวลาที่คำตอบจากเซิร์ฟเวอร์มาถึง ลงใน log ไคลเอนต์ของ dev build แล้วดูคู่กับ RTT ในเกม วัดโดยเปลี่ยนปิงไปเรื่อย ๆ ด้วยการใส่ดีเลย์ผ่าน network emulation ของเอนจิน (Unreal NetEmulation.PktLag) หรือ tc netem ของ Linux บนเซิร์ฟเวอร์ทดสอบ สัญญาณว่าใช่ การแสดงผลเริ่มพร้อมกับที่คำตอบจากเซิร์ฟเวอร์มาถึงทุกครั้ง เวลาตั้งแต่อินพุตจนแสดงผลเท่ากับ RTT + เวลารอทิก และเพิ่มขึ้นตามดีเลย์ที่ใส่เข้าไปพอดี สัญญาณว่าไม่ใช่ การแสดงผลเริ่มทันทีที่กดและมีแค่ผลลัพธ์อย่างตัวเลขดาเมจที่ช้า: เป็นการออกแบบปกติ ถ้าช้าเกินช่วงห่างระหว่างทิกแม้ในที่ที่ปิงต่ำ น่าจะเป็นการรอทิกซ้อนสองชั้นหรือปัญหาเฟรมฝั่งไคลเอนต์ วิธีตรวจ ต้องมี log หรือเมตริกจากเซิร์ฟเวอร์/ไคลเอนต์เกม
รายละเอียดเพิ่มเติม เกมที่ไม่ต้องการการตอบสนองเร็ว เช่น เกมเทิร์นเบส, เกมการ์ด และเกม idle วิธีนี้ง่ายและปลอดภัยที่สุด ปัญหาเกิดเมื่อเกมที่มีการควบคุมแบบเรียลไทม์ทำแม้แต่การเดินหรือการโจมตีปกติด้วยวิธีนี้
แหล่งอ้างอิง 5 รายการ
ID sy-chatty · ผู้รับผิดชอบหลัก พัฒนาเซิร์ฟเวอร์ (ทีมพัฒนาเกม) · ร่วมกับ พัฒนาไคลเอนต์ (ทีมพัฒนาเกม)
ถ้าการกระทำหนึ่งครั้งต้องไปกลับเซิร์ฟเวอร์หลายรอบตามลำดับ ปิงจะคูณตามจำนวนรอบนั้น
ทำไม เปิดร้านค้า → ขอรายการ → ตรวจราคา → ซื้อ → อัปเดตกระเป๋า แยกเป็นคำขอทีละรายการ → ผลคือ ต้องได้คำตอบของคำขอก่อนหน้าก่อนจึงส่งคำขอถัดไป → บนหน้าจอ ที่ปิง 150 ms ซื้อของครั้งเดียวใช้เวลาเกือบ 1 วินาที และโหลดนานผิดปกติ
อาการ อินพุตดีเลย์ , เข้าเกมไม่ได้/โหลดไม่จบ
ปัจจัย ความหน่วง
ใครเจอ เฉพาะบางฟีเจอร์, เราคนเดียว
เกิดเมื่อไร ตอนทำแอ็กชันบางอย่าง, หลังล็อกอิน/หลังปิดปรับปรุง
ผู้รับผิดชอบ ผู้รับผิดชอบหลัก พัฒนาเซิร์ฟเวอร์ (ทีมพัฒนาเกม) · ร่วมกับ พัฒนาไคลเอนต์ (ทีมพัฒนาเกม)
งานฝั่งทีมพัฒนาเกม เซิร์ฟเวอร์: เปลี่ยนโปรโตคอลให้รวมหลายขั้นตอนไว้ในคำขอและคำตอบเดียว (เช่น ใส่กระเป๋าที่อัปเดตแล้วไว้ในคำตอบของการซื้อด้วย) ไคลเอนต์: โหลดข้อมูลที่ต้องใช้ไว้ล่วงหน้า, ทำ UI ที่ไม่ต้องรอผลลัพธ์
ตัวเลขที่ควรรู้ เวลาที่ใช้ ≈ จำนวนรอบไปกลับ × (ปิง + เวลาประมวลผลบนเซิร์ฟเวอร์ + เวลารอทิก) ถ้า 5 รอบที่ปิง 150 ms จะใช้ประมาณ 0.85–1 วินาที
บนกราฟ สูงตลอดตั้งแต่แรก · เวลาที่แต่ละฟีเจอร์ใช้จนเสร็จ, จำนวนรอบไปกลับต่อการกระทำหนึ่งครั้ง
จุดที่ต้องดู ใน packet capture ฝั่งเซิร์ฟเวอร์ (Wireshark) นับว่าระหว่างที่บัญชีทดสอบกดซื้อของในร้านหรือล็อกอินหนึ่งครั้ง คำขอและคำตอบสลับกันไปมากี่รอบ และห่างกันเท่าไร ถ้ามี log คำขอของเซิร์ฟเวอร์ ให้จัดกลุ่มด้วย session ID แล้วดูจำนวนคำขอและเวลาที่แต่ละคำขอมาถึงและได้คำตอบ สัญญาณว่าใช่ การกระทำหนึ่งครั้งมีคำขอที่ต้องรอคำตอบก่อนหน้าแล้วจึงส่งต่อกันหลายรอบ เวลาที่ใช้จนเสร็จประมาณจำนวนรอบ × RTT และผู้เล่นในพื้นที่ที่ปิงสูงจะใช้ฟีเจอร์เดียวกันได้ช้าลงตามสัดส่วน สัญญาณว่าไม่ใช่ ไปกลับแค่หนึ่งสองรอบ แต่คำตอบเดียวใช้เวลานาน: น่าจะเป็นสาเหตุที่การประมวลผลบนเซิร์ฟเวอร์หรือ DB ถ้าผู้เล่นทุกคนช้าเท่ากันโดยไม่เกี่ยวกับปิง ให้ดูโหลดของเซิร์ฟเวอร์ วิธีตรวจ ใช้เครื่องมือฝั่งอินฟรา (ไม่ต้องใช้โค้ดเกม)
แหล่งอ้างอิง 1 รายการ Chatty I/O antipattern Microsoft Azure ถ้ามีคำขอ I/O เล็ก ๆ จำนวนมาก ดีเลย์สะสมจะทำให้การตอบสนองแย่ลงมาก แนะนำให้รวมคำขอให้ใหญ่ขึ้นและน้อยครั้งลง
ID sy-no-queue · ผู้รับผิดชอบหลัก พัฒนาไคลเอนต์ (ทีมพัฒนาเกม) · ร่วมกับ พัฒนาเซิร์ฟเวอร์ (ทีมพัฒนาเกม)
ถ้าต้องได้การยืนยันจากเซิร์ฟเวอร์ว่าสกิลก่อนหน้าจบแล้วจึงจะกดสกิลถัดไปได้ ทุกคอมโบจะมีเวลาไปกลับแทรกเข้ามา
ทำไม รับอินพุตสกิลถัดไปเฉพาะ “หลังสกิลก่อนหน้ายืนยันแล้ว” เท่านั้น → ผลคือ ระหว่างสกิลแต่ละครั้งมีช่วงว่างเท่ากับปิง → บนหน้าจอ เกิดช่องว่างระหว่างคอมโบทุกครั้ง และยิ่งปิงสูง DPS ยิ่งลดลง
อาการ อินพุตดีเลย์ , กดไม่ติด/โรลแบ็ค
ปัจจัย ความหน่วง
ใครเจอ เราคนเดียว, เฉพาะบางฟีเจอร์
เกิดเมื่อไร ตอนทำแอ็กชันบางอย่าง
ผู้รับผิดชอบ ผู้รับผิดชอบหลัก พัฒนาไคลเอนต์ (ทีมพัฒนาเกม) · ร่วมกับ พัฒนาเซิร์ฟเวอร์ (ทีมพัฒนาเกม)
งานฝั่งทีมพัฒนาเกม ไคลเอนต์: มีช่วงเวลาที่รับการกดล่วงหน้า คือรับอินพุตที่กดภายในช่วงเวลาหนึ่งก่อนคูลดาวน์จบ (เช่น 0.3–0.4 วินาที) แล้วส่งให้เซิร์ฟเวอร์ทันที เซิร์ฟเวอร์: รับอินพุตที่มาถึงเร็วไปเล็กน้อยไว้ แล้วรันทันทีที่คูลดาวน์จบ
ตัวเลขที่ควรรู้ ในคอมโบที่คูลดาวน์ 1 วินาที ถ้าปิง 150 ms จะว่างระหว่างสกิลอย่างน้อย 0.15 วินาทีทุกครั้ง จำนวนสกิลที่ใช้ได้ในเวลาเท่ากันจะลดลงมากกว่า 13%
บนกราฟ สูงตลอดตั้งแต่แรก · ช่วงว่างระหว่างสกิล, RTT (ปิง)
จุดที่ต้องดู บันทึกเวลาที่คูลดาวน์สกิลจบ, เวลาที่คำขอสกิลถัดไปมาถึง และเวลาที่รัน ของแต่ละตัวละครลงใน log ของเซิร์ฟเวอร์ แล้วเทียบช่วงว่างระหว่างนั้นกับ RTT ของผู้เล่น สัญญาณว่าใช่ ตั้งแต่คูลดาวน์จบจนสกิลถัดไปทำงาน ว่างประมาณเท่า RTT ทุกครั้ง ผู้เล่นที่ปิงสูงกว่ามีช่วงว่างยาวกว่าและใช้สกิลได้น้อยกว่าในเวลาเท่ากัน สัญญาณว่าไม่ใช่ ช่วงว่างคงที่ไม่ขึ้นกับปิง: น่าจะเป็นการออกแบบ global cooldown หรือความยาวแอนิเมชัน ถ้าช่วงว่างพุ่งสูงแค่บางครั้ง ให้ดูจิตเตอร์, แพ็กเก็ตหาย หรือทิกเกินงบเวลา วิธีตรวจ ต้องมี log หรือเมตริกจากเซิร์ฟเวอร์/ไคลเอนต์เกม
รายละเอียดเพิ่มเติม ตัวอย่างเช่น World of Warcraft มีช่วงเวลาที่รับการกดล่วงหน้า และให้ผู้เล่นปรับได้ในการตั้งค่า ถ้าช่วงเวลานี้ยาวกว่าเวลาไปกลับ ปิงแทบไม่แทรกเข้ามาระหว่างคอมโบ
แหล่งอ้างอิง 1 รายการ
ID sy-short-window · ผู้รับผิดชอบหลัก พัฒนาเซิร์ฟเวอร์ (ทีมพัฒนาเกม) · ร่วมกับ พัฒนาไคลเอนต์ (ทีมพัฒนาเกม), อินฟราเซิร์ฟเวอร์ (ทีมอินฟรา)
ถ้าเวลาที่ต้องตอบสนอง เช่น การหลบ, การแพร์รี และการกัน สั้นเกินไป ปิงจะกินเวลานั้นไปจนเกิดการโจมตีที่หลบไม่ได้
ทำไม ช่วงเวลาตัดสินที่สั้น เช่น สัญญาณเตือนท่าโจมตีของบอส 0.5 วินาที หรือช่วงเวลาตัดสินการแพร์รี 0.2 วินาที → ผลคือ เห็นสัญญาณเตือนช้า (ดีเลย์ขาลง + interpolation) และอินพุตของเราก็ไปถึงช้า (ดีเลย์ขาขึ้น + เวลารอทิก) → บนหน้าจอ หลบพ้นแน่ ๆ แต่ยังโดน, แพร์รีไม่ออก
อาการ กดไม่ติด/โรลแบ็ค , อินพุตดีเลย์
ปัจจัย ความหน่วง
ใครเจอ เราคนเดียว, เฉพาะบางฟีเจอร์
เกิดเมื่อไร ตอนทำแอ็กชันบางอย่าง
ผู้รับผิดชอบ ผู้รับผิดชอบหลัก พัฒนาเซิร์ฟเวอร์ (ทีมพัฒนาเกม) · ร่วมกับ พัฒนาไคลเอนต์ (ทีมพัฒนาเกม), อินฟราเซิร์ฟเวอร์ (ทีมอินฟรา)
งานฝั่งทีมพัฒนาเกม เซิร์ฟเวอร์: นัดเวลาสัญญาณเตือนการโจมตีตามเวลาเซิร์ฟเวอร์แล้วส่งล่วงหน้า, ขยายช่วงเวลาตัดสินออกไปเท่ากับปิง (lag compensation) ไคลเอนต์: เล่นสัญญาณเตือนที่ได้รับให้ตรงกับเวลาเซิร์ฟเวอร์ที่นัดไว้
งานฝั่งทีมอินฟรา วางเซิร์ฟเวอร์ใกล้พื้นที่ที่มีผู้เล่นมาก (เซิร์ฟเวอร์ประจำภูมิภาค) เพื่อลดปิงโดยตรง
ตัวเลขที่ควรรู้ ถ้าปิง 150 ms และ interpolation 100 ms กว่าสัญญาณเตือนจะขึ้นบนจอเราใช้ประมาณ 0.18 วินาที และกว่าอินพุตของเราจะถึงเซิร์ฟเวอร์ใช้ประมาณ 0.1 วินาที บวกเวลาตอบสนองของคน 0.25 วินาทีเข้าไป สัญญาณเตือน 0.5 วินาทีจึงแทบหลบไม่ทัน
บนกราฟ สูงเฉพาะบางกลุ่ม · อัตราการหลบ/แพร์รีพลาด (แยกตามช่วงปิง)
จุดที่ต้องดู บันทึกเวลาเริ่มและจบของช่วงเวลาตัดสิน, เวลาที่อินพุตของผู้เล่นมาถึงเซิร์ฟเวอร์ และ RTT ของผู้เล่นคนนั้นลงใน log ของเซิร์ฟเวอร์ แล้วแบ่งดูอัตราพลาดตามช่วงปิง (เช่น ทีละ 50 ms) สัญญาณว่าใช่ ยิ่งช่วงปิงสูง อัตราพลาดยิ่งสูงชัดเจน และอินพุตที่พลาดมาถึงหลังช่วงเวลาตัดสินจบไปไม่นาน (ไม่เกิน RTT รวมเวลา interpolation) สัญญาณว่าไม่ใช่ อัตราพลาดใกล้เคียงกันทุกช่วงปิง: น่าจะเป็นความยากของแพตเทิร์น ถ้าอินพุตมาถึงภายในช่วงเวลาตัดสินแล้วยังนับเป็นพลาด ให้ดูโค้ดตัดสินผลหรือการตรวจสอบของเซิร์ฟเวอร์ วิธีตรวจ ต้องมี log หรือเมตริกจากเซิร์ฟเวอร์/ไคลเอนต์เกม
แหล่งอ้างอิง 3 รายการ
ID sy-no-lagcomp · ผู้รับผิดชอบหลัก พัฒนาเซิร์ฟเวอร์ (ทีมพัฒนาเกม) · ร่วมกับ พัฒนาไคลเอนต์ (ทีมพัฒนาเกม)
ถ้าเซิร์ฟเวอร์ตัดสินการโดนโดยดูแค่ “ตำแหน่งบนเซิร์ฟเวอร์ ณ ตอนนี้” ผลการตัดสินจะไม่ตรงกับที่เราเห็นบนจอ
ทำไม คู่ต่อสู้บนจอเราอยู่ในตำแหน่งย้อนหลังไปประมาณ 0.2 วินาที (เมื่อปิง 150 ms และ interpolation 100 ms) → ผลคือ เซิร์ฟเวอร์ตัดสินจากตำแหน่งปัจจุบัน ตรงที่เราเล็งไว้จึงไม่มีเป้าแล้ว → บนหน้าจอ ยิงโดนแน่ ๆ แต่พลาด ต้องยิงดักหน้าเป้าที่กำลังเคลื่อนที่
อาการ กดไม่ติด/โรลแบ็ค
ปัจจัย ความหน่วง
ใครเจอ เราคนเดียว
เกิดเมื่อไร ตอนทำแอ็กชันบางอย่าง
ผู้รับผิดชอบ ผู้รับผิดชอบหลัก พัฒนาเซิร์ฟเวอร์ (ทีมพัฒนาเกม) · ร่วมกับ พัฒนาไคลเอนต์ (ทีมพัฒนาเกม)
งานฝั่งทีมพัฒนาเกม เซิร์ฟเวอร์: ย้อนเวลาไปยังจังหวะที่ผู้โจมตีเห็นแล้วจึงตัดสิน (lag compensation) หรือเปลี่ยนเป็นระบบล็อกเป้า ไคลเอนต์: ตอนโจมตีให้ส่งจังหวะที่ตัวเองเห็นอยู่ (เวลาเซิร์ฟเวอร์ที่กำลัง interpolate) ไปด้วย
บนกราฟ สูงเฉพาะบางกลุ่ม · อัตราการโจมตีโดนเป้าที่เคลื่อนที่ (แยกตามช่วงปิง)
จุดที่ต้องดู บันทึกเวลาโจมตี, ตำแหน่งเป้าบนจอผู้โจมตี (ค่าที่ไคลเอนต์ส่งมา), ตำแหน่งเป้าบนเซิร์ฟเวอร์ที่ใช้ตัดสิน และ RTT ของผู้โจมตีลงใน log การตัดสินของเซิร์ฟเวอร์ ใน dev build ถ้าวาดตำแหน่งที่เซิร์ฟเวอร์ใช้ตัดสินซ้อนบนจอไคลเอนต์จะเห็นทันที สัญญาณว่าใช่ ในการตัดสินที่พลาด ระยะห่างระหว่างสองตำแหน่งประมาณความเร็วเป้า × (RTT ของผู้โจมตี + เวลา interpolation) และยิ่งปิงสูง อัตราโดนลดลงเฉพาะกับเป้าที่เคลื่อนที่ สัญญาณว่าไม่ใช่ เป้าที่ยืนนิ่งก็พลาด: น่าจะเป็นปัญหา hitbox หรือการตรวจการชน ถ้าย้อนเวลาแล้วยังคลาด ให้ดูว่าไคลเอนต์แจ้งเวลา interpolation ให้เซิร์ฟเวอร์ผิดหรือไม่ วิธีตรวจ ต้องมี log หรือเมตริกจากเซิร์ฟเวอร์/ไคลเอนต์เกม
แหล่งอ้างอิง 3 รายการ
ID sy-lagcomp-overreach · ผู้รับผิดชอบหลัก พัฒนาเซิร์ฟเวอร์ (ทีมพัฒนาเกม)
ถ้าย้อนเวลาให้ผู้โจมตีไกลเกินไป ฝ่ายที่ถูกโจมตีจะโดนทั้งที่หลบไปแล้ว
ทำไม เซิร์ฟเวอร์ย้อนเวลาไกลเพื่อผู้โจมตีที่ปิงสูง แล้วจึงตัดสิน → ผลคือ บนจอของฝ่ายที่ถูกโจมตี เขาเข้าที่กำบังไปแล้ว → บนหน้าจอ “หลบหลังกำแพงแล้วยังโดน”, คนปิงสูงได้เปรียบ
อาการ กดไม่ติด/โรลแบ็ค
ปัจจัย ความหน่วง
ใครเจอ เราคนเดียว, บางพื้นที่/บาง ISP
เกิดเมื่อไร ตอนทำแอ็กชันบางอย่าง
ผู้รับผิดชอบ ผู้รับผิดชอบหลัก พัฒนาเซิร์ฟเวอร์ (ทีมพัฒนาเกม)
งานฝั่งทีมพัฒนาเกม ตั้งเพดานการย้อนเวลา (เช่น 200–250 ms), ผู้โจมตีที่ปิงสูงกว่านั้นให้ย้อนได้ถึงเพดานเท่านั้น ส่วนที่เหลือให้ผู้โจมตียิงดักหน้าเอง
บนกราฟ สูงเฉพาะบางกลุ่ม · เวลาที่ย้อนกลับต่อการโดนแต่ละครั้ง (แยกตามปิงของผู้โจมตี)
จุดที่ต้องดู บันทึกเวลาที่ย้อนกลับ, RTT ของผู้โจมตี และเวลาเซิร์ฟเวอร์ที่ฝ่ายถูกยิงเข้าที่กำบัง ของการโดนแต่ละครั้งลงใน log การตัดสินของเซิร์ฟเวอร์ ใน dev build ลองวาด hitbox ที่ย้อนเวลาแล้วบนจอ (เอนจิน Source ใช้ sv_showlagcompensation) สัญญาณว่าใช่ การโดนในเคสที่แจ้งว่า “หลบหลังกำแพงแล้วยังโดน” กระจุกอยู่ที่ผู้โจมตีที่ย้อนเวลานาน และเวลาที่ย้อนเพิ่มตามปิงของผู้โจมตีโดยไม่มีเพดาน สัญญาณว่าไม่ใช่ โดนหลังกำแพงแม้ในการโดนที่ย้อนเวลาสั้น: น่าจะเป็นปัญหา hitbox หรือการตรวจการชน ถ้าฝ่ายที่ถูกยิงปิงสูง เป็นเพราะการเคลื่อนที่ของคนนั้นไปถึงเซิร์ฟเวอร์ช้า วิธีตรวจ ต้องมี log หรือเมตริกจากเซิร์ฟเวอร์/ไคลเอนต์เกม
รายละเอียดเพิ่มเติม การตัดสินแบบย้อนเวลาเป็นแบบ “ยึดฝั่งผู้ยิง” และมีข้อเสนอข้อยกเว้นแบบ “ยึดฝั่งผู้ถูกยิง” คือไม่ย้อนเวลาถ้าฝ่ายที่ถูกยิงเข้าที่ปลอดภัยบนจอของตัวเองแล้ว
แหล่งอ้างอิง 3 รายการ
ID sy-client-auth · ผู้รับผิดชอบหลัก พัฒนาเซิร์ฟเวอร์ (ทีมพัฒนาเกม) · ร่วมกับ พัฒนาไคลเอนต์ (ทีมพัฒนาเกม)
ถ้าแต่ละคนตัดสินผลของตัวเอง จอของเราจะลื่น แต่ผลจะไม่ตรงกับจอของคนอื่นและโกงได้ง่าย
ทำไม ไคลเอนต์เป็นผู้กำหนดตำแหน่งและการโดน เซิร์ฟเวอร์แค่ส่งต่อ → ผลคือ สองคนต่างอ้างว่าตัวเองยิงโดนก่อน เซิร์ฟเวอร์ตรวจสอบไม่ได้ → บนหน้าจอ อีกฝ่ายวาร์ปหรือเดินทะลุกำแพง, “ยิงโดนแล้วแต่ไม่เข้า”
อาการ วาร์ป , กดไม่ติด/โรลแบ็ค
ปัจจัย ความหน่วง
ใครเจอ ทั้งเซิร์ฟเวอร์
เกิดเมื่อไร ตลอดเวลา
ผู้รับผิดชอบ ผู้รับผิดชอบหลัก พัฒนาเซิร์ฟเวอร์ (ทีมพัฒนาเกม) · ร่วมกับ พัฒนาไคลเอนต์ (ทีมพัฒนาเกม)
งานฝั่งทีมพัฒนาเกม เซิร์ฟเวอร์: ผลที่สำคัญ (เช่น การโดน) ให้ตรวจเอง, การเคลื่อนที่ให้ตรวจความเร็วและระยะทาง ไคลเอนต์: เมื่อได้รับผลที่เซิร์ฟเวอร์ปฏิเสธหรือแก้มา ให้ย้อนกลับไปใช้ค่านั้น
บนกราฟ สูงตลอดตั้งแต่แรก · จำนวนรายงานความเร็วการเคลื่อนที่ที่เป็นไปไม่ได้/รายงานการโดนที่ขัดกัน
จุดที่ต้องดู ให้เซิร์ฟเวอร์บันทึกตำแหน่งและการโดนที่ไคลเอนต์รายงานไว้ตามจริง แล้วคำนวณความเร็วการเคลื่อนที่จากรายงานตำแหน่งที่ต่อกัน นับรายงานที่เกินความเร็วสูงสุด และรายงานที่สองคนต่างบอกว่าตัวเองยิงโดนก่อน สัญญาณว่าใช่ เซิร์ฟเวอร์ส่งรายงานต่อให้ไคลเอนต์อื่นโดยไม่ตรวจสอบ และรายงานความเร็วที่เป็นไปไม่ได้หรือการโดนที่ขัดกันเกิดขึ้นสม่ำเสมอโดยไม่เกี่ยวกับแพตช์หรือพื้นที่ สัญญาณว่าไม่ใช่ เซิร์ฟเวอร์คำนวณหรือตรวจผลเองอยู่แล้ว: ไม่ใช่สาเหตุนี้ อาการวาร์ปในกรณีนั้นให้ดูแพ็กเก็ตหายหรือ interpolation buffer วิธีตรวจ ต้องมี log หรือเมตริกจากเซิร์ฟเวอร์/ไคลเอนต์เกม
แหล่งอ้างอิง 3 รายการ
ID sy-lockstep · ผู้รับผิดชอบหลัก พัฒนาเซิร์ฟเวอร์ (ทีมพัฒนาเกม) · ร่วมกับ พัฒนาไคลเอนต์ (ทีมพัฒนาเกม)
ในโครงสร้างที่ทุกคนคำนวณเทิร์นเดียวกันไปพร้อมกัน ถ้าอินพุตของคนหนึ่งช้า ทุกคนต้องรอ
ทำไม แต่ละเทิร์นต้องได้อินพุตของผู้เล่นครบทุกคนจึงจะคำนวณได้ → ผลคือ อินพุตของคนหนึ่งมาถึงช้าเพราะจิตเตอร์หรือแพ็กเก็ตหาย → บนหน้าจอ ทุกคนหยุดแวบพร้อมกัน ถ้าหนักจะขึ้นหน้าต่าง “กำลังรอผู้เล่น”
อาการ ค้าง , กระตุก , อินพุตดีเลย์
ปัจจัย จิตเตอร์, แพ็กเก็ตหาย, การหยุดชะงัก
ใครเจอ บางจุด/บางแชนแนล
เกิดเมื่อไร สุ่มเป็นครั้งคราว
ผู้รับผิดชอบ ผู้รับผิดชอบหลัก พัฒนาเซิร์ฟเวอร์ (ทีมพัฒนาเกม) · ร่วมกับ พัฒนาไคลเอนต์ (ทีมพัฒนาเกม)
งานฝั่งทีมพัฒนาเกม เซิร์ฟเวอร์: ปรับ input delay ตามปิงอัตโนมัติ, ตัดเฉพาะคนที่ช้าออกชั่วคราวให้คนที่เหลือเล่นต่อโดยไม่ต้องรอ ไคลเอนต์: ใช้ input delay ตามที่กำหนด, ถ้าเป็น P2P ที่ไม่มีเซิร์ฟเวอร์ตัวกลาง ให้ไคลเอนต์ที่เป็นโฮสต์รับหน้าที่ปรับ input delay และจัดการคนที่ช้าด้วย
ตัวเลขที่ควรรู้ ถ้าตั้ง input delay สั้นกว่า “เวลาที่อินพุตไปถึงอีกฝ่าย + จิตเตอร์” จะหยุดชะงักบ่อยขึ้น เวลาที่ไปถึงคือครึ่งหนึ่งของปิงถ้ารับส่งกันโดยตรง และประมาณครึ่งหนึ่งของผลรวมปิงของทั้งสองคนถ้าผ่านเซิร์ฟเวอร์ตัวกลาง
บนกราฟ พุ่งแบบสุ่มเป็นครั้งคราว · เวลารอแต่ละเทิร์น, ดีเลย์การมาถึงของอินพุตแยกตามผู้เล่น
จุดที่ต้องดู บันทึกเวลาที่อินพุตของผู้เล่นแต่ละคนมาถึงและเวลาที่เทิร์นหยุดรอ ในทุกเทิร์น แล้วดูว่าเทิร์นที่หยุดนั้นรออินพุตของใคร ถ้ามีเซิร์ฟเวอร์ตัวกลาง ดูจากช่วงห่างการมาถึงของแพ็กเก็ตอินพุตแยกตามผู้เล่นใน packet capture ฝั่งเซิร์ฟเวอร์ได้ด้วย สัญญาณว่าใช่ ทุกเทิร์นที่หยุด อินพุตของคนคนเดียวกันมาถึงช้ากว่า input delay และช่วงนั้นจิตเตอร์หรือแพ็กเก็ตหายของคนนั้นพุ่ง สัญญาณว่าไม่ใช่ อินพุตมาครบตรงเวลาแต่ยังหยุด: น่าจะเป็นเวลาคำนวณของ PC ที่ช้าที่สุดหรือปัญหาการประมวลผลบนเซิร์ฟเวอร์ ถ้าไม่หยุดแต่ผลบนสองจอต่างกัน คือผลการคำนวณไม่ตรงกัน (desync) ให้ดู “การคำนวณเส้นทางไม่ตรงกันในการซิงก์คำสั่ง” วิธีตรวจ ต้องมี log หรือเมตริกจากเซิร์ฟเวอร์/ไคลเอนต์เกม
แหล่งอ้างอิง 3 รายการ
ID sy-rollback · ผู้รับผิดชอบหลัก พัฒนาไคลเอนต์ (ทีมพัฒนาเกม)
แสดงผลไปก่อนโดยคาดการณ์อินพุตของอีกฝ่าย ถ้าผิดจะย้อนกลับไปคำนวณใหม่ ยิ่งปิงสูง ช่วงที่ต้องย้อนยิ่งยาว
ทำไม อีกฝ่ายเปลี่ยนอินพุต (ไม่ตรงกับที่คาดการณ์) → ผลคือ อินพุตจริงมาถึงช้าไปครึ่งหนึ่งของปิง จึงต้องย้อนกลับไปคำนวณใหม่เท่ากับช่วงนั้น → บนหน้าจอ ท่าทางของอีกฝ่ายกระโดดข้ามไปหลายเฟรม หรือเปลี่ยนไปกะทันหัน
อาการ วาร์ป
ปัจจัย ความหน่วง, จิตเตอร์
ใครเจอ เราคนเดียว
เกิดเมื่อไร ตอนทำแอ็กชันบางอย่าง, สุ่มเป็นครั้งคราว
ผู้รับผิดชอบ ผู้รับผิดชอบหลัก พัฒนาไคลเอนต์ (ทีมพัฒนาเกม)
งานฝั่งทีมพัฒนาเกม ผสม input delay 1–3 เฟรมเพื่อลดช่วงที่ต้องย้อน, ตั้งเพดานการย้อน
ตัวเลขที่ควรรู้ ปิง 100 ms (ทางเดียว 50 ms) ที่ 60 fps จะย้อนประมาณ 3 เฟรม ถ้าตั้ง input delay 2 เฟรม จะลดเหลือ 1 เฟรม
บนกราฟ พุ่งแบบสุ่มเป็นครั้งคราว · จำนวนเฟรมที่ย้อน, RTT (ปิง)
จุดที่ต้องดู ให้ไคลเอนต์บันทึกจำนวนเฟรมที่ย้อน, RTT ในตอนนั้น, ค่า input delay ที่ตั้งไว้ และเวลาที่ใช้ย้อนและคำนวณใหม่ ทุกครั้งที่ย้อน สัญญาณว่าใช่ จังหวะที่แจ้งว่าท่าทางอีกฝ่ายกระโดด จำนวนเฟรมที่ย้อนสูง และช่วงย้อนเฉลี่ยประมาณ (ดีเลย์ทางเดียว − input delay) ÷ เวลาต่อเฟรม และยิ่งปิงสูงยิ่งมาก สัญญาณว่าไม่ใช่ ช่วงย้อนสั้นแต่ยังกระตุก: น่าจะเป็นปัญหาประสิทธิภาพที่การคำนวณใหม่ใช้เวลาเกินหนึ่งเฟรม ถ้าย้อนแล้วผลบนสองจอยังต่างกันต่อไป คือผลการคำนวณไม่ตรงกัน (desync) วิธีตรวจ ต้องมี log หรือเมตริกจากเซิร์ฟเวอร์/ไคลเอนต์เกม
แหล่งอ้างอิง 2 รายการ
ID sy-no-timestamp · ผู้รับผิดชอบหลัก พัฒนาไคลเอนต์ (ทีมพัฒนาเกม) · ร่วมกับ พัฒนาเซิร์ฟเวอร์ (ทีมพัฒนาเกม)
ถ้าไม่ติดเวลาที่เกิดให้อีเวนต์จากเซิร์ฟเวอร์ แล้วเล่นทันทีที่ได้รับ จังหวะการแสดงผลจะไม่สม่ำเสมอตามจิตเตอร์ของเครือข่าย
ทำไม รันอีเวนต์ “เริ่มโจมตี” และ “เล่นเอฟเฟกต์” ทันทีที่มาถึง → ผลคือ แต่ละแพ็กเก็ตมาถึงในเวลาต่างกัน ช่วงห่างจึงไม่สม่ำเสมอ → บนหน้าจอ ท่าโจมตีต่อเนื่องเร็วบ้างช้าบ้าง, จังหวะแพตเทิร์นบอสไม่เหมือนเดิมทุกครั้ง
อาการ กระตุก , กรอเร็ว
ปัจจัย จิตเตอร์
ใครเจอ เราคนเดียว
เกิดเมื่อไร ตลอดเวลา
ผู้รับผิดชอบ ผู้รับผิดชอบหลัก พัฒนาไคลเอนต์ (ทีมพัฒนาเกม) · ร่วมกับ พัฒนาเซิร์ฟเวอร์ (ทีมพัฒนาเกม)
งานฝั่งทีมพัฒนาเกม ไคลเอนต์: เล่นตามเวลาที่ติดมากับอีเวนต์ (นัดเวลาอีเวนต์, interpolation buffer) เซิร์ฟเวอร์: ติดเวลาที่เกิด (เวลาเซิร์ฟเวอร์) ให้อีเวนต์ก่อนส่ง
บนกราฟ พุ่งแบบสุ่มเป็นครั้งคราว · ช่วงห่างการเล่นอีเวนต์, ช่วงห่างการมาถึงของแพ็กเก็ต
จุดที่ต้องดู จับคู่เวลาที่เกิดอีเวนต์ใน log ของเซิร์ฟเวอร์กับเวลาที่มาถึงและเวลาที่เล่นใน log ของไคลเอนต์ด้วยหมายเลขอีเวนต์ แล้วเทียบช่วงห่าง ใน dev build ลองใส่จิตเตอร์ (ค่าจิตเตอร์ของ tc netem, ดีเลย์ต่ำสุด/สูงสุดใน network emulation ของ Unreal) เพื่อจำลองอาการ สัญญาณว่าใช่ ช่วงห่างที่เกิดบนเซิร์ฟเวอร์คงที่ แต่ช่วงห่างการเล่นไม่สม่ำเสมอตามช่วงห่างการมาถึงทุกประการ สัญญาณว่าไม่ใช่ ช่วงห่างการมาถึงสม่ำเสมอแต่การเล่นไม่สม่ำเสมอ: น่าจะเป็นปัญหาเฟรมฝั่งไคลเอนต์ (เฟรมไทม์พุ่ง) ถ้าช่วงห่างที่เกิดบนเซิร์ฟเวอร์แกว่งตั้งแต่ต้น น่าจะเป็นทิกเกินงบเวลา วิธีตรวจ ต้องมี log หรือเมตริกจากเซิร์ฟเวอร์/ไคลเอนต์เกม
แหล่งอ้างอิง 5 รายการ
ID sy-double-tick · ผู้รับผิดชอบหลัก พัฒนาเซิร์ฟเวอร์ (ทีมพัฒนาเกม)
ถ้าเก็บคำขอรอจนถึงทิกถัดไปแล้วจึงประมวลผล และส่งผลลัพธ์ในทิกถัดจากนั้นอีก ช่วงห่างระหว่างทิกจะถูกบวกเพิ่มสองครั้ง
ทำไม คำขอที่ได้รับจะประมวลผลในทิกถัดไป → ผลคือ ผลการประมวลผลก็เก็บรวมไว้ส่งในทิกส่งถัดไป → บนหน้าจอ ปิงของเน็ตต่ำ แต่การตอบสนองช้าคงที่ประมาณ 1.5 เท่าของช่วงห่างระหว่างทิก ถ้าเซิร์ฟเวอร์ 10 ทิก จะเฉลี่ย 0.15 วินาที แย่สุด 0.2 วินาที
อาการ อินพุตดีเลย์
ปัจจัย ความหน่วง
ใครเจอ ทั้งเซิร์ฟเวอร์
เกิดเมื่อไร ตลอดเวลา
ผู้รับผิดชอบ ผู้รับผิดชอบหลัก พัฒนาเซิร์ฟเวอร์ (ทีมพัฒนาเกม)
งานฝั่งทีมพัฒนาเกม ส่งคำตอบทันทีในทิกที่ประมวลผล, เพิ่มทิกเรต, คำตอบที่สำคัญให้ส่งทันที
ตัวเลขที่ควรรู้ เซิร์ฟเวอร์ 10 ทิกมีหนึ่งทิกเท่ากับ 100 ms การรอทิกอย่างเดียวจึงเพิ่มเฉลี่ย 150 ms แย่สุด 200 ms ถ้ารอครั้งเดียว เฉลี่ยจะเป็น 50 ms
บนกราฟ สูงตลอดตั้งแต่แรก · เวลาตั้งแต่คำขอมาถึงจนส่งคำตอบ
จุดที่ต้องดู ใน packet capture ฝั่งเซิร์ฟเวอร์ วัดช่วงห่างระหว่างเวลาที่แพ็กเก็ตคำขอมาถึงกับเวลาที่แพ็กเก็ตคำตอบออกไป ขณะที่บัญชีทดสอบทำแอ็กชันเดิมซ้ำหลายครั้ง (เช่น ใช้ไอเทม) ถ้ามี log ของเซิร์ฟเวอร์ ให้ดูเวลาที่คำขอมาถึง, หมายเลขทิกที่ประมวลผล และเวลาที่ส่งคำตอบ สัญญาณว่าใช่ เวลาที่ใช้ภายในเซิร์ฟเวอร์เฉลี่ยประมาณ 1.5 เท่า สูงสุดประมาณ 2 เท่าของช่วงห่างระหว่างทิก และคงที่โดยไม่ขึ้นกับ RTT สัญญาณว่าไม่ใช่ เวลาภายในเซิร์ฟเวอร์อยู่ราวครึ่งหนึ่งของช่วงห่างระหว่างทิก: รอทิกแค่ครั้งเดียว ถ้านานกว่าช่วงห่างระหว่างทิกแบบไม่สม่ำเสมอ ให้ดูทิกเกินงบเวลา วิธีตรวจ ใช้เครื่องมือฝั่งอินฟรา (ไม่ต้องใช้โค้ดเกม)
แหล่งอ้างอิง 3 รายการ
ID sy-strict-check · ผู้รับผิดชอบหลัก พัฒนาเซิร์ฟเวอร์ (ทีมพัฒนาเกม)
ถ้าเซิร์ฟเวอร์ตรวจความเร็วการเคลื่อนที่, คูลดาวน์ และระยะเข้มงวดเกินไป จะปฏิเสธแม้อินพุตปกติที่มาถึงรวมกันเพราะจิตเตอร์
ทำไม เกณฑ์ที่เข้มงวด เช่น “ระยะที่เคลื่อนที่ได้ในหนึ่งทิก” หรือ “ยอมให้คูลดาวน์คลาดได้ 0 ms” → ผลคือ เมื่อคำสั่งสองคำสั่งมาถึงรวมกันในทิกเดียวเพราะจิตเตอร์ จะถูกตัดสินว่าผิดกฎ → บนหน้าจอ โดนดีดกลับ, คูลดาวน์ครบแล้วแต่สกิลถูกปฏิเสธ
อาการ ดีดกลับ , กดไม่ติด/โรลแบ็ค
ปัจจัย จิตเตอร์
ใครเจอ เราคนเดียว
เกิดเมื่อไร สุ่มเป็นครั้งคราว, ระหว่างเดินทาง/ย้ายแมพ
ผู้รับผิดชอบ ผู้รับผิดชอบหลัก พัฒนาเซิร์ฟเวอร์ (ทีมพัฒนาเกม)
งานฝั่งทีมพัฒนาเกม ตรวจแบบโควตาสะสม (token bucket), เผื่อระยะไว้เท่ากับปิงและจิตเตอร์
บนกราฟ พุ่งแบบสุ่มเป็นครั้งคราว · จำนวนครั้งที่เซิร์ฟเวอร์ปฏิเสธจากการตรวจสอบ/แก้ตำแหน่ง
จุดที่ต้องดู บันทึกสาเหตุ, จำนวนคำสั่งของผู้เล่นคนนั้นที่มาถึงในทิกนั้น และช่วงห่างการมาถึงจากคำสั่งก่อนหน้า ทุกครั้งที่ปฏิเสธหรือแก้ตำแหน่ง ลงใน log ของเซิร์ฟเวอร์ สัญญาณว่าใช่ การปฏิเสธและการแก้ตำแหน่งกระจุกในจังหวะที่มีคำสั่งตั้งแต่ 2 คำสั่งมาถึงรวมกันในทิกเดียว แต่ปริมาณการเคลื่อนที่และจำนวนครั้งที่ใช้เมื่อรวมเป็นช่วงหลายวินาทียังอยู่ในกฎ สัญญาณว่าไม่ใช่ รวมเป็นช่วงหลายวินาทีแล้วยังเกินกฎ: อาจเป็นการเคลื่อนที่เร็วเกินจริงหรือการโกง ถ้าการปฏิเสธกระจุกที่บาง ISP และช่วงหัวค่ำ น่าจะเป็น “false positive ของการตรวจสอบที่กระจุกกับผู้ใช้บาง ISP” วิธีตรวจ ต้องมี log หรือเมตริกจากเซิร์ฟเวอร์/ไคลเอนต์เกม
แหล่งอ้างอิง 2 รายการ
ID sy-host · ผู้รับผิดชอบหลัก พัฒนาเซิร์ฟเวอร์ (ทีมพัฒนาเกม) · ร่วมกับ พัฒนาไคลเอนต์ (ทีมพัฒนาเกม), อินฟราเซิร์ฟเวอร์ (ทีมอินฟรา)
ถ้า PC ของผู้เล่นคนหนึ่งทำหน้าที่เป็นเซิร์ฟเวอร์ เน็ตและสเปก PC ของคนนั้นจะกำหนดฟีลการเล่นของทุกคน
ทำไม PC ของหัวห้องทำหน้าที่เป็นเซิร์ฟเวอร์ (P2P, listen server) → ผลคือ ถ้าเน็ตหรือ PC ของหัวห้องช้า จะส่งผลไปถึงทุกคน ส่วนหัวห้องปิง 0 → บนหน้าจอ หัวห้องได้เปรียบคนเดียว ถ้าหัวห้องออก ทุกคนค้างหรือหลุด
อาการ กระตุก , ค้าง , หลุด
ปัจจัย ความหน่วง, การหยุดชะงัก
ใครเจอ บางจุด/บางแชนแนล
เกิดเมื่อไร สุ่มเป็นครั้งคราว
ผู้รับผิดชอบ ผู้รับผิดชอบหลัก พัฒนาเซิร์ฟเวอร์ (ทีมพัฒนาเกม) · ร่วมกับ พัฒนาไคลเอนต์ (ทีมพัฒนาเกม), อินฟราเซิร์ฟเวอร์ (ทีมอินฟรา)
งานฝั่งทีมพัฒนาเกม เซิร์ฟเวอร์: เปลี่ยนไปใช้ dedicated server ที่รับหน้าที่ตัดสินผล ระหว่างนั้นให้เลือกคนที่เน็ตและ PC ดีเป็นหัวห้องตอนจับคู่ ไคลเอนต์: รองรับการย้ายโฮสต์ (host migration), ตอนจับคู่ให้วัดปิงกับผู้เล่นคนอื่น ความเร็วอัปโหลด และสเปก PC แล้วส่งไป
งานฝั่งทีมอินฟรา เตรียมเครื่องเซิร์ฟเวอร์/อินสแตนซ์สำหรับ dedicated server, วางไว้ใกล้พื้นที่ที่มีผู้เล่นมาก
บนกราฟ สูงเฉพาะบางกลุ่ม · จำนวนการแจ้งแลค/การหลุดแยกตามหัวห้อง
จุดที่ต้องดู บันทึกความเร็วอัปโหลดของหัวห้อง (โฮสต์), RTT ระหว่างผู้เล่นแต่ละคนกับหัวห้อง, เฟรมไทม์ของ PC หัวห้อง และเวลาที่หัวห้องออก ลงใน log ของแมตช์ แล้วจัดกลุ่มการแจ้งแลคและการหลุดตามหัวห้อง ผู้เล่นเองก็ตรวจได้โดยเล่นใหม่กับคนกลุ่มเดิมแต่เปลี่ยนแค่หัวห้อง สัญญาณว่าใช่ แลคและการหลุดกระจุกอยู่ในห้องของหัวห้องบางคน เมื่อความเร็วอัปโหลดของหัวห้องคนนั้นต่ำหรือเฟรมไทม์ยาว ผู้เล่นทุกคนแย่ลงพร้อมกัน และถ้าไม่มีการย้ายโฮสต์ ทุกคนหลุดทันทีที่หัวห้องออก สัญญาณว่าไม่ใช่ แย่เฉพาะผู้เล่นในพื้นที่เดียวกันโดยไม่เกี่ยวกับหัวห้อง: น่าจะเป็นปัญหาเน็ตหรือเส้นทาง ถ้าเป็นโครงสร้าง dedicated server ไม่ใช่สาเหตุนี้ วิธีตรวจ ต้องมี log หรือเมตริกจากเซิร์ฟเวอร์/ไคลเอนต์เกม
แหล่งอ้างอิง 3 รายการ
ID sy-optimistic-reject · ผู้รับผิดชอบหลัก พัฒนาไคลเอนต์ (ทีมพัฒนาเกม) · ร่วมกับ พัฒนาเซิร์ฟเวอร์ (ทีมพัฒนาเกม)
ถ้าการโจมตีหรือสกิลที่จอเราแสดงไปก่อนแล้วถูกเซิร์ฟเวอร์ปฏิเสธทีหลัง ผลที่เห็นกับตาจะกลายเป็นเหมือนไม่เคยเกิดขึ้น
ทำไม เล่นเอฟเฟกต์การโจมตีและท่าสกิลก่อนเซิร์ฟเวอร์ยืนยัน (การแสดงผลล่วงหน้า) → ผลคือ เซิร์ฟเวอร์ตรวจระยะ, ตำแหน่งเป้า, คูลดาวน์ และทรัพยากรอีกครั้งแล้วปฏิเสธ → บนหน้าจอ เลือดกระเด็นแต่ไม่มีดาเมจ, ท่าสกิลออกแต่ไม่มีผล, มีแต่คูลดาวน์ที่เดิน
อาการ กดไม่ติด/โรลแบ็ค , ดีดกลับ
ปัจจัย ความหน่วง
ใครเจอ เราคนเดียว, เฉพาะบางฟีเจอร์
เกิดเมื่อไร ตอนทำแอ็กชันบางอย่าง
ผู้รับผิดชอบ ผู้รับผิดชอบหลัก พัฒนาไคลเอนต์ (ทีมพัฒนาเกม) · ร่วมกับ พัฒนาเซิร์ฟเวอร์ (ทีมพัฒนาเกม)
งานฝั่งทีมพัฒนาเกม ไคลเอนต์: แสดงผลจากเซิร์ฟเวอร์เฉพาะส่วนที่ต้องยืนยัน เช่น ตัวเลขดาเมจ, การตาย และของรางวัล, ตรวจสาเหตุการปฏิเสธที่พบบ่อยไว้ก่อน, ถ้าถูกปฏิเสธให้คืนคูลดาวน์และทรัพยากรแล้วแสดงเหตุผล เซิร์ฟเวอร์: เผื่อระยะในการตรวจระยะและตำแหน่งเป้าไว้เท่ากับปิง, ใส่สาเหตุในคำตอบปฏิเสธ, เก็บอัตราการปฏิเสธแยกตามสกิลเป็นเมตริก
ตัวเลขที่ควรรู้ คำตอบปฏิเสธมาถึงหลังกดช้าไปเท่ากับปิง + เวลารอทิก ถ้าปิง 150 ms จะ “นึกว่าโดนแล้ว” อยู่ประมาณ 0.2 วินาที
บนกราฟ สูงเฉพาะบางกลุ่ม · อัตราที่เซิร์ฟเวอร์ปฏิเสธแยกตามสกิล (แยกตามช่วงปิง)
จุดที่ต้องดู เก็บอัตราการปฏิเสธและสาเหตุ (ระยะ, ตำแหน่งเป้า, คูลดาวน์, ทรัพยากร) แยกตามสกิลที่เซิร์ฟเวอร์ แล้วแบ่งตามช่วง RTT ของผู้เล่น ฝั่งไคลเอนต์ให้บันทึกจำนวนครั้งที่การกระทำที่แสดงผลล่วงหน้าถูกปฏิเสธ สัญญาณว่าใช่ การปฏิเสธกระจุกที่บางสกิลและสาเหตุเรื่องระยะหรือตำแหน่งเป้า และยิ่งปิงสูง อัตราการปฏิเสธยิ่งสูง สัญญาณว่าไม่ใช่ สาเหตุการปฏิเสธเป็นคูลดาวน์หรือทรัพยากรและไม่เกี่ยวกับปิง: ให้ดูว่าค่าข้อมูล (คูลดาวน์, ค่าใช้จ่าย) ของไคลเอนต์กับเซิร์ฟเวอร์ต่างกันหรือไม่ ถ้าไม่มีการปฏิเสธแต่การแสดงผลเริ่มหลังเซิร์ฟเวอร์ตอบเท่านั้น น่าจะเป็น “แสดงผลหลังเซิร์ฟเวอร์ตอบเท่านั้น (แบบ request-response)” วิธีตรวจ ต้องมี log หรือเมตริกจากเซิร์ฟเวอร์/ไคลเอนต์เกม
รายละเอียดเพิ่มเติม การแสดงผลล่วงหน้าเป็นวิธีที่ดีที่สุดในการกลบปิง แต่ยิ่งข้อมูลที่ไคลเอนต์กับเซิร์ฟเวอร์ใช้ตัดสิน (ตำแหน่งอีกฝ่าย, ทรัพยากรที่เหลือ) ต่างกันมาก ก็ยิ่งถูกปฏิเสธบ่อย ถ้าเก็บอัตราการปฏิเสธแยกตามสกิลเป็นเมตริกไว้ จะหาจุดที่การตัดสินคลาดกันได้ง่าย
แหล่งอ้างอิง 2 รายการ
ID sy-path-mismatch · ผู้รับผิดชอบหลัก พัฒนาเซิร์ฟเวอร์ (ทีมพัฒนาเกม) · ร่วมกับ พัฒนาไคลเอนต์ (ทีมพัฒนาเกม)
ถ้ารับส่งแค่ “ให้ไปที่นี่” แล้วแต่ละฝั่งคำนวณเส้นทางเอง เมื่อการคำนวณต่างกันแม้เพียงเล็กน้อย ตัวละครหรือมอนสเตอร์จะเดินไปคนละเส้นทางแล้วถูกดึงกลับมาที่ตำแหน่งที่ถูกต้อง
ทำไม การเดินแบบคลิกและการไล่ตามของมอนสเตอร์ ส่งแค่จุดหมาย และไคลเอนต์คำนวณเส้นทางแยกเอง → ผลคือ ข้อมูลภูมิประเทศต่างกัน, การชนกับตัวละครอื่น และลำดับการคำนวณที่ต่างกัน ทำให้เดินคนละเส้นทางกับเซิร์ฟเวอร์ → บนหน้าจอ มอนสเตอร์เดินทะลุกำแพงแล้ววืดไปอยู่อีกที่, ตัวละครที่คลิกเดินเลี้ยวเหมือนไถลไป
อาการ วาร์ป , ดีดกลับ
ปัจจัย ความหน่วง
ใครเจอ บางจุด/บางแชนแนล, เราคนเดียว
เกิดเมื่อไร ระหว่างเดินทาง/ย้ายแมพ
ผู้รับผิดชอบ ผู้รับผิดชอบหลัก พัฒนาเซิร์ฟเวอร์ (ทีมพัฒนาเกม) · ร่วมกับ พัฒนาไคลเอนต์ (ทีมพัฒนาเกม)
งานฝั่งทีมพัฒนาเกม เซิร์ฟเวอร์: ส่งจุดกลางทาง (waypoint) ของเส้นทางไปด้วย, ซิงก์ตำแหน่งเป็นระยะ ไคลเอนต์: ค่อย ๆ ปรับส่วนที่คลาดให้เข้าที่อย่างนุ่มนวล, ใช้ข้อมูลภูมิประเทศชุดเดียวกับเซิร์ฟเวอร์
บนกราฟ พุ่งแบบสุ่มเป็นครั้งคราว · จำนวนครั้งและระยะการแก้ตำแหน่งแยกตามเอนทิตี
จุดที่ต้องดู บันทึกความต่างระหว่างตำแหน่งที่เซิร์ฟเวอร์ส่งมากับตำแหน่งที่ไคลเอนต์คำนวณ ของแต่ละเอนทิตี แล้วปักพิกัดที่เกิดการแก้ตำแหน่งลงบนแผนที่ ถ้าสรุปผลเส้นทางหรือตำแหน่งของทั้งสองฝั่งเป็น checksum แล้วเทียบเป็นระยะ จะหาจังหวะที่เริ่มคลาดได้ สัญญาณว่าใช่ การแก้ตำแหน่งกระจุกอยู่ที่ภูมิประเทศบางแบบ (ขอบต่างระดับ, ทางแคบ, ทางลาด) หรือที่ที่คนแน่น และเกิดซ้ำที่จุดเดิมแม้กับผู้เล่นที่เมตริกเครือข่ายปกติ สัญญาณว่าไม่ใช่ แก้ตำแหน่งเฉพาะจังหวะที่แพ็กเก็ตหายหรือจิตเตอร์พุ่งโดยไม่เกี่ยวกับสถานที่: น่าจะเป็นปัญหาเน็ต ถ้ามอนสเตอร์ตัวเดียวกระโดดบนจอของหลายคนพร้อมกัน ให้ดูว่าสิทธิ์ควบคุมมอนสเตอร์อยู่ที่ไคลเอนต์ที่ช้าหรือไม่ วิธีตรวจ ต้องมี log หรือเมตริกจากเซิร์ฟเวอร์/ไคลเอนต์เกม
รายละเอียดเพิ่มเติม วิธีนี้เป็นเหตุผลหนึ่งที่เกมคลิกเดินและเกม tab target ไม่ค่อยไวต่อปิง แต่ไม่มีอะไรรับประกันว่าผลทั้งสองฝั่งจะตรงกัน จึงจำเป็นต้องมีกลไกปรับตำแหน่งให้ตรงกันเป็นครั้งคราว การคำนวณแบบ floating point อาจให้ผลต่างกันเล็กน้อยตามชนิด CPU, คอมไพเลอร์ และการตั้งค่า optimization ของคอมไพเลอร์ (รวมถึงความต่างระหว่าง debug build กับ release build) ในโครงสร้างที่รับส่งแค่อินพุตและถือว่าผลการคำนวณทั้งสองฝั่งเหมือนกันทุกประการ อย่าง lockstep และ rollback ความต่างเล็ก ๆ นี้อาจสะสมจนสถานะเกมบนสองจอแยกออกจากกัน (desync)
แหล่งอ้างอิง 6 รายการ Deterministic Lockstep Gaffer On Games แม้จะ deterministic บนเครื่องเดียวกัน ถ้าคอมไพเลอร์, OS หรือ CPU ต่างกัน ผล floating point ก็อาจต่างกัน State Synchronization Gaffer On Games ถ้าส่งสถานะไปพร้อมอินพุต ก็ปรับทั้งสองฝั่งให้ตรงกันได้โดยไม่ต้อง deterministic สมบูรณ์ Peeking into VALORANT's Netcode Riot Games เมื่อแพ็กเก็ตหาย หรือตัวละครสองตัวพยายามไปที่จุดเดียวกัน simulation ของเซิร์ฟเวอร์กับไคลเอนต์จะคลาดกันจนต้องแก้ 1500 Archers on a 28.8: Network Programming in Age of Empires and Beyond Game Developer ความต่างเล็กมากขยายใหญ่ขึ้นตามเวลา จนเส้นทางของคนงาน (worker) ค่อย ๆ คลาด, เทียบโลก, เอนทิตี และ pathfinding ด้วย checksum เพื่อหาการคลาด (out-of-sync) Floating Point Determinism Gaffer On Games โค้ด floating point เดียวกันอาจให้ผลต่างกันตามคอมไพเลอร์, สถาปัตยกรรม CPU และ debug/release build, มีกรณีที่ CPU ของ AMD และ Intel ให้ค่าฟังก์ชัน transcendental ต่างกันเล็กน้อย /fp (Specify floating-point behavior) Microsoft /fp:fast อาจสลับหรือรวมลำดับการคำนวณ floating point จนผลต่างจากการตั้งค่า /fp แบบอื่น และการคำนวณที่รวมด้วย FMA ก็อาจต่างจากการคูณแล้วบวกแยกกัน
ID sy-low-send-rate · ผู้รับผิดชอบหลัก พัฒนาเซิร์ฟเวอร์ (ทีมพัฒนาเกม) · ร่วมกับ พัฒนาไคลเอนต์ (ทีมพัฒนาเกม)
ถ้าเซิร์ฟเวอร์ส่งอัปเดตตำแหน่ง (สแนปช็อต) แค่ไม่กี่ครั้งใน 1 วินาที ต้องตั้ง interpolation buffer ให้ยาวตามไปด้วย จึงเห็นตัวละครอื่นเป็นภาพในอดีตที่ไกลขึ้น
ทำไม ส่งอัปเดตตำแหน่งแค่ 5–10 ครั้งใน 1 วินาทีเพื่อประหยัดปริมาณการส่ง → ผลคือ ถ้าจะวาดให้ลื่น ต้องตั้งบัฟเฟอร์เป็น 2 เท่าของช่วงห่างแพ็กเก็ต (200–400 ms) ถ้าตั้งสั้น พลาดแพ็กเก็ตเดียวตัวละครก็หยุดนิ่ง → บนหน้าจอ เห็นอีกฝ่ายเปลี่ยนทิศช้าและไม่ตรงกับการตัดสินผล ถ้าบัฟเฟอร์สั้นจะกระตุก และวาร์ปเมื่อแพ็กเก็ตหาย
อาการ กระตุก , วาร์ป , กดไม่ติด/โรลแบ็ค
ปัจจัย ความหน่วง, แพ็กเก็ตหาย
ใครเจอ ทั้งเซิร์ฟเวอร์
เกิดเมื่อไร ตลอดเวลา
ผู้รับผิดชอบ ผู้รับผิดชอบหลัก พัฒนาเซิร์ฟเวอร์ (ทีมพัฒนาเกม) · ร่วมกับ พัฒนาไคลเอนต์ (ทีมพัฒนาเกม)
งานฝั่งทีมพัฒนาเกม เซิร์ฟเวอร์: เป้าหมายที่อยู่ใกล้หรือกำลังต่อสู้ให้ส่งบ่อย ที่อยู่ไกลให้ส่งห่าง, ส่งเฉพาะส่วนที่เปลี่ยน (delta compression) เพื่อลดขนาดต่อครั้งแล้วเพิ่มความถี่ ไคลเอนต์: ปรับความยาว interpolation buffer ตามช่วงห่างแพ็กเก็ตอัตโนมัติ
ตัวเลขที่ควรรู้ ถ้า 10 ครั้งใน 1 วินาที ช่วงห่างแพ็กเก็ตคือ 100 ms บัฟเฟอร์ 200 ms บวกดีเลย์ทางเดียว 75 ms ของปิง 150 ms จะเห็นอีกฝ่ายย้อนหลังไปประมาณ 0.3 วินาที
บนกราฟ สูงตลอดตั้งแต่แรก · ช่วงห่างการมาถึงของแพ็กเก็ตแยกตามไคลเอนต์, ความยาว interpolation buffer
จุดที่ต้องดู ใน packet capture ฝั่งเซิร์ฟเวอร์ กรองเฉพาะ flow ที่ไปหาผู้เล่นคนหนึ่ง แล้วดูจำนวนแพ็กเก็ตต่อวินาทีและช่วงห่างด้วย I/O Graphs ของ Wireshark ถ้ามี log ฝั่งเกม ให้ดูช่วงห่างการอัปเดตแยกตามเอนทิตีควบคู่กับระยะเผื่อของ interpolation buffer บนไคลเอนต์ (เวลาที่เหลือจนสแนปช็อตถัดไปมาถึง) สัญญาณว่าใช่ อัปเดตตำแหน่งห่างตลอดที่ 5–10 ครั้งต่อวินาที (ช่วงห่าง 100–200 ms) และตั้ง interpolation buffer ไว้เกิน 200 ms หรือระยะเผื่อของบัฟเฟอร์เหลือ 0 บ่อย สัญญาณว่าไม่ใช่ ส่งอัปเดตถี่แล้วแต่ช่วงห่างการมาถึงแกว่ง: น่าจะเป็นจิตเตอร์หรือแพ็กเก็ตหาย ถ้าตอนคนแน่นได้รับอัปเดตห่างเฉพาะเอนทิตีที่อยู่ไกล น่าจะเป็น “งบการส่ง/ลำดับความสำคัญต่อการเชื่อมต่อ” วิธีตรวจ ใช้เครื่องมือฝั่งอินฟรา (ไม่ต้องใช้โค้ดเกม)
แหล่งอ้างอิง 4 รายการ
ปัญหาที่เกิดกับบางคนเท่านั้น
24 สาเหตุ · บทในฉบับหลัก
ID pt-slow-burst · ผู้รับผิดชอบหลัก พัฒนาเซิร์ฟเวอร์ (ทีมพัฒนาเกม) · ร่วมกับ ภายนอก (ภายนอก)
อินพุตของคนที่เน็ตไม่ดีจะไปถึงเซิร์ฟเวอร์แบบไม่สม่ำเสมอและมาเป็นกลุ่ม ถ้าเซิร์ฟเวอร์ใช้คำสั่งตามที่ได้รับในแต่ละทิก คนอื่นจะเห็นตัวละครนั้นหยุดแวบแล้วเดินหลายก้าวในทีเดียว
ทำไม คำสั่งเคลื่อนที่ของคนที่ช้า บางทิกมาถึง 0 คำสั่ง บางทิกมา 2–3 คำสั่ง → ผลคือ เซิร์ฟเวอร์ใช้คำสั่งทั้งหมดในทิกที่ได้รับ ตำแหน่งของตัวละครนั้นจึงเปลี่ยนเป็นขั้นบันได → บนหน้าจอ บนจอคนอื่น ตัวละครนั้นตัวเดียวหยุดแวบแล้วขยับรวดเดียวแบบกรอเร็ว ที่เหลือปกติ
อาการ กรอเร็ว , วาร์ป
ปัจจัย จิตเตอร์, แพ็กเก็ตหาย
ใครเจอ เห็นตัวละครบางตัวผิดปกติ, บางพื้นที่/บาง ISP
เกิดเมื่อไร ตลอดเวลา, ระหว่างเดินทาง/ย้ายแมพ
ผู้รับผิดชอบ ผู้รับผิดชอบหลัก พัฒนาเซิร์ฟเวอร์ (ทีมพัฒนาเกม) · ร่วมกับ ภายนอก (ภายนอก)
งานฝั่งทีมพัฒนาเกม ใช้บัฟเฟอร์อินพุตของผู้เล่นแต่ละคนกระจายคำสั่งไปใช้อย่างสม่ำเสมอ, ดู sequence number ของอินพุตแล้วใช้ตามช่วงห่างเดิม, การเพิ่มแค่ interpolation buffer บนจอคนอื่นไม่พอ (เพราะประวัติตำแหน่งบนเซิร์ฟเวอร์เองเป็นขั้นบันไดอยู่แล้ว)
งานฝั่งภายนอก แนะนำผู้เล่นที่ช้าให้ใช้สาย LAN และตรวจ Wi-Fi/เราเตอร์
ตัวเลขที่ควรรู้ ถ้าจิตเตอร์ 80 ms บนเซิร์ฟเวอร์ 20 ทิก (50 ms) จำนวนคำสั่งต่อทิกจะแกว่งระหว่าง 0–3 คำสั่ง
บนกราฟ สูงเฉพาะบางกลุ่ม · จำนวนคำสั่งที่ใช้ต่อทิกแยกตามผู้เล่น, จิตเตอร์แยกตามผู้เล่น
จุดที่ต้องดู ใน packet capture ฝั่งเซิร์ฟเวอร์ กรองเฉพาะแพ็กเก็ตที่ผู้เล่นที่ถูกแจ้งส่งมา แล้วนับว่ามาถึงกี่แพ็กเก็ตในแต่ละช่วงทิก (เช่น 50 ms) และเทียบกับผู้เล่นคนอื่น ถ้ามี log ของเซิร์ฟเวอร์ ให้ดูจำนวนคำสั่งเคลื่อนที่ที่ใช้ในแต่ละทิกและ sequence number ของอินพุตแยกตามผู้เล่น สัญญาณว่าใช่ เฉพาะแพ็กเก็ตของผู้เล่นที่ถูกแจ้งที่มาถึงเป็นกลุ่มสลับระหว่าง 0 กับ 2–3 แพ็กเก็ตต่อทิก และจิตเตอร์/แพ็กเก็ตหายของผู้เล่นคนนั้นสูง ขณะที่แพ็กเก็ตของผู้เล่นคนอื่นมาสม่ำเสมอ ถ้าผู้เล่นคนนั้นเปลี่ยนไปใช้สาย LAN อาการจะลดลง สัญญาณว่าไม่ใช่ หลายตัวละครขยับรวดเดียวพร้อมกัน: น่าจะเป็นทิกของเซิร์ฟเวอร์ล่าช้าหรือเน็ตของฝั่งคนดู ถ้าการมาถึงและการใช้คำสั่งสม่ำเสมอแต่ตัวละครนั้นยังดูกระโดด น่าจะเป็นปัญหา interpolation หรือการแสดงผลของฝั่งคนดู วิธีตรวจ ใช้เครื่องมือฝั่งอินฟรา (ไม่ต้องใช้โค้ดเกม)
รายละเอียดเพิ่มเติม ในโครงสร้าง server authoritative นี่คือพฤติกรรมปกติ แลคของคนที่ช้าคนเดียวจะแสดงให้คนอื่นเห็นแค่เป็น “คนนั้นขยับแปลก ๆ” และไม่กระทบการควบคุมของคนอื่นหรือการเคลื่อนที่ของมอนสเตอร์ แต่สิ่งที่ต้องโต้ตอบกับคนนั้นโดยตรง (เทรด, กิมมิกปาร์ตี้, การตัดสินผล PvP) จะช้าตามไปด้วย
แหล่งอ้างอิง 3 รายการ Peeking into VALORANT's Netcode Riot Games เซิร์ฟเวอร์ใส่อินพุตที่มาถึงลงในคิวการเคลื่อนที่ของผู้เล่นแต่ละคนตามลำดับทิก และถ้าคิวว่างจะเติมด้วยการคาดการณ์ การแก้ตำแหน่งจะเห็นเฉพาะผู้เล่นคนนั้น คนอื่นเห็นลื่นไหล State Synchronization Gaffer On Games แม้แพ็กเก็ตที่ส่ง 60 ครั้งต่อวินาที ก็มาถึงเป็นกลุ่ม เช่น เฟรมหนึ่ง 2 แพ็กเก็ต เฟรมถัดไป 0 แพ็กเก็ต Source SDK 2013: player.cpp Valve กระจายคำสั่งที่มาถึงเป็นกลุ่มไปประมวลผลตามทิกของเซิร์ฟเวอร์ (meter out)
ID pt-event-server · ผู้รับผิดชอบหลัก พัฒนาเซิร์ฟเวอร์ (ทีมพัฒนาเกม) · ร่วมกับ พัฒนาไคลเอนต์ (ทีมพัฒนาเกม)
บนเซิร์ฟเวอร์ที่ประมวลผลและแจ้งผลทันทีที่แพ็กเก็ตมาถึง การกระทำของคนที่ช้าซึ่งมาถึงเป็นกลุ่มจะถูกรันทันทีต่อเนื่องกัน
ทำไม คำขอสกิลและการเคลื่อนที่ของคนที่ช้ามาถึงเป็นกลุ่ม → ผลคือ เซิร์ฟเวอร์รันตามลำดับทันทีที่ได้รับ และแจ้งทุกคนทันที → บนหน้าจอ คนอื่นเห็นคนนั้นใช้สกิลหลายสกิลในพริบตาเดียว หรือขยับเหมือนกดกรอ
อาการ กรอเร็ว
ปัจจัย จิตเตอร์
ใครเจอ เห็นตัวละครบางตัวผิดปกติ
เกิดเมื่อไร ตอนทำแอ็กชันบางอย่าง, ตลอดเวลา
ผู้รับผิดชอบ ผู้รับผิดชอบหลัก พัฒนาเซิร์ฟเวอร์ (ทีมพัฒนาเกม) · ร่วมกับ พัฒนาไคลเอนต์ (ทีมพัฒนาเกม)
งานฝั่งทีมพัฒนาเกม เซิร์ฟเวอร์: รันตามช่วงห่างของเวลาอินพุตที่ติดมากับการกระทำ (ยอมรับเวลานั้นเฉพาะเมื่ออยู่ในช่วงที่อนุญาต) หรือรับการกระทำที่มาเป็นกลุ่มไว้แล้วรันทีละอย่างโดยเว้นช่วงห่างขั้นต่ำ (global cooldown), อย่าตรวจคูลดาวน์จากเวลาที่มาถึงอย่างเดียว (อินพุตปกติจะกดไม่ติด) ไคลเอนต์: ติดเวลาอินพุตให้การกระทำก่อนส่ง
บนกราฟ สูงเฉพาะบางกลุ่ม · ช่วงห่างการรันการกระทำแยกตามผู้เล่น
จุดที่ต้องดู บันทึกเวลาที่การกระทำของผู้เล่นแต่ละคนมาถึง, เวลาที่รัน และเวลาอินพุตที่ไคลเอนต์ติดมา (ถ้ามี) ลงใน log ของเซิร์ฟเวอร์ แล้วเทียบช่วงห่างการรันกับช่วงห่างอินพุต ดูช่วงห่างการมาถึงของแพ็กเก็ตจากผู้เล่นคนนั้นใน packet capture ฝั่งเซิร์ฟเวอร์ประกอบด้วย สัญญาณว่าใช่ ช่วงห่างอินพุตปกติ แต่ช่วงห่างการมาถึงและการรันบนเซิร์ฟเวอร์อัดกันเหลือไม่กี่ ms และจังหวะที่อัดกันตรงกับเวลาที่คนอื่นแจ้งว่าเห็นอาการกรอเร็ว สัญญาณว่าไม่ใช่ ช่วงห่างของเวลาอินพุตอัดกันตั้งแต่ต้น: น่าจะเป็นที่ไคลเอนต์หรือมาโคร ถ้าช่วงห่างการรันบนเซิร์ฟเวอร์สม่ำเสมอแต่ดูอัดกันเฉพาะบนจอคนอื่น น่าจะเป็นเน็ตของคนดู วิธีตรวจ ต้องมี log หรือเมตริกจากเซิร์ฟเวอร์/ไคลเอนต์เกม
แหล่งอ้างอิง 2 รายการ
ID pt-input-buffer · ผู้รับผิดชอบหลัก พัฒนาเซิร์ฟเวอร์ (ทีมพัฒนาเกม) · ร่วมกับ พัฒนาไคลเอนต์ (ทีมพัฒนาเกม)
ถ้าเซิร์ฟเวอร์เก็บอินพุตของแต่ละคนไว้เล็กน้อยแล้วดึงมาใช้ทิกละหนึ่งอัน คนอื่นจะเห็นลื่นไหล แต่จังหวะที่การกระทำของเจ้าตัวถูกยืนยันบนเซิร์ฟเวอร์จะช้าลงตามไปด้วย
ทำไม เซิร์ฟเวอร์เก็บอินพุตของคนที่ช้าไว้ในบัฟเฟอร์ แล้วใช้ทิกละหนึ่งอัน → ผลคือ ถ้าบัฟเฟอร์เล็กจะว่างบ่อย ตัวละครนั้นยืนนิ่งอยู่กับที่หรือเซิร์ฟเวอร์เดาจากอินพุตล่าสุดแล้วขยับให้ ถ้าบัฟเฟอร์ใหญ่ อินพุตของเจ้าตัวจะถูกยืนยันช้า → บนหน้าจอ ถ้าเล็ก คนอื่นเห็นหยุดแวบ ถ้าใหญ่ ผลสกิลของเจ้าตัวออกช้า (อินพุตดีเลย์)
อาการ กระตุก , อินพุตดีเลย์
ปัจจัย จิตเตอร์
ใครเจอ เห็นตัวละครบางตัวผิดปกติ, เราคนเดียว
เกิดเมื่อไร ตลอดเวลา
ผู้รับผิดชอบ ผู้รับผิดชอบหลัก พัฒนาเซิร์ฟเวอร์ (ทีมพัฒนาเกม) · ร่วมกับ พัฒนาไคลเอนต์ (ทีมพัฒนาเกม)
งานฝั่งทีมพัฒนาเกม เซิร์ฟเวอร์: ปรับขนาดบัฟเฟอร์ของแต่ละคนอัตโนมัติตามสภาพเน็ต, ถ้าอินพุตสะสมให้ดึงครั้งละสองอันเพื่อไล่ให้ทัน, สั่งไคลเอนต์ของคนที่บัฟเฟอร์ว่างบ่อยให้ส่งอินพุตเร็วขึ้น ไคลเอนต์: ส่งอินพุตให้เร็วขึ้นอีกเล็กน้อยตามคำสั่งของเซิร์ฟเวอร์ (ปรับเวลาฝั่งไคลเอนต์)
ตัวเลขที่ควรรู้ แต่ละเกมต่างกัน แต่มักเท่ากับ 1–3 ทิก VALORANT บนเซิร์ฟเวอร์ 128 ทิกรักษาบัฟเฟอร์ฝั่งเซิร์ฟเวอร์ให้สั้นกว่านั้น คือเฉลี่ยครึ่งเฟรม (ประมาณ 4 ms) ส่วนแบบ adaptive ที่เพิ่มบัฟเฟอร์เฉพาะคนที่จิตเตอร์สูงพบได้ทั่วไป
บนกราฟ สูงเฉพาะบางกลุ่ม · ความยาว/จำนวนครั้งที่ว่างของบัฟเฟอร์อินพุตแยกตามผู้เล่น
จุดที่ต้องดู ให้เซิร์ฟเวอร์บันทึกจำนวนอินพุตที่เหลือในบัฟเฟอร์ทุกทิก, จำนวนครั้งที่บัฟเฟอร์ว่างจนต้องเดาจากอินพุตล่าสุดมาเติม และเวลาตั้งแต่อินพุตมาถึงจนถูกใช้ แยกตามผู้เล่น สัญญาณว่าใช่ คนที่บัฟเฟอร์เล็กมีจำนวนครั้งที่ว่างมาก และจังหวะนั้นหยุดสั้น ๆ บนจอคนอื่น ส่วนคนที่บัฟเฟอร์ใหญ่ เวลาตั้งแต่อินพุตจนถูกใช้เพิ่มขึ้นเท่ากับความยาวบัฟเฟอร์ สัญญาณว่าไม่ใช่ บัฟเฟอร์แทบไม่ว่างแต่บนจอคนอื่นยังเห็นอาการกระตุก: น่าจะเป็นปัญหา interpolation ของฝั่งคนดู ถ้าบัฟเฟอร์สั้นแต่อินพุตดีเลย์ยังสูง น่าจะเป็นที่ RTT เองหรือการรอทิกซ้อนสองชั้น วิธีตรวจ ต้องมี log หรือเมตริกจากเซิร์ฟเวอร์/ไคลเอนต์เกม
แหล่งอ้างอิง 3 รายการ
ID pt-isp-validation · ผู้รับผิดชอบหลัก พัฒนาเซิร์ฟเวอร์ (ทีมพัฒนาเกม) · ร่วมกับ อินฟราเครือข่าย (ทีมอินฟรา)
คนที่ใช้เน็ตที่จิตเตอร์สูง อินพุตจะไปถึงเป็นกลุ่ม จึงติดการตรวจความเร็วและคูลดาวน์ของเซิร์ฟเวอร์บ่อย
ทำไม จิตเตอร์ของเน็ตจากบาง ISP หรือบางพื้นที่สูงขึ้นในช่วงหัวค่ำ → ผลคือ เซิร์ฟเวอร์ตัดสินว่าอินพุตปกติที่มาถึงเป็นกลุ่มคือการเคลื่อนที่เร็วเกินหรือผิดกฎคูลดาวน์ → บนหน้าจอ เฉพาะผู้ใช้ ISP นั้นที่โดนดีดกลับ สกิลถูกปฏิเสธ ถ้าหนักจะถูกเซิร์ฟเวอร์เตะออกจนหลุด
อาการ ดีดกลับ , กดไม่ติด/โรลแบ็ค , หลุด
ปัจจัย จิตเตอร์
ใครเจอ บางพื้นที่/บาง ISP, เราคนเดียว
เกิดเมื่อไร ช่วงพีคหัวค่ำ, ระหว่างเดินทาง/ย้ายแมพ
ผู้รับผิดชอบ ผู้รับผิดชอบหลัก พัฒนาเซิร์ฟเวอร์ (ทีมพัฒนาเกม) · ร่วมกับ อินฟราเครือข่าย (ทีมอินฟรา)
งานฝั่งทีมพัฒนาเกม ตรวจด้วยโควตาสะสมในช่วงหลายวินาที, ผ่อนเกณฑ์โดยดูสภาพเน็ต (ปิง, จิตเตอร์) ประกอบ, มีขั้นเตือนก่อนบังคับออก, ใช้บัฟเฟอร์อินพุตของผู้เล่นแต่ละคนกระจายอินพุตที่มาเป็นกลุ่มให้เท่ากันทุกทิก เพื่อลด false positive ตั้งแต่ต้นทาง
งานฝั่งทีมอินฟรา ตรวจการกระจายของอัตราแพ็กเก็ตหายและจิตเตอร์แยกตาม ISP และช่วงเวลาแล้วแชร์ให้ทีมพัฒนาเกม, ตรวจเส้นทางช่วงของ ISP นั้น (mtr ทั้งสองทิศทาง), ถ้าจำเป็นให้เปลี่ยนเส้นทางหรือ escalate ไปยัง ISP
บนกราฟ สูงเฉพาะบางช่วงเวลา · จำนวนการปฏิเสธจากการตรวจสอบ/การบังคับออกแยกตาม ISP (ASN), จิตเตอร์แยกตาม ISP
จุดที่ต้องดู ใส่ ISP (ASN) ของ IP ที่เชื่อมต่อและเวลาให้ log การปฏิเสธจากการตรวจสอบ, การแก้ตำแหน่ง และการบังคับออกของเซิร์ฟเวอร์ แล้วนับแยกตาม ISP และช่วงเวลา ทีมอินฟรารัน mtr ทั้งสองทิศทางไปยังฝั่ง ISP นั้นในช่วงเวลาเดียวกันเพื่อดูจิตเตอร์และแพ็กเก็ตหาย สัญญาณว่าใช่ การปฏิเสธและการบังคับออกกระจุกที่บาง ISP และเพิ่มขึ้นช่วงหัวค่ำ จิตเตอร์ของ ISP นั้นสูงในเวลาเดียวกัน และปริมาณการเคลื่อนที่เมื่อรวมเป็นช่วงหลายวินาทียังอยู่ในกฎ สัญญาณว่าไม่ใช่ เกิดซ้ำเฉพาะบางบัญชีโดยไม่เกี่ยวกับ ISP: อาจเป็นการโกงจริง ถ้าเพิ่มขึ้นพร้อมกันทุก ISP น่าจะเป็นสาเหตุฝั่งเซิร์ฟเวอร์ที่ทิกล่าช้าจนคำสั่งถูกใช้รวมกัน (ทิกเกินงบเวลา) วิธีตรวจ ต้องมี log หรือเมตริกจากเซิร์ฟเวอร์/ไคลเอนต์เกม
แหล่งอ้างอิง 3 รายการ
ID pt-raid-member · ผู้รับผิดชอบหลัก พัฒนาเซิร์ฟเวอร์ (ทีมพัฒนาเกม) · ร่วมกับ พัฒนาไคลเอนต์ (ทีมพัฒนาเกม)
ในกิมมิกเรดที่ทุกคนต้องตอบสนองพร้อมกันในจังหวะที่กำหนด การตอบสนองช้าของคนที่ช้าเพียงคนเดียวจะทำให้ทั้งปาร์ตี้ล้มเหลว
ทำไม กิมมิกร่วม เช่น “ทุกคนกระจายพร้อมกัน” หรือ “ให้คนหนึ่งกดปุ่ม” → ผลคือ คนที่ช้าเห็นสัญญาณเตือนช้า และอินพุตก็ไปถึงช้า → บนหน้าจอ ตายยกปาร์ตี้เพราะคนคนเดียว เพื่อนในปาร์ตี้คนอื่นรู้สึกว่า “เพราะคนที่แลค”
อาการ กดไม่ติด/โรลแบ็ค , อินพุตดีเลย์
ปัจจัย ความหน่วง
ใครเจอ บางจุด/บางแชนแนล, เห็นตัวละครบางตัวผิดปกติ
เกิดเมื่อไร ตอนคนแห่มารวมกัน, ตอนทำแอ็กชันบางอย่าง
ผู้รับผิดชอบ ผู้รับผิดชอบหลัก พัฒนาเซิร์ฟเวอร์ (ทีมพัฒนาเกม) · ร่วมกับ พัฒนาไคลเอนต์ (ทีมพัฒนาเกม)
งานฝั่งทีมพัฒนาเกม เซิร์ฟเวอร์: ให้ช่วงเวลาตัดสินกิมมิกเผื่อไว้เท่ากับปิง, ส่งสัญญาณเตือนล่วงหน้าตามเวลาเซิร์ฟเวอร์, ออกแบบไม่ให้คนเดียวพลาดแล้วตายยกปาร์ตี้ ไคลเอนต์: เล่นสัญญาณเตือนที่ได้รับให้ตรงกับเวลาเซิร์ฟเวอร์
บนกราฟ สูงเฉพาะบางกลุ่ม · RTT ของผู้เล่นที่ทำให้กิมมิกล้มเหลว
จุดที่ต้องดู บันทึกผู้เล่นที่ทำให้ล้มเหลว, เวลาที่อินพุตของคนนั้นมาถึง, ช่วงเวลาตัดสิน และ RTT/แพ็กเก็ตหายของคนนั้น ลงใน log กิมมิกของเซิร์ฟเวอร์ สัญญาณว่าใช่ อินพุตที่ทำให้ตายยกปาร์ตี้ส่วนใหญ่เป็นของคนคนเดียวกัน RTT ของคนนั้นสูงกว่าค่าเฉลี่ยของปาร์ตี้ชัดเจน และอินพุตมาถึงหลังช่วงเวลาตัดสินจบไปไม่นาน สัญญาณว่าไม่ใช่ ความล้มเหลวกระจายเท่า ๆ กันในปาร์ตี้: ช่วงเวลาตัดสินเองสั้นเกินไป (ช่วงเวลาตัดสินสั้นจนปิงกินหมด) ถ้าอินพุตของคนที่ช้ามาถึงภายในช่วงเวลาตัดสินแล้วยังล้มเหลว น่าจะเป็นโค้ดตัดสินผลของเซิร์ฟเวอร์ วิธีตรวจ ต้องมี log หรือเมตริกจากเซิร์ฟเวอร์/ไคลเอนต์เกม
แหล่งอ้างอิง 2 รายการ
ID pt-mob-control · ผู้รับผิดชอบหลัก พัฒนาเซิร์ฟเวอร์ (ทีมพัฒนาเกม)
บางเกมให้ไคลเอนต์ของผู้เล่นคนหนึ่งที่อยู่ใกล้คำนวณการเคลื่อนที่ของมอนสเตอร์เพื่อลดโหลดเซิร์ฟเวอร์ ถ้าเน็ตของคนนั้นไม่ดี มอนสเตอร์ตัวนั้นจะขยับแปลก ๆ บนจอของทุกคน
ทำไม เซิร์ฟเวอร์ให้ไคลเอนต์ของผู้เล่นที่อยู่ใกล้ที่สุด (หรือมาถึงก่อน) คำนวณการเคลื่อนที่ของมอนสเตอร์ → ผลคือ รายงานผลของคนที่รับหน้าที่ไปถึงเซิร์ฟเวอร์ช้าหรือมาเป็นกลุ่ม → บนหน้าจอ เฉพาะมอนสเตอร์ตัวนั้นที่หยุดแวบแล้ววาร์ปบนจอของทุกคนรอบ ๆ ส่วนบนจอของคนที่รับหน้าที่เองปกติ
อาการ วาร์ป , กระตุก , กรอเร็ว
ปัจจัย จิตเตอร์, แพ็กเก็ตหาย
ใครเจอ เห็นตัวละครบางตัวผิดปกติ, บางจุด/บางแชนแนล
เกิดเมื่อไร ตลอดเวลา, สุ่มเป็นครั้งคราว
ผู้รับผิดชอบ ผู้รับผิดชอบหลัก พัฒนาเซิร์ฟเวอร์ (ทีมพัฒนาเกม)
งานฝั่งทีมพัฒนาเกม ย้ายสิทธิ์ควบคุมไปให้คนที่เน็ตดี (ดูจากปิงและแพ็กเก็ตหาย), ถ้ารายงานขาดหายให้เซิร์ฟเวอร์ดึงสิทธิ์คืนทันที, มอนสเตอร์สำคัญอย่างบอสให้เซิร์ฟเวอร์คำนวณเอง
บนกราฟ สูงเฉพาะบางกลุ่ม · ช่วงห่างการรายงานตำแหน่งแยกตามมอนสเตอร์ (แยกตามไคลเอนต์ที่ถือสิทธิ์ควบคุม)
จุดที่ต้องดู ให้เซิร์ฟเวอร์บันทึกไคลเอนต์ที่ถือสิทธิ์ควบคุมของมอนสเตอร์แต่ละตัว พร้อมช่วงห่างการรายงาน, RTT และแพ็กเก็ตหายของไคลเอนต์นั้น ดูช่วงห่างการมาถึงของแพ็กเก็ตที่ไคลเอนต์นั้นส่งได้จาก packet capture ฝั่งเซิร์ฟเวอร์ด้วย สัญญาณว่าใช่ สิทธิ์ควบคุมของมอนสเตอร์ที่ขยับแปลกอยู่ที่คนคนเดียวกันทั้งหมด ช่วงห่างการรายงานของคนนั้นไม่สม่ำเสมอหรือขาดหาย และเมื่อย้ายสิทธิ์ไปให้คนอื่นก็ปกติทันที สัญญาณว่าไม่ใช่ มอนสเตอร์ที่เซิร์ฟเวอร์คำนวณเองก็กระโดดเหมือนกัน: น่าจะเป็นทิกของเซิร์ฟเวอร์ล่าช้าหรือเน็ตของฝั่งคนดู ถ้าย้ายสิทธิ์แล้วยังกระโดดต่อ น่าจะเป็น “การคำนวณเส้นทางไม่ตรงกันในการซิงก์คำสั่ง” วิธีตรวจ ต้องมี log หรือเมตริกจากเซิร์ฟเวอร์/ไคลเอนต์เกม
รายละเอียดเพิ่มเติม คนที่รับหน้าที่รู้สึกว่าปกติ การแจ้งปัญหาจึงเข้ามาแค่ว่า “มอนสเตอร์แปลก ๆ” ถ้าทุกคนยกเว้นคนเดียวเห็นมอนสเตอร์ตัวเดียวกันขยับแปลก ให้ตรวจก่อนว่าใครถือสิทธิ์ควบคุมมอนสเตอร์ตัวนั้น
แหล่งอ้างอิง 2 รายการ
ID pt-heavy-char · ผู้รับผิดชอบหลัก พัฒนาเซิร์ฟเวอร์ (ทีมพัฒนาเกม) · ร่วมกับ อินฟรา DB (ทีมอินฟรา)
ตัวละครที่มีไอเทมหรือจดหมายสะสมหลายพันชิ้น หรือมีรายชื่อเพื่อน รายชื่อบล็อก และบัฟมากผิดปกติ ต้องโหลดตอนเชื่อมต่อ บันทึก และแจ้งคนรอบข้างมากกว่าคนอื่นหลายเท่า จึงช้าเฉพาะตัวละครนั้นโดยไม่เกี่ยวกับเน็ต
ทำไม ตัวละครที่เล่นมานานหรือของรางวัลอีเวนต์สะสมในกระเป๋าและกล่องจดหมายหลายพันชิ้น → ผลคือ ทุกครั้งที่เชื่อมต่อ ย้ายแมพ หรือบันทึก ต้องอ่านเขียน DB มากตามไปด้วย และข้อมูลอุปกรณ์สวมใส่และบัฟที่ต้องส่งให้คนรอบข้างก็ใหญ่ → บนหน้าจอ เฉพาะตัวละครนั้นที่โหลดเข้าโซนนาน และหยุดแวบตอนเปิดกระเป๋าหรือกล่องจดหมาย ถ้าเซิร์ฟเวอร์รอการบันทึกบนเธรดเกม คนรอบข้างก็ค้างไปครู่หนึ่งด้วย
อาการ เข้าเกมไม่ได้/โหลดไม่จบ , อินพุตดีเลย์ , ค้าง
ปัจจัย การหยุดชะงัก
ใครเจอ เราคนเดียว, เฉพาะบางฟีเจอร์
เกิดเมื่อไร หลังล็อกอิน/หลังปิดปรับปรุง, ตอนทำแอ็กชันบางอย่าง, ระหว่างเดินทาง/ย้ายแมพ
ผู้รับผิดชอบ ผู้รับผิดชอบหลัก พัฒนาเซิร์ฟเวอร์ (ทีมพัฒนาเกม) · ร่วมกับ อินฟรา DB (ทีมอินฟรา)
งานฝั่งทีมพัฒนาเกม จำกัดความจุกระเป๋าและกล่องจดหมาย และลบจดหมายเก่าอัตโนมัติ, โหลดแยกเฉพาะส่วนที่ต้องใช้, บันทึกเฉพาะส่วนที่เปลี่ยนนอกเธรดเกม
งานฝั่งทีมอินฟรา หาการอ่านที่ช้าซึ่งเกิดซ้ำกับตัวละครเดิมจาก slow query log แล้วส่งให้ทีมพัฒนาเกม, ให้รายชื่ออันดับต้นของตัวละครที่มีจำนวนแถวไอเทมและจดหมายมาก
ตัวเลขที่ควรรู้ ถ้าไอเทมหนึ่งชิ้นคือหนึ่งแถวใน DB ตัวละครที่มีไอเทม 5,000 ชิ้นจะอ่าน 5,000 แถวทุกครั้งที่เชื่อมต่อ ซึ่งมากกว่าตัวละครทั่วไปหลายสิบเท่า
บนกราฟ สูงเฉพาะบางกลุ่ม · เวลาเชื่อมต่อ/บันทึกแยกตามตัวละคร, จำนวนแถวที่อ่านจาก DB แยกตามตัวละคร
จุดที่ต้องดู หาการอ่านและการบันทึกที่ช้าซึ่งเกิดซ้ำกับ ID ตัวละครเดิมใน slow query log ของ DB (MySQL slow query log, PostgreSQL log_min_duration_statement) และดึงรายชื่ออันดับต้นของจำนวนแถวต่อตัวละครในตารางไอเทมและจดหมาย สัญญาณว่าใช่ คิวรีที่ช้ากระจุกที่ ID ตัวละครไม่กี่ตัว จำนวนแถวไอเทมและจดหมายของตัวละครเหล่านั้นสูงเป็นหลายสิบเท่าของค่าเฉลี่ย และเชื่อมต่อจาก PC หรือเน็ตอื่นก็ช้าเท่าเดิม สัญญาณว่าไม่ใช่ ตัวละครอื่นในบัญชีเดียวกันหรือผู้เล่นคนอื่นก็ช้าด้วย: น่าจะเป็นที่เครื่อง DB หรือล็อก ถ้าตัวละครนั้นปกติบน PC อื่น น่าจะเป็นสภาพแวดล้อมของผู้เล่น วิธีตรวจ ใช้เครื่องมือฝั่งอินฟรา (ไม่ต้องใช้โค้ดเกม)
รายละเอียดเพิ่มเติม ถ้าใช้ตัวละครเดียวกันเชื่อมต่อจาก PC หรือเน็ตอื่นแล้วยังช้าเท่าเดิม แต่ตัวละครอื่นในบัญชีเดียวกันปกติ ให้สงสัยข้อมูลตัวละคร นี่คือเหตุผลที่การแจ้งปัญหาต้องมีชื่อตัวละครเสมอ
แหล่งอ้างอิง 3 รายการ
ID pt-phase · ผู้รับผิดชอบหลัก พัฒนาเซิร์ฟเวอร์ (ทีมพัฒนาเกม) · ร่วมกับ พัฒนาไคลเอนต์ (ทีมพัฒนาเกม)
ถ้าตัวละครสองตัวอยู่คนละแชนแนลหรือคนละอินสแตนซ์ หรืออยู่คนละ “phase” ที่เห็น NPC ต่างกันตามความคืบหน้าของเควสต์ จะเห็นโลกคนละแบบ
ทำไม ตัวละครตัวที่สองถูกจัดไปแชนแนลอื่น หรืออยู่ขั้นเควสต์ต่างกัน → ผลคือ เซิร์ฟเวอร์ไม่ส่ง NPC นั้นให้ตัวละครนั้น (ปกติ) → บนหน้าจอ NPC หายไปฝั่งเดียว ดูเหมือนบั๊กแต่เป็นไปตามการออกแบบ
อาการ มองไม่เห็น/ตัวผี
ปัจจัย แพ็กเก็ตหาย
ใครเจอ ไคลเอนต์เดียวในเครื่องที่เปิดหลายจอ, เราคนเดียว
เกิดเมื่อไร ตลอดเวลา, หลังล็อกอิน/หลังปิดปรับปรุง
ผู้รับผิดชอบ ผู้รับผิดชอบหลัก พัฒนาเซิร์ฟเวอร์ (ทีมพัฒนาเกม) · ร่วมกับ พัฒนาไคลเอนต์ (ทีมพัฒนาเกม)
งานฝั่งทีมพัฒนาเกม เซิร์ฟเวอร์: ส่งข้อมูลแชนแนลและ phase ให้ไคลเอนต์, เพิ่ม “ตรวจแชนแนลและขั้นเควสต์ของตัวละครทั้งสอง” ในเช็กลิสต์ของ QA ไคลเอนต์: แสดงแชนแนลและ phase บนหน้าจอ
บนกราฟ สูงเฉพาะบางกลุ่ม · จำนวนเอนทิตีรอบตัวแยกตามไคลเอนต์, แชนแนล/phase
จุดที่ต้องดู เทียบหมายเลขแชนแนลและขั้นความคืบหน้าของเควสต์ที่เกี่ยวข้องของตัวละครทั้งสองบนหน้าจอเกม แล้วปรับให้อยู่แชนแนลและขั้นเดียวกันแล้วดูอีกครั้ง ถ้ามี log การส่งเอนทิตีของเซิร์ฟเวอร์ ให้ดูเหตุผลที่ไม่ส่ง NPC นั้นให้ตัวละครนั้น (แชนแนล, phase) สัญญาณว่าใช่ แชนแนลหรือขั้นเควสต์ของตัวละครทั้งสองต่างกัน และเมื่อปรับให้ตรงกันก็เห็น NPC สัญญาณว่าไม่ใช่ แชนแนลและขั้นเควสต์ตรงกันแต่ยังหายไปฝั่งเดียว: น่าจะเป็น “ทิ้งข้อความแจ้งการปรากฏตัวที่มาถึงระหว่างโหลด”, “ข้อมูลการปรากฏตัวที่ทะลักมาหลังเข้าโซนหาย” หรือ “ลำดับการลงทะเบียนระยะมองเห็นพันกัน” วิธีตรวจ ตรวจที่สภาพแวดล้อมฝั่งผู้เล่น
รายละเอียดเพิ่มเติม ตรวจด้วยว่าความคืบหน้าเควสต์บันทึกระดับบัญชีหรือระดับตัวละคร ถ้าเป็นตัวละครสองตัวในบัญชีเดียวกัน ความคืบหน้าของตัวหนึ่งอาจเปลี่ยน phase ของอีกตัวได้
แหล่งอ้างอิง 2 รายการ
ID pt-loading-drop · ผู้รับผิดชอบหลัก พัฒนาไคลเอนต์ (ทีมพัฒนาเกม) · ร่วมกับ พัฒนาเซิร์ฟเวอร์ (ทีมพัฒนาเกม)
ทันทีที่เข้าโซน เซิร์ฟเวอร์ส่งข้อความแจ้งการปรากฏตัวของ NPC รอบตัวมา แต่ไคลเอนต์ยังโหลดแมพอยู่จึงทิ้งข้อความนั้น
ทำไม เซิร์ฟเวอร์ส่งข้อความแจ้งการปรากฏตัวของเอนทิตีรอบตัวทันทีหลังประมวลผลการเข้าโซน → ผลคือ ไคลเอนต์กำลังโหลดและยังไม่มี message handler จึงทิ้งข้อความ → บนหน้าจอ เซิร์ฟเวอร์ถือว่าส่งไปแล้วจึงไม่ส่งซ้ำ มองไม่เห็น NPC จนกว่าจะออกจากระยะมองเห็นแล้วกลับมา
อาการ มองไม่เห็น/ตัวผี
ปัจจัย แพ็กเก็ตหาย
ใครเจอ ไคลเอนต์เดียวในเครื่องที่เปิดหลายจอ, เราคนเดียว
เกิดเมื่อไร หลังล็อกอิน/หลังปิดปรับปรุง, ระหว่างเดินทาง/ย้ายแมพ
ผู้รับผิดชอบ ผู้รับผิดชอบหลัก พัฒนาไคลเอนต์ (ทีมพัฒนาเกม) · ร่วมกับ พัฒนาเซิร์ฟเวอร์ (ทีมพัฒนาเกม)
งานฝั่งทีมพัฒนาเกม ไคลเอนต์: ส่ง “พร้อม” เมื่อโหลดเสร็จ หรือเก็บแพ็กเก็ตที่ได้ระหว่างโหลดไว้ประมวลผลทีหลัง เซิร์ฟเวอร์: ส่งข้อมูลรอบตัวหลังได้รับ “พร้อม”
ตัวเลขที่ควรรู้ ถ้าสองไคลเอนต์ในเครื่องเดียวกันโหลดพร้อมกัน หรือฝั่งที่โหลดเป็นหน้าต่างที่อยู่เบื้องหลัง จะต้องแบ่ง CPU และดิสก์กัน และถูกจำกัดการประมวลผลด้วย ฝั่งนั้นจึงอาจโหลดนานขึ้นหลายเท่า บั๊กเดียวกันนี้ยังโผล่ขึ้นมาได้เมื่อเซิร์ฟเวอร์ประมวลผลการเข้าโซนเร็วขึ้น
บนกราฟ สูงเฉพาะบางกลุ่ม · เวลาโหลดแยกตามไคลเอนต์, จำนวนข้อความที่ทิ้งระหว่างโหลด
จุดที่ต้องดู เทียบจำนวนและชนิดของข้อความที่ไคลเอนต์ได้รับแล้วทิ้งระหว่างโหลด และเวลาที่โหลดเสร็จ กับเวลาที่เซิร์ฟเวอร์ส่งข้อความแจ้งการปรากฏตัว จำลองอาการได้ง่ายโดยให้สองไคลเอนต์ในเครื่องเดียวกันโหลดพร้อมกัน หรือให้ฝั่งที่โหลดเป็นหน้าต่างที่อยู่เบื้องหลัง สัญญาณว่าใช่ เซิร์ฟเวอร์ส่งข้อความแจ้งการปรากฏตัวของ NPC ที่มองไม่เห็นแล้ว และมาถึงก่อนโหลดเสร็จ ช่วงนั้นจำนวนข้อความที่ถูกทิ้งเพิ่มขึ้น เกิดเฉพาะกับไคลเอนต์ฝั่งที่โหลดนาน สัญญาณว่าไม่ใช่ ข้อความแจ้งการปรากฏตัวมาถึงหลังโหลดเสร็จแล้วแต่ยังมองไม่เห็น: น่าจะเป็น “สแนปช็อตตั้งต้น (baseline) หาย” หรือ “สับสนจากการนำ entity ID กลับมาใช้ซ้ำ” ถ้าเซิร์ฟเวอร์ไม่ได้ส่งข้อความของ NPC นั้นเลย น่าจะเป็น “ลำดับการลงทะเบียนระยะมองเห็นพันกัน” หรือ “แชนแนล/อินสแตนซ์/phasing ต่างกัน” วิธีตรวจ ต้องมี log หรือเมตริกจากเซิร์ฟเวอร์/ไคลเอนต์เกม
แหล่งอ้างอิง 2 รายการ
ID pt-aoi-race · ผู้รับผิดชอบหลัก พัฒนาเซิร์ฟเวอร์ (ทีมพัฒนาเกม)
ถ้าจังหวะที่ตัวละครถูกลงทะเบียนในตาราง (grid) ระยะมองเห็นตรงกับจังหวะที่ NPC ย้ายช่องตาราง ข้อความแจ้งการปรากฏตัวของ NPC นั้นอาจตกหล่น
ทำไม การประมวลผลการเข้าโซน, การย้ายแชนแนล หรือการเทเลพอร์ต เกิดในจังหวะเดียวกับการเคลื่อนที่ของ NPC → ผลคือ NPC นั้นตกไปจากการคำนวณ “เอนทิตีที่เพิ่งมองเห็น” → บนหน้าจอ มองไม่เห็นแค่ NPC บางตัว หรือ NPC ที่ออกไปแล้วยังยืนอยู่
อาการ มองไม่เห็น/ตัวผี
ปัจจัย แพ็กเก็ตหาย
ใครเจอ ไคลเอนต์เดียวในเครื่องที่เปิดหลายจอ, เราคนเดียว
เกิดเมื่อไร ระหว่างเดินทาง/ย้ายแมพ, สุ่มเป็นครั้งคราว
ผู้รับผิดชอบ ผู้รับผิดชอบหลัก พัฒนาเซิร์ฟเวอร์ (ทีมพัฒนาเกม)
งานฝั่งทีมพัฒนาเกม ประมวลผลการอัปเดตระยะมองเห็นในเธรดเดียวและลำดับเดียว, ซิงก์ “รายการที่มองเห็น” ใหม่ทั้งหมดเป็นระยะ
บนกราฟ พุ่งแบบสุ่มเป็นครั้งคราว · จำนวนรายการที่ต่างกันระหว่างรายการที่มองเห็นบนเซิร์ฟเวอร์กับรายการเอนทิตีบนไคลเอนต์
จุดที่ต้องดู ให้เซิร์ฟเวอร์บันทึกการลงทะเบียนในตารางระยะมองเห็น, การย้ายเซลล์ของเอนทิตี และการส่งข้อความแจ้งการปรากฏตัว/ออกไป พร้อมหมายเลขทิก แล้วเทียบ “รายการที่มองเห็น” ของเซิร์ฟเวอร์กับรายการที่ไคลเอนต์มีเป็นระยะ สัญญาณว่าใช่ NPC ที่หายไปย้ายเซลล์ในทิกเดียวกับที่ตัวละครนั้นเข้าโซนหรือเทเลพอร์ต และไม่มีบันทึกการส่งข้อความแจ้งการปรากฏตัวของ NPC นั้น สัญญาณว่าไม่ใช่ ส่งข้อความแจ้งการปรากฏตัวแล้วแต่ไคลเอนต์ไม่ได้รับหรือทิ้งไป: น่าจะเป็นที่การส่ง (“ข้อมูลการปรากฏตัวที่ทะลักมาหลังเข้าโซนหาย”, “ทิ้งข้อความแจ้งการปรากฏตัวที่มาถึงระหว่างโหลด”) ถ้าหายเฉพาะ NPC ตัวเดิมเสมอ น่าจะเป็น phasing หรือตัวเลือกการแสดงผลต่างกัน วิธีตรวจ ต้องมี log หรือเมตริกจากเซิร์ฟเวอร์/ไคลเอนต์เกม
แหล่งอ้างอิง 2 รายการ
ID pt-baseline · ผู้รับผิดชอบหลัก พัฒนาเซิร์ฟเวอร์ (ทีมพัฒนาเกม) · ร่วมกับ พัฒนาไคลเอนต์ (ทีมพัฒนาเกม)
ในแบบที่เซิร์ฟเวอร์ส่ง “เฉพาะส่วนที่ต่างจากครั้งก่อน” ถ้าข้อมูลเต็ม (baseline) ที่ส่งครั้งแรกหายไป ก็จะใช้ส่วนเปลี่ยนแปลงที่ตามมาไม่ได้
ทำไม แพ็กเก็ตข้อมูลเต็ม (baseline) ของเอนทิตีหาย หรือถูกทิ้งก่อนประมวลผล → ผลคือ ไคลเอนต์ไม่มีเป้าหมายให้ใช้ส่วนเปลี่ยนแปลงที่ตามมา จึงไม่สนใจ → บนหน้าจอ มองไม่เห็นเอนทิตีนั้น หรือผ่านไปนานแล้วจู่ ๆ ก็โผล่ขึ้นมา
อาการ มองไม่เห็น/ตัวผี , วาร์ป
ปัจจัย แพ็กเก็ตหาย
ใครเจอ ไคลเอนต์เดียวในเครื่องที่เปิดหลายจอ, เราคนเดียว
เกิดเมื่อไร สุ่มเป็นครั้งคราว
ผู้รับผิดชอบ ผู้รับผิดชอบหลัก พัฒนาเซิร์ฟเวอร์ (ทีมพัฒนาเกม) · ร่วมกับ พัฒนาไคลเอนต์ (ทีมพัฒนาเกม)
งานฝั่งทีมพัฒนาเกม เซิร์ฟเวอร์: ต้องส่ง baseline ซ้ำจนกว่าจะได้รับ ACK (สัญญาณยืนยันการรับ), สร้างส่วนเปลี่ยนแปลงเทียบกับ baseline ที่ไคลเอนต์ยืนยันว่าได้รับแล้วเท่านั้น ไคลเอนต์: ส่ง ACK ของ baseline หลังนำไปใช้จริงแล้ว, ถ้าได้รับส่วนเปลี่ยนแปลงของเอนทิตีที่ไม่รู้จัก ให้ขอจากเซิร์ฟเวอร์ใหม่
บนกราฟ พุ่งแบบสุ่มเป็นครั้งคราว · จำนวนครั้งที่ได้รับส่วนเปลี่ยนแปลงของเอนทิตีที่ไม่รู้จัก
จุดที่ต้องดู เทียบจำนวนครั้งและ entity ID ที่ไคลเอนต์ทิ้งส่วนเปลี่ยนแปลงเพราะไม่มี baseline กับเวลาที่เซิร์ฟเวอร์ส่ง baseline ของเอนทิตีนั้นและเวลาที่ได้รับ ACK จำลองอาการในสภาพแวดล้อม dev โดยใส่แพ็กเก็ตหาย (loss ของ tc netem, อัตราแพ็กเก็ตหายใน network emulation ของ Unreal) สัญญาณว่าใช่ สำหรับเอนทิตีที่มองไม่เห็น เซิร์ฟเวอร์ส่ง baseline แล้วแต่ไม่ได้รับ ACK ก็ยังส่งแต่ส่วนเปลี่ยนแปลงต่อไป และไคลเอนต์ทิ้งส่วนเปลี่ยนแปลงนั้น สัญญาณว่าไม่ใช่ baseline ได้รับ ACK และนำไปใช้บนไคลเอนต์แล้วแต่ยังมองไม่เห็น: น่าจะเป็น “ข้อความแจ้งการออกไปหาย (ตัวผี)” หรือ “สับสนจากการนำ entity ID กลับมาใช้ซ้ำ” วิธีตรวจ ต้องมี log หรือเมตริกจากเซิร์ฟเวอร์/ไคลเอนต์เกม
แหล่งอ้างอิง 4 รายการ
ID pt-ghost · ผู้รับผิดชอบหลัก พัฒนาเซิร์ฟเวอร์ (ทีมพัฒนาเกม) · ร่วมกับ พัฒนาไคลเอนต์ (ทีมพัฒนาเกม)
ในทางกลับกัน ถ้าพลาดข้อความแจ้งว่า “หายไปแล้ว” NPC หรือผู้เล่นที่ตายหรือออกไปแล้วจะยังอยู่บนจอเราคนเดียว
ทำไม ข้อความแจ้งการตาย, การออกไป หรือการออกจากระยะมองเห็นหาย หรือลำดับสลับกัน → ผลคือ ไคลเอนต์ถือว่าเอนทิตีนั้นยังอยู่ → บนหน้าจอ มอนสเตอร์ที่ตีแล้วไม่มีปฏิกิริยา, ผู้เล่นที่ออกไปแล้วยังยืนอยู่
อาการ มองไม่เห็น/ตัวผี
ปัจจัย แพ็กเก็ตหาย
ใครเจอ ไคลเอนต์เดียวในเครื่องที่เปิดหลายจอ, เราคนเดียว
เกิดเมื่อไร สุ่มเป็นครั้งคราว, ตอนคนแห่มารวมกัน
ผู้รับผิดชอบ ผู้รับผิดชอบหลัก พัฒนาเซิร์ฟเวอร์ (ทีมพัฒนาเกม) · ร่วมกับ พัฒนาไคลเอนต์ (ทีมพัฒนาเกม)
งานฝั่งทีมพัฒนาเกม เซิร์ฟเวอร์: ส่ง “รายการที่มองเห็นตอนนี้” เป็นระยะ ไคลเอนต์: ลบเอนทิตีที่ไม่อยู่ในรายการ, ซ่อนเอนทิตีที่ควรเคลื่อนที่แต่ไม่ได้อัปเดตนาน
บนกราฟ พุ่งแบบสุ่มเป็นครั้งคราว · จำนวนเอนทิตีที่เหลืออยู่แค่บนไคลเอนต์
จุดที่ต้องดู เทียบ “รายการที่มองเห็นตอนนี้” ที่เซิร์ฟเวอร์ส่งกับรายการเอนทิตีที่ไคลเอนต์มี แล้วนับเอนทิตีที่มีแค่บนไคลเอนต์ และจับคู่ log การส่งและการรับข้อความแจ้งการออกไปด้วย entity ID สัญญาณว่าใช่ เซิร์ฟเวอร์ส่งข้อความแจ้งการออกไปของตัวผีแล้วแต่ไคลเอนต์ไม่มีบันทึกการรับ หรือข้อความแจ้งการออกไปมาถึงก่อนข้อความแจ้งการปรากฏตัวจนลำดับกลับกัน สัญญาณว่าไม่ใช่ รายการที่มองเห็นของเซิร์ฟเวอร์ก็ยังมีเอนทิตีนั้นอยู่: น่าจะเป็นฝั่งเซิร์ฟเวอร์เก็บกวาดเอนทิตีตกหล่น ถ้าเพิ่งมีเอนทิตีใหม่ใช้ ID เดียวกันโผล่มา น่าจะเป็น “สับสนจากการนำ entity ID กลับมาใช้ซ้ำ” วิธีตรวจ ต้องมี log หรือเมตริกจากเซิร์ฟเวอร์/ไคลเอนต์เกม
แหล่งอ้างอิง 2 รายการ
ID pt-spawn-burst · ผู้รับผิดชอบหลัก พัฒนาเซิร์ฟเวอร์ (ทีมพัฒนาเกม) · ร่วมกับ พัฒนาไคลเอนต์ (ทีมพัฒนาเกม)
วินาทีที่เข้าโซน เซิร์ฟเวอร์จะส่งข้อมูลการปรากฏตัวของเอนทิตีรอบตัวหลายสิบถึงหลายร้อยตัวมาพร้อมกัน ถ้าส่งผ่านช่องทางแบบ unreliable หรือ receive buffer ล้นในช่วงที่ยังโหลดอยู่จนอ่านซ็อกเก็ตไม่ได้ บางส่วนจะหายไปและไม่ถูกส่งมาอีก
ทำไม ทันทีหลังเข้าโซน ข้อมูลการปรากฏตัวมาถึงพร้อมกันในช่วงสั้น ๆ → ผลคือ ไคลเอนต์ที่กำลังโหลดอ่านซ็อกเก็ตช้าจน receive buffer ของ OS ล้น หรือแพ็กเก็ต UDP ขนาดใหญ่ถูก fragment และหาย fragment เดียวก็หายทั้งแพ็กเก็ต ถ้าเป็นช่องทางแบบ unreliable ก็ไม่ส่งซ้ำให้ด้วย → บนหน้าจอ NPC หายไปบางตัวเฉพาะในไคลเอนต์ฝั่งที่โหลดช้า ถ้าออกจากระยะมองเห็นแล้วกลับมาจะเห็น
อาการ มองไม่เห็น/ตัวผี
ปัจจัย แพ็กเก็ตหาย
ใครเจอ ไคลเอนต์เดียวในเครื่องที่เปิดหลายจอ, เราคนเดียว
เกิดเมื่อไร หลังล็อกอิน/หลังปิดปรับปรุง, ระหว่างเดินทาง/ย้ายแมพ
ผู้รับผิดชอบ ผู้รับผิดชอบหลัก พัฒนาเซิร์ฟเวอร์ (ทีมพัฒนาเกม) · ร่วมกับ พัฒนาไคลเอนต์ (ทีมพัฒนาเกม)
งานฝั่งทีมพัฒนาเกม เซิร์ฟเวอร์: ข้อความแจ้งการปรากฏตัว/ออกไปต้องส่งผ่านช่องทาง reliable ที่รับประกันการส่งซ้ำ, ข้อมูลเริ่มต้นให้แบ่งส่ง ไคลเอนต์: รับข้อมูลในเธรดที่แยกจากการโหลด, เพิ่มขนาด receive buffer
ตัวเลขที่ควรรู้ ค่าเริ่มต้นของ receive buffer สำหรับ UDP บน PC ต่างกันตาม OS แต่มักอยู่ที่หลายสิบถึงหลายร้อย KB ถ้าข้อมูลตอนเข้าเมืองที่คนเยอะใหญ่กว่านี้ แค่อ่านซ็อกเก็ตไม่ได้ชั่วครู่เพราะกำลังโหลดก็ล้นแล้ว
บนกราฟ พุ่งทันทีหลังเปิดเซิร์ฟ/ปิดปรับปรุง · ปริมาณข้อมูลที่รับทันทีหลังเข้าโซน, จำนวนข้อความแจ้งการปรากฏตัวที่ตกหล่น
จุดที่ต้องดู เทียบจำนวนข้อความแจ้งการปรากฏตัวที่เซิร์ฟเวอร์ส่งทันทีหลังเข้าโซนกับจำนวนที่ไคลเอนต์ได้รับ และดูว่าส่งผ่านช่องทางไหน (reliable หรือ unreliable) ใน packet capture ฝั่งเซิร์ฟเวอร์ ให้ดูปริมาณที่ส่งไปหาผู้เล่นคนนั้นทันทีหลังเข้าโซน และแพ็กเก็ตที่ถูก fragment (filter ของ Wireshark ip.flags.mf == 1 || ip.frag_offset > 0) สัญญาณว่าใช่ จำนวนที่ได้รับน้อยกว่าที่ส่ง ส่วนที่หายกระจุกในช่วงที่ข้อมูลทะลักมาหลังเข้าโซน และส่งผ่านช่องทางแบบ unreliable หรือแพ็กเก็ตใหญ่ถูก fragment เกิดบ่อยกว่าในไคลเอนต์ฝั่งที่โหลดช้า สัญญาณว่าไม่ใช่ จำนวนที่ส่งกับที่ได้รับเท่ากันแต่ยังมองไม่เห็น: น่าจะเป็นการทิ้งหลังได้รับ (“ทิ้งข้อความแจ้งการปรากฏตัวที่มาถึงระหว่างโหลด”) หรือปัญหาการคำนวณระยะมองเห็น ถ้าหายเป็นระยะโดยไม่เกี่ยวกับช่วงหลังเข้าโซน น่าจะเป็นแพ็กเก็ตหายจากเน็ต วิธีตรวจ ต้องมี log หรือเมตริกจากเซิร์ฟเวอร์/ไคลเอนต์เกม
แหล่งอ้างอิง 4 รายการ
ID pt-id-reuse · ผู้รับผิดชอบหลัก พัฒนาเซิร์ฟเวอร์ (ทีมพัฒนาเกม) · ร่วมกับ พัฒนาไคลเอนต์ (ทีมพัฒนาเกม)
ถ้าเซิร์ฟเวอร์ใช้ entity ID เดิมซ้ำเมื่อ NPC ที่ตายเกิดใหม่ ไคลเอนต์ที่พลาดข้อความแจ้งการออกไปในช่วงนั้นจะเข้าใจผิดว่า NPC ตัวใหม่คือตัวเก่า
ทำไม NPC ตายแล้วเกิดใหม่ด้วย entity ID เดิม → ผลคือ ไคลเอนต์ที่พลาดข้อความแจ้งการออกไปถือว่าเป็น “เอนทิตีที่รู้จักอยู่แล้ว” จึงไม่สนใจข้อความแจ้งการปรากฏตัว หรือคงสถานะตายไว้เหมือนเดิม → บนหน้าจอ NPC หายไปหรือเห็นนอนตายอยู่บนจอฝั่งเดียว บางครั้งเห็นเป็นหน้าตาของ NPC ตัวอื่น
อาการ มองไม่เห็น/ตัวผี
ปัจจัย แพ็กเก็ตหาย
ใครเจอ ไคลเอนต์เดียวในเครื่องที่เปิดหลายจอ, เราคนเดียว
เกิดเมื่อไร สุ่มเป็นครั้งคราว, ตอนคนแห่มารวมกัน
ผู้รับผิดชอบ ผู้รับผิดชอบหลัก พัฒนาเซิร์ฟเวอร์ (ทีมพัฒนาเกม) · ร่วมกับ พัฒนาไคลเอนต์ (ทีมพัฒนาเกม)
งานฝั่งทีมพัฒนาเกม เซิร์ฟเวอร์: ใส่หมายเลข generation ให้ entity ID เพื่อแยกการนำกลับมาใช้ซ้ำ ไคลเอนต์: ถ้าได้รับข้อความแจ้งการปรากฏตัวของ ID ที่รู้จักอยู่แล้ว ให้ลบเอนทิตีเดิมแล้วสร้างใหม่
บนกราฟ พุ่งแบบสุ่มเป็นครั้งคราว · จำนวนข้อความแจ้งการปรากฏตัวของ ID ที่รู้จักอยู่แล้ว
จุดที่ต้องดู ให้เซิร์ฟเวอร์บันทึกเวลาสร้างและลบของแต่ละ entity ID (พร้อมหมายเลข generation ถ้ามี) แล้วนับจำนวนครั้งที่ไคลเอนต์ได้รับข้อความแจ้งการปรากฏตัวด้วย ID ที่รู้จักอยู่แล้ว และการลบแล้วสร้างใหม่ที่ถูกนับเป็น “ไม่มีการเปลี่ยนแปลง” ตอนอัปเดตระยะมองเห็น สัญญาณว่าใช่ ID ของ NPC ที่มองไม่เห็นหรือเห็นนอนตายอยู่ ตรงกับ NPC ที่เพิ่งตายไป และในช่วงนั้นไคลเอนต์นั้นไม่ได้รับข้อความแจ้งการออกไป หรือเซิร์ฟเวอร์ไม่ได้ส่งทั้งข้อความแจ้งการออกไปและการปรากฏตัว สัญญาณว่าไม่ใช่ ID มีหมายเลข generation และใช้ในการเทียบด้วย: ไม่ใช่สาเหตุนี้ ถ้ามองไม่เห็นทั้งที่ ID ไม่ได้ถูกนำกลับมาใช้ซ้ำ น่าจะเป็นข้อความแจ้งการปรากฏตัวหาย วิธีตรวจ ต้องมี log หรือเมตริกจากเซิร์ฟเวอร์/ไคลเอนต์เกม
รายละเอียดเพิ่มเติม เกิดที่ฝั่งเซิร์ฟเวอร์ได้เช่นกัน ถ้าเทียบรายการเอนทิตีในระยะมองเห็นด้วย ID อย่างเดียว NPC ที่ตายแล้วเกิดใหม่ด้วย ID เดิมระหว่างการอัปเดตระยะมองเห็นสองรอบจะถูกมองว่า “ไม่มีการเปลี่ยนแปลง” และไม่ส่งทั้งข้อความแจ้งการออกไปและการปรากฏตัว ถ้าจังหวะอัปเดตระยะมองเห็นของแต่ละคนไม่ตรงกัน จะเจอเฉพาะไคลเอนต์ที่ตรงกับจังหวะนั้น
แหล่งอ้างอิง 2 รายการ
ID pt-port-collision · ผู้รับผิดชอบหลัก พัฒนาไคลเอนต์ (ทีมพัฒนาเกม) · ร่วมกับ พัฒนาเซิร์ฟเวอร์ (ทีมพัฒนาเกม)
ถ้าไคลเอนต์ถูกออกแบบให้ใช้พอร์ตภายในเครื่องที่กำหนดตายตัว ไคลเอนต์ตัวที่สองบน PC เดียวกันจะใช้พอร์ตไม่ได้ หรือต้องแบ่งรับแพ็กเก็ตกับตัวแรก
ทำไม สองไคลเอนต์พยายามเปิดพอร์ต UDP ภายในเครื่องพอร์ตเดียวกัน (ฝืนใช้ร่วมกันด้วยออปชัน reuse) → ผลคือ OS ส่งแพ็กเก็ตขาเข้าให้ซ็อกเก็ตฝั่งเดียว หรือไม่รับประกันว่าฝั่งไหนจะได้รับ เราเตอร์และเซิร์ฟเวอร์ก็มองสองไคลเอนต์เป็นที่อยู่เดียวกัน → บนหน้าจอ ฝั่งหนึ่งไม่ได้รับแพ็กเก็ตของโลกในเกม จึงมองไม่เห็น NPC และผู้เล่นคนอื่น หรือหลุด
อาการ มองไม่เห็น/ตัวผี , หลุด , เข้าเกมไม่ได้/โหลดไม่จบ
ปัจจัย แพ็กเก็ตหาย
ใครเจอ ไคลเอนต์เดียวในเครื่องที่เปิดหลายจอ
เกิดเมื่อไร หลังล็อกอิน/หลังปิดปรับปรุง, ตลอดเวลา
ผู้รับผิดชอบ ผู้รับผิดชอบหลัก พัฒนาไคลเอนต์ (ทีมพัฒนาเกม) · ร่วมกับ พัฒนาเซิร์ฟเวอร์ (ทีมพัฒนาเกม)
งานฝั่งทีมพัฒนาเกม ไคลเอนต์: ให้ OS เลือกพอร์ตภายในเครื่องอัตโนมัติ (bind พอร์ต 0) เซิร์ฟเวอร์: แยกการเชื่อมต่อด้วย session token ที่ออกให้แต่ละการเชื่อมต่อ
บนกราฟ สูงเฉพาะบางกลุ่ม · จำนวนแพ็กเก็ตที่ได้รับแยกตามไคลเอนต์
จุดที่ต้องดู บน PC ของผู้เล่น เปิดสองไคลเอนต์ไว้พร้อมกันแล้วใช้ netstat -ano -p udp ใน Command Prompt ดูพอร์ต UDP ภายในเครื่องที่แต่ละโปรเซสเกม (PID) เปิด ฝั่งเซิร์ฟเวอร์ให้ตรวจว่าสองเซสชันเข้ามาด้วย public IP และพอร์ตเดียวกันหรือไม่ สัญญาณว่าใช่ สองโปรเซสเกมผูกอยู่กับพอร์ตภายในเครื่องเดียวกัน หรือบนเซิร์ฟเวอร์เห็นสองเซสชันเป็น IP และพอร์ตเดียวกัน ถ้าเปิดฝั่งเดียวจะปกติ สัญญาณว่าไม่ใช่ สองไคลเอนต์ใช้พอร์ตภายในเครื่องต่างกันแต่ฝั่งหนึ่งยังผิดปกติ: น่าจะเป็น “บั๊กแยกเซสชันด้วย IP/ID เครื่อง” หรือ “การจำกัดการเปิดหลายไคลเอนต์” วิธีตรวจ ตรวจที่สภาพแวดล้อมฝั่งผู้เล่น
แหล่งอ้างอิง 3 รายการ Using SO_REUSEADDR and SO_EXCLUSIVEADDRUSE Microsoft ถ้า bind พอร์ตเดียวกันเป็นตัวที่สองด้วย SO_REUSEADDR จะแย่งพอร์ตไป และไม่รู้ว่าซ็อกเก็ตไหนจะได้รับแพ็กเก็ต bind function (winsock.h) Microsoft ถ้า bind พอร์ต 0 จะได้พอร์ตที่ไม่ซ้ำจากช่วง dynamic port (49152–65535) netstat Microsoft -a แสดงพอร์ต TCP/UDP, -n แสดงที่อยู่เป็นตัวเลข, -o แสดง process ID (PID), -p udp แสดงเฉพาะ UDP
ID pt-session-key · ผู้รับผิดชอบหลัก พัฒนาเซิร์ฟเวอร์ (ทีมพัฒนาเกม) · ร่วมกับ พัฒนาไคลเอนต์ (ทีมพัฒนาเกม)
ถ้าเซิร์ฟเวอร์หรือเซิร์ฟเวอร์ตัวกลางแยกการเชื่อมต่อด้วย IP หรือ ID เครื่อง สองไคลเอนต์ใน PC เดียวกัน (public IP เดียวกัน) จะถูกมองเป็นคนเดียว
ทำไม สร้างตารางเซสชันโดยใช้ IP หรือ IP+ID เครื่องเป็นคีย์ → ผลคือ ข้อมูลของไคลเอนต์ตัวที่สองเขียนทับหรือปนกับเซสชันแรก → บนหน้าจอ ฝั่งหนึ่งมองไม่เห็น NPC อีกฝั่งหลุดหรือได้รับข้อมูลของคนอื่น
อาการ มองไม่เห็น/ตัวผี , หลุด
ปัจจัย แพ็กเก็ตหาย
ใครเจอ ไคลเอนต์เดียวในเครื่องที่เปิดหลายจอ, คนในบ้านเดียวกัน, บางพื้นที่/บาง ISP
เกิดเมื่อไร หลังล็อกอิน/หลังปิดปรับปรุง
ผู้รับผิดชอบ ผู้รับผิดชอบหลัก พัฒนาเซิร์ฟเวอร์ (ทีมพัฒนาเกม) · ร่วมกับ พัฒนาไคลเอนต์ (ทีมพัฒนาเกม)
งานฝั่งทีมพัฒนาเกม เซิร์ฟเวอร์: ทั้งเซิร์ฟเวอร์และเซิร์ฟเวอร์ตัวกลางต้องแยกการเชื่อมต่อด้วย session token ที่ไม่ซ้ำกัน, ต้องแก้ให้ได้เพราะหลายคนในบ้านเดียวกัน (หลัง NAT ของเราเตอร์) และผู้ใช้เครือข่ายมือถือที่ ISP แบ่ง IP เดียวให้ผู้ใช้หลายราย (CGNAT) ก็เจอปัญหาเดียวกัน ไคลเอนต์: ใช้ session token ที่ได้รับแยกกันสำหรับแต่ละไคลเอนต์ที่เปิด
บนกราฟ สูงเฉพาะบางกลุ่ม · จำนวนเซสชันพร้อมกันจาก public IP เดียวกัน, จำนวนครั้งที่เซสชันถูกเขียนทับ
จุดที่ต้องดู บันทึกคีย์ที่ใช้ค้นหาเซสชัน, session token และ IP/พอร์ตของไคลเอนต์ ลงใน log ของเซิร์ฟเวอร์และเซิร์ฟเวอร์ตัวกลาง แล้วดูว่าเซสชันเดิมเปลี่ยนไปหรือไม่ในจังหวะที่มีการเชื่อมต่อที่สองจาก IP เดียวกัน จำลองอาการได้โดยเปิดสองไคลเอนต์ใน PC เดียวกันตามลำดับ สัญญาณว่าใช่ ทันทีที่ไคลเอนต์ตัวที่สองเชื่อมต่อ ที่อยู่หรือข้อมูลตัวละครของเซสชันแรกเปลี่ยน และผู้เล่นคนอื่นที่อยู่หลังเราเตอร์เดียวกันหรือเครือข่ายมือถือ (CGNAT) ก็หลุดแบบเดียวกัน สัญญาณว่าไม่ใช่ สองเซสชันจาก IP เดียวกันแยกกันด้วย token ต่างกัน: ไม่ใช่สาเหตุนี้ ถ้าสองโปรเซสใช้พอร์ตภายในเครื่องเดียวกัน น่าจะเป็น “พอร์ต UDP แบบตายตัวชนกัน” วิธีตรวจ ต้องมี log หรือเมตริกจากเซิร์ฟเวอร์/ไคลเอนต์เกม
แหล่งอ้างอิง 1 รายการ
ID pt-multiclient · ผู้รับผิดชอบหลัก พัฒนาไคลเอนต์ (ทีมพัฒนาเกม) · ร่วมกับ พัฒนาเซิร์ฟเวอร์ (ทีมพัฒนาเกม)
ถ้าโมดูลความปลอดภัยหรือนโยบายของเซิร์ฟเวอร์จำกัดการเปิดหลายไคลเอนต์ใน PC เดียว ไคลเอนต์ตัวที่สองจะเปิดหรือเชื่อมต่อไม่ได้ หรือตัวที่เปิดก่อนจะหลุด บางเกมบล็อกแค่บางฟีเจอร์ของไคลเอนต์ที่เปิดเพิ่ม
ทำไม โมดูลความปลอดภัยตรวจพบการเปิดซ้ำ หรือเซิร์ฟเวอร์จำกัดการเชื่อมต่อเพิ่มจากเครื่องเดียวกัน → ผลคือ ปฏิเสธการเปิดหรือการเชื่อมต่อครั้งที่สอง หรือตัดฝั่งหนึ่งออก บางกรณีบล็อกเฉพาะบางฟีเจอร์ของไคลเอนต์ที่เปิดเพิ่ม → บนหน้าจอ เข้าเกมไม่ได้หรือฝั่งหนึ่งหลุด ในเกมที่บล็อกแค่ฟีเจอร์ ฝั่งหนึ่งจะมองไม่เห็น NPC หรือร้านค้า
อาการ เข้าเกมไม่ได้/โหลดไม่จบ , มองไม่เห็น/ตัวผี , หลุด
ปัจจัย แพ็กเก็ตหาย
ใครเจอ ไคลเอนต์เดียวในเครื่องที่เปิดหลายจอ
เกิดเมื่อไร หลังล็อกอิน/หลังปิดปรับปรุง
ผู้รับผิดชอบ ผู้รับผิดชอบหลัก พัฒนาไคลเอนต์ (ทีมพัฒนาเกม) · ร่วมกับ พัฒนาเซิร์ฟเวอร์ (ทีมพัฒนาเกม)
งานฝั่งทีมพัฒนาเกม ไคลเอนต์: ถ้าจะจำกัด ให้แสดงข้อความแจ้งที่ชัดเจน, ตั้งข้อยกเว้นสำหรับ QA ในโมดูลความปลอดภัย เซิร์ฟเวอร์: ตั้งข้อยกเว้นสำหรับ QA ในการจำกัดการเชื่อมต่อจากเครื่องเดียวกันด้วย
บนกราฟ สูงเฉพาะบางกลุ่ม · จำนวนการปฏิเสธ/การหลุดแยกตามสาเหตุ (เชื่อมต่อซ้ำ)
จุดที่ต้องดู ดูข้อความที่ขึ้นตอนเปิดไคลเอนต์ตัวที่สอง และข้อความตอนหลุดของฝั่งที่เปิดก่อน ตรวจว่า log การปฏิเสธการเชื่อมต่อหรือการบังคับออกของเซิร์ฟเวอร์มีรหัสสาเหตุ เช่น เชื่อมต่อซ้ำหรือเครื่องเดียวกัน หรือไม่ สัญญาณว่าใช่ ทันทีที่เปิดหรือเชื่อมต่อครั้งที่สอง มีข้อความปฏิเสธขึ้น หรือฝั่งที่เปิดก่อนหลุดด้วยสาเหตุเชื่อมต่อซ้ำ และถ้าเปิดไคลเอนต์ตัวเดียวก็ไม่มีปัญหา สัญญาณว่าไม่ใช่ เชื่อมต่อได้ทั้งสองฝั่งโดยไม่มีสาเหตุการปฏิเสธหรือการหลุด แต่ฝั่งเดียวมองไม่เห็น NPC: น่าจะเป็น “พอร์ต UDP แบบตายตัวชนกัน”, “บั๊กแยกเซสชันด้วย IP/ID เครื่อง” หรือสาเหตุฝั่งการโหลดและการแสดงผล วิธีตรวจ ตรวจที่สภาพแวดล้อมฝั่งผู้เล่น
แหล่งอ้างอิง 1 รายการ
ID pt-background · ผู้รับผิดชอบหลัก พัฒนาไคลเอนต์ (ทีมพัฒนาเกม) · ร่วมกับ ภายนอก (ภายนอก)
สำหรับไคลเอนต์ที่เป็นหน้าต่างเบื้องหลัง ตัวเกม เอนจิน และ OS จะลดเฟรมและการประมวลผลลง แพ็กเก็ตที่ได้รับจึงประมวลผลไม่ทันจนกองรอหรือล้น
ทำไม การจำกัดเฟรมของหน้าต่างเบื้องหลังจากออปชันเกมหรือไดรเวอร์การ์ดจอ (เช่น ไดรเวอร์ NVIDIA ตั้งได้ตั้งแต่ 20–200 เฟรมต่อวินาที), โหมดประหยัดพลังงาน, การตั้งค่าหยุดทำงานเบื้องหลังของเอนจิน OS เองก็ให้ CPU/GPU กับหน้าต่างที่อยู่ด้านหน้า (foreground) ก่อน → ผลคือ จำนวนแพ็กเก็ตที่ประมวลผลต่อเฟรมลดลงจนคิวสะสม และถ้า receive buffer ล้นจะถูกทิ้ง → บนหน้าจอ เมื่อดึงหน้าต่างขึ้นมาด้านหน้า ทุกอย่างโผล่มารวดเดียว หรือ NPC บางตัวไม่โผล่เลย
อาการ มองไม่เห็น/ตัวผี , กรอเร็ว , หลุด
ปัจจัย การหยุดชะงัก, แพ็กเก็ตหาย
ใครเจอ ไคลเอนต์เดียวในเครื่องที่เปิดหลายจอ
เกิดเมื่อไร หลังอยู่เฉย ๆ สักพัก, ตลอดเวลา
ผู้รับผิดชอบ ผู้รับผิดชอบหลัก พัฒนาไคลเอนต์ (ทีมพัฒนาเกม) · ร่วมกับ ภายนอก (ภายนอก)
งานฝั่งทีมพัฒนาเกม รับข้อมูลเครือข่ายต่อเนื่องในเธรดที่แยกจากลูปของเกม, รับประกันการประมวลผลขั้นต่ำแม้อยู่เบื้องหลัง, เปิดการตั้งค่าให้เอนจินทำงานเบื้องหลัง (Unity คือ runInBackground)
งานฝั่งภายนอก แนะนำให้ผู้เล่นปิดการจำกัดเฟรมของหน้าต่างเบื้องหลังในไดรเวอร์การ์ดจอ และปิดโหมดประหยัดพลังงานของ PC
ตัวเลขที่ควรรู้ ใน Unity ถ้าปิดการตั้งค่า runInBackground ลูปของเกมจะหยุดทันทีที่หน้าต่างเสียโฟกัส ถ้ารับแพ็กเก็ตเฉพาะในลูปนั้น ระหว่างนั้นแพ็กเก็ตจะไม่ถูกประมวลผลเลย
บนกราฟ ขาดช่วงแล้วมารวดเดียว · ช่วงห่างระหว่างเฟรมของไคลเอนต์, จำนวนแพ็กเก็ตที่ประมวลผลต่อเฟรม
จุดที่ต้องดู บน PC เดียวกัน ให้หน้าต่างหนึ่งอยู่ด้านหน้า อีกหน้าต่างอยู่ด้านหลัง แล้วสลับบทบาทเปรียบเทียบ วัดช่วงห่างระหว่างเฟรมของทั้งสองโปรเซสด้วย PresentMon ถ้ามี log ฝั่งเกม ให้ดูสถานะโฟกัสของหน้าต่างและจำนวนแพ็กเก็ตที่ประมวลผลในแต่ละเฟรม สัญญาณว่าใช่ เฉพาะตอนเป็นหน้าต่างเบื้องหลังที่ช่วงห่างระหว่างเฟรมเพิ่มขึ้นมาก (ถ้าเป็นการจำกัดของไดรเวอร์ จะแบนราบที่ช่วงห่างที่ตรงกับจำนวนเฟรมที่ตั้งไว้) หรือการประมวลผลหยุด และเมื่อสลับหน้าต่าง ปัญหาก็ย้ายไปอีกไคลเอนต์ สัญญาณว่าไม่ใช่ หน้าต่างที่อยู่ด้านหน้าก็เป็นเหมือนกัน: ไม่ได้เกิดจากการจำกัดของหน้าต่างเบื้องหลัง ถ้าผิดปกติแต่ไคลเอนต์ตัวเดิมเสมอโดยไม่เกี่ยวกับตำแหน่งหน้าต่าง น่าจะเป็นตัวเลือกการแสดงผลหรือเวอร์ชันต่างกัน วิธีตรวจ ตรวจที่สภาพแวดล้อมฝั่งผู้เล่น
แหล่งอ้างอิง 4 รายการ
ID pt-asset-lock · ผู้รับผิดชอบหลัก พัฒนาไคลเอนต์ (ทีมพัฒนาเกม)
ถ้าสองไคลเอนต์เขียนลงโฟลเดอร์แคชเดียวกันพร้อมกันหรือล็อกไฟล์ไว้ ฝั่งหนึ่งจะโหลดโมเดลหรือเท็กซ์เจอร์ของ NPC ไม่ได้
ทำไม สองไคลเอนต์เขียนไฟล์แคชหรือไฟล์แพตช์ในโฟลเดอร์ติดตั้งเดียวกันพร้อมกัน → ผลคือ ล็อกไฟล์ไม่สำเร็จ หรืออ่านไฟล์ที่เขียนไม่เสร็จ จึงโหลดล้มเหลว → บนหน้าจอ NPC ที่มีป้ายชื่อแต่ไม่มีโมเดลตัวละคร หรือโปร่งใส
อาการ มองไม่เห็น/ตัวผี
ปัจจัย การหยุดชะงัก
ใครเจอ ไคลเอนต์เดียวในเครื่องที่เปิดหลายจอ
เกิดเมื่อไร หลังล็อกอิน/หลังปิดปรับปรุง, ระหว่างเดินทาง/ย้ายแมพ
ผู้รับผิดชอบ ผู้รับผิดชอบหลัก พัฒนาไคลเอนต์ (ทีมพัฒนาเกม)
งานฝั่งทีมพัฒนาเกม แยกโฟลเดอร์แคชตามไคลเอนต์, ลองใหม่เมื่อล็อกไฟล์ไม่สำเร็จ, ถ้าโหลดล้มเหลวให้แสดงโมเดลพื้นฐานไว้ก่อน
บนกราฟ สูงเฉพาะบางกลุ่ม · จำนวนการโหลดแอสเซ็ตล้มเหลวแยกตามไคลเอนต์
จุดที่ต้องดู บน PC ของผู้เล่น ใช้ Process Monitor กรองเฉพาะ path ของโฟลเดอร์ติดตั้งและแคชของเกม แล้วดูผลการเปิดและเขียนไฟล์ของสองโปรเซสเกม ถ้ามี log ของไคลเอนต์ ให้หาการโหลดแอสเซ็ตล้มเหลวและรหัสข้อผิดพลาดการเปิดไฟล์ (ERROR_SHARING_VIOLATION) สัญญาณว่าใช่ การเปิดไฟล์ของโมเดลที่มองไม่เห็นจบลงด้วย sharing violation หรือล็อกไม่สำเร็จ และในเวลาเดียวกันไคลเอนต์อีกตัวกำลังเขียนไฟล์นั้น ถ้าเปิดตัวเดียวหรือแยกโฟลเดอร์ติดตั้ง/แคช อาการจะหายไป สัญญาณว่าไม่ใช่ เปิดไคลเอนต์ตัวเดียวแล้วโมเดลเดิมยังไม่ขึ้น: น่าจะเป็นไฟล์เสียหรือ “เวอร์ชันไคลเอนต์/ข้อมูลไม่ตรงกัน” ถ้าเปิดไฟล์ได้ปกติแต่ไม่ถูกวาด น่าจะเป็น “หน่วยความจำ/VRAM ไม่พอจนสตรีมล้มเหลว” วิธีตรวจ ตรวจที่สภาพแวดล้อมฝั่งผู้เล่น
แหล่งอ้างอิง 2 รายการ Creating and Opening Files Microsoft ไฟล์ที่เปิดโดยไม่มี share mode โปรเซสอื่นจะเปิดไม่ได้ และเกิด ERROR_SHARING_VIOLATION Process Monitor Microsoft บันทึกกิจกรรมของ file system, registry และโปรเซสแบบเรียลไทม์ และกรองได้ด้วยทุกฟิลด์ รวมถึง path
ID pt-vram · ผู้รับผิดชอบหลัก พัฒนาไคลเอนต์ (ทีมพัฒนาเกม) · ร่วมกับ ภายนอก (ภายนอก)
ถ้าสองไคลเอนต์แบ่งหน่วยความจำกราฟิกกันใช้ จะไม่มีที่ให้โหลดโมเดลหรือเท็กซ์เจอร์ที่ต้องใช้ใหม่ บางส่วนจึงไม่ถูกวาด
ทำไม สองไคลเอนต์แบ่ง VRAM และ RAM กันใช้ บางครั้ง OS ลดโควตาหน่วยความจำกราฟิกของหน้าต่างเบื้องหลังก่อน → ผลคือ เอนจินโหลดโมเดลหรือเท็กซ์เจอร์ใหม่ไม่ได้ หรือเอาออกแล้วโหลดใหม่ซ้ำไปมา → บนหน้าจอ NPC โผล่ช้า ภาพเบลอ หรือมองไม่เห็น, กระตุก
อาการ มองไม่เห็น/ตัวผี , กระตุก
ปัจจัย การหยุดชะงัก
ใครเจอ ไคลเอนต์เดียวในเครื่องที่เปิดหลายจอ
เกิดเมื่อไร ระหว่างเดินทาง/ย้ายแมพ, ตอนคนแห่มารวมกัน
ผู้รับผิดชอบ ผู้รับผิดชอบหลัก พัฒนาไคลเอนต์ (ทีมพัฒนาเกม) · ร่วมกับ ภายนอก (ภายนอก)
งานฝั่งทีมพัฒนาเกม ปรับคุณภาพอัตโนมัติให้อยู่ในงบหน่วยความจำ, แสดงโมเดลทดแทนเมื่อโหลดล้มเหลว
งานฝั่งภายนอก แนะนำผู้เล่นที่เปิดสองไคลเอนต์พร้อมกันให้ลดคุณภาพกราฟิกหรือใช้โหมดสเปกต่ำ, แจ้งสเปก VRAM และ RAM ที่แนะนำ
บนกราฟ ชนเพดานแล้วแบนราบ · ปริมาณการใช้ dedicated GPU memory แยกตามโปรเซส
จุดที่ต้องดู ใน Task Manager บน PC ของผู้เล่น เพิ่มคอลัมน์ Dedicated GPU memory ในแท็บ “Details” แล้วเทียบผลรวมการใช้ของสองไคลเอนต์กับความจุ VRAM ของการ์ดจอ ฝั่งเกมให้บันทึกงบ (Budget) และปริมาณที่ใช้อยู่ (CurrentUsage) ที่ QueryVideoMemoryInfo ของ DXGI รายงาน สัญญาณว่าใช่ ผลรวมการใช้ของสองไคลเอนต์แบนราบใกล้ความจุ VRAM และการโหลดโมเดลหรือเท็กซ์เจอร์ล้มเหลวกระจุกในช่วงที่ปริมาณที่ใช้อยู่เกินงบ ถ้าลดคุณภาพหรือเปิดตัวเดียว อาการจะหายไป สัญญาณว่าไม่ใช่ VRAM ยังเหลือแต่ยังมองไม่เห็น: น่าจะเป็น “การเข้าถึงไฟล์แคช/แอสเซ็ตพร้อมกันจนชนกัน” หรือ “ตัวเลือกการแสดงผลต่างกัน” วิธีตรวจ ตรวจที่สภาพแวดล้อมฝั่งผู้เล่น
แหล่งอ้างอิง 3 รายการ Residency (Direct3D 12) Microsoft งบ video memory อาจลดลงมากเมื่อสลับไปแอปอื่น และถ้าเกินงบจะหยุดชะงักหรือสร้าง resource ไม่สำเร็จ ถ้าไม่ได้อยู่ foreground ส่วนที่จองไว้ก็ไม่รับประกัน GPUs in the task manager Microsoft ถ้าเพิ่มคอลัมน์ในแท็บ Details ของ Task Manager จะเห็นการใช้ dedicated และ shared GPU memory แยกตามโปรเซส dedicated GPU memory คือ VRAM ของการ์ดจอ DXGI_QUERY_VIDEO_MEMORY_INFO structure (dxgi1_4.h) Microsoft Budget (งบ video memory ที่ OS กำหนด) และ CurrentUsage (ปริมาณที่แอปใช้อยู่) ถ้าใช้เกินงบอาจเกิดอาการกระตุก
ID pt-display-option · ผู้รับผิดชอบหลัก พัฒนาไคลเอนต์ (ทีมพัฒนาเกม)
ถ้าตัวเลือกอย่างการจำกัดจำนวนตัวละครที่แสดง, การซ่อนป้ายชื่อหรือโมเดล NPC และโหมดสเปกต่ำ ตั้งไว้ต่างกันในสองไคลเอนต์ สิ่งที่มองเห็นก็จะต่างกัน
ทำไม ไคลเอนต์ฝั่งเดียวที่ตั้ง “จำกัดจำนวนตัวละครรอบตัวที่แสดง” หรือโหมดสเปกต่ำ → ผลคือ ไม่วาด NPC ที่อยู่ไกลหรือมีลำดับความสำคัญต่ำ (ปกติ) → บนหน้าจอ NPC หายไปฝั่งเดียว
อาการ มองไม่เห็น/ตัวผี
ปัจจัย การหยุดชะงัก
ใครเจอ ไคลเอนต์เดียวในเครื่องที่เปิดหลายจอ, เราคนเดียว
เกิดเมื่อไร ตอนคนแห่มารวมกัน, ตลอดเวลา
ผู้รับผิดชอบ ผู้รับผิดชอบหลัก พัฒนาไคลเอนต์ (ทีมพัฒนาเกม)
งานฝั่งทีมพัฒนาเกม แสดงให้รู้ว่าเป็นเอนทิตีที่ซ่อนด้วยตัวเลือก, แยกไฟล์ตั้งค่าตามไคลเอนต์เพื่อไม่ให้ปนกัน
บนกราฟ สูงเฉพาะบางกลุ่ม · จำนวนเอนทิตีที่วาดบนจอแยกตามไคลเอนต์
จุดที่ต้องดู เทียบการตั้งค่าจำกัดจำนวนตัวละครที่แสดง, การซ่อนป้ายชื่อ/โมเดล และโหมดสเปกต่ำของสองไคลเอนต์แบบเคียงกัน แล้วลองตั้งฝั่งหนึ่งให้เหมือนอีกฝั่ง ตรวจด้วยว่าสองไคลเอนต์ใช้ไฟล์ตั้งค่าไฟล์เดียวกันจนเขียนทับกันหรือไม่ สัญญาณว่าใช่ เมื่อตั้งค่าให้ตรงกัน สองจอก็เห็นเหมือนกัน และ NPC ที่มองไม่เห็นคือเอนทิตีที่อยู่ไกลเกินจำนวนที่จำกัดการแสดง หรือมีลำดับความสำคัญต่ำ สัญญาณว่าไม่ใช่ ตั้งค่าเหมือนกันแล้วยังหายไปฝั่งเดียว: น่าจะเป็น “แชนแนล/อินสแตนซ์/phasing ต่างกัน” หรือข้อความแจ้งการปรากฏตัวหาย วิธีตรวจ ตรวจที่สภาพแวดล้อมฝั่งผู้เล่น
แหล่งอ้างอิง 1 รายการ
ID pt-version · ผู้รับผิดชอบหลัก พัฒนาไคลเอนต์ (ทีมพัฒนาเกม) · ร่วมกับ พัฒนาเซิร์ฟเวอร์ (ทีมพัฒนาเกม)
ถ้าไคลเอนต์ตัวที่สองเป็นตัวติดตั้งอื่นหรือแพตช์ยังไม่ครบ จะไม่รู้จัก NPC ID ใหม่ที่เซิร์ฟเวอร์ส่งมา และข้ามไปเงียบ ๆ
ทำไม ตัวติดตั้งในโฟลเดอร์อื่น หรือไคลเอนต์ที่เปิดระหว่างลงแพตช์ → ผลคือ ถ้าได้รับ NPC ID หรือ model ID ที่ไม่รู้จัก ก็ข้ามไป → บนหน้าจอ เฉพาะ NPC ที่เพิ่มเข้ามาใหม่ที่มองไม่เห็นในฝั่งเดียว
อาการ มองไม่เห็น/ตัวผี
ปัจจัย แพ็กเก็ตหาย
ใครเจอ ไคลเอนต์เดียวในเครื่องที่เปิดหลายจอ
เกิดเมื่อไร หลังล็อกอิน/หลังปิดปรับปรุง
ผู้รับผิดชอบ ผู้รับผิดชอบหลัก พัฒนาไคลเอนต์ (ทีมพัฒนาเกม) · ร่วมกับ พัฒนาเซิร์ฟเวอร์ (ทีมพัฒนาเกม)
งานฝั่งทีมพัฒนาเกม ไคลเอนต์: ส่งเวอร์ชันข้อมูลตอนเชื่อมต่อ, ถ้าได้รับ ID ที่ไม่รู้จักให้บันทึก log และแสดงสิ่งทดแทน เซิร์ฟเวอร์: ตรวจเวอร์ชันข้อมูลตอนเชื่อมต่อ ถ้าไม่ตรงให้ปฏิเสธการเชื่อมต่อและแนะนำให้ลงแพตช์
บนกราฟ สูงเฉพาะบางกลุ่ม · จำนวนครั้งที่ได้รับ ID ที่ไม่รู้จักแยกตามเวอร์ชันไคลเอนต์
จุดที่ต้องดู เทียบ path ของไฟล์โปรแกรมและเวอร์ชันไคลเอนต์/ข้อมูลที่แสดงบนจอหรือใน log ของสองไคลเอนต์ ฝั่งเกมให้บันทึกเวอร์ชันข้อมูลที่ส่งตอนเชื่อมต่อ และจำนวนครั้งที่ได้รับ NPC ID หรือ model ID ที่ไม่รู้จักแล้วข้ามไป สัญญาณว่าใช่ เวอร์ชันหรือโฟลเดอร์ติดตั้งของสองไคลเอนต์ต่างกัน NPC ที่มองไม่เห็นเป็นตัวที่เพิ่มมาในแพตช์ล่าสุด และตัวติดตั้งที่ลงแพตช์ครบแล้วมองเห็น สัญญาณว่าไม่ใช่ เวอร์ชันและโฟลเดอร์ติดตั้งเหมือนกันแต่หายไปฝั่งเดียว: น่าจะเป็น “แชนแนล/อินสแตนซ์/phasing ต่างกัน” หรือสาเหตุฝั่งการโหลดและการส่ง วิธีตรวจ ตรวจที่สภาพแวดล้อมฝั่งผู้เล่น
แหล่งอ้างอิง 1 รายการ
ID pt-priority · ผู้รับผิดชอบหลัก พัฒนาเซิร์ฟเวอร์ (ทีมพัฒนาเกม) · ร่วมกับ พัฒนาไคลเอนต์ (ทีมพัฒนาเกม)
ถ้าเซิร์ฟเวอร์จำกัดปริมาณที่ส่งต่อการเชื่อมต่อและส่งสิ่งที่อยู่ใกล้ก่อน ฝั่งที่ถูกตั้งเพดานไว้ต่ำจะได้รับ NPC ที่อยู่ไกลช้าหรือไม่ได้รับเลย
ทำไม ในที่ที่คนเยอะ เซิร์ฟเวอร์ส่งตามลำดับความสำคัญภายในเพดานปริมาณการส่งของแต่ละการเชื่อมต่อ → ผลคือ การเชื่อมต่อที่ค่าประเมินแบนด์วิดท์ต่ำ (เช่น ฝั่งที่เป็นหน้าต่างเบื้องหลังจึงส่งสัญญาณยืนยันการรับช้า) จะเลื่อนเอนทิตีลำดับท้าย ๆ ออกไปเรื่อย ๆ → บนหน้าจอ NPC ที่อยู่ไกลโผล่ช้าหรือมองไม่เห็นในฝั่งเดียว
อาการ มองไม่เห็น/ตัวผี , อินพุตดีเลย์
ปัจจัย ความหน่วง
ใครเจอ ไคลเอนต์เดียวในเครื่องที่เปิดหลายจอ, บางจุด/บางแชนแนล
เกิดเมื่อไร ตอนคนแห่มารวมกัน
ผู้รับผิดชอบ ผู้รับผิดชอบหลัก พัฒนาเซิร์ฟเวอร์ (ทีมพัฒนาเกม) · ร่วมกับ พัฒนาไคลเอนต์ (ทีมพัฒนาเกม)
งานฝั่งทีมพัฒนาเกม เซิร์ฟเวอร์: เพิ่มลำดับความสำคัญของเอนทิตีที่ถูกเลื่อนตามเวลาที่ผ่านไป (กัน starvation), รับประกันรอบการอัปเดตขั้นต่ำ ไคลเอนต์: ส่งสัญญาณยืนยันการรับให้ทันเวลาแม้อยู่เบื้องหลัง เพื่อไม่ให้ค่าประเมินแบนด์วิดท์ลดลง
บนกราฟ สูงตามจำนวนคนและโหลด · จำนวนเอนทิตีที่ถูกเลื่อนแยกตามการเชื่อมต่อ, ปริมาณการส่งแยกตามการเชื่อมต่อ
จุดที่ต้องดู ให้เซิร์ฟเวอร์บันทึกไบต์ที่ส่งในแต่ละทิก, เพดานการส่ง (แบนด์วิดท์ที่ประเมิน), จำนวนเอนทิตีที่ส่งไม่ได้และถูกเลื่อน และเวลาที่ผ่านไปนับจากส่งครั้งล่าสุดของแต่ละเอนทิตี แยกตามการเชื่อมต่อ ใน Unreal ใช้ Networking Insights ดูขนาดแพ็กเก็ตของแต่ละการเชื่อมต่อและเอนทิตีที่ replicate อยู่ในนั้นได้ สัญญาณว่าใช่ NPC ที่มองไม่เห็นเป็นเอนทิตีที่ถูกเลื่อนมานานในการเชื่อมต่อนั้น เพดานของการเชื่อมต่อนั้นต่ำกว่าการเชื่อมต่ออื่น และยิ่งคนแน่น เอนทิตีที่ถูกเลื่อนยิ่งเพิ่ม สัญญาณว่าไม่ใช่ ไม่มีเอนทิตีที่ถูกเลื่อน และส่ง NPC นั้นตรงเวลาแล้ว: น่าจะเป็นขั้นหลังการส่ง (receive buffer, การโหลด, ตัวเลือกการแสดงผล) ถ้าทุกการเชื่อมต่อชนเพดานหมด น่าจะเป็นปัญหาปริมาณการส่งของทั้งเซิร์ฟเวอร์หรือการออกแบบระยะมองเห็น วิธีตรวจ ต้องมี log หรือเมตริกจากเซิร์ฟเวอร์/ไคลเอนต์เกม
แหล่งอ้างอิง 3 รายการ Actor Priority in Unreal Engine Epic Games เมื่อแบนด์วิดท์อิ่มตัว จะเลือก actor ที่จะ replicate ตามลำดับความสำคัญ (ระยะทาง, แนวสายตา, เวลาที่ผ่านไปนับจาก replicate ครั้งล่าสุด) ไม่ใช่ทุก actor จะถูก replicate ทุกครั้ง State Synchronization Gaffer On Games สะสมลำดับความสำคัญ: เอนทิตีที่ใส่ในแพ็กเก็ตรอบนี้ไม่ได้จะได้เข้าแพ็กเก็ตถัดไปก่อน และเพดานแบนด์วิดท์ปรับแบบเรียลไทม์ Networking Insights in Unreal Engine Epic Games แสดงขนาดแพ็กเก็ตที่รับส่งในแต่ละการเชื่อมต่อ และเอนทิตี/property ที่ replicate อยู่ในนั้น
ID pt-clock-hold · ผู้รับผิดชอบหลัก พัฒนาไคลเอนต์ (ทีมพัฒนาเกม)
ถ้าเวลาเซิร์ฟเวอร์ที่ไคลเอนต์ประมาณไว้ผิด ข้อมูลเอนทิตีที่เพิ่งมาถึงจะถูกพักไว้เพราะ “ยังเป็นอนาคต” หรือถูกทิ้งเพราะ “เก่าเกินไป”
ทำไม การประมาณเวลาเซิร์ฟเวอร์ของไคลเอนต์ฝั่งหนึ่งคลาดไปมาก (วัดระหว่างโหลด, เพิ่งตื่นจากโหมดประหยัดพลังงาน) → ผลคือ เวลาอ้างอิงของ interpolation ไม่ตรงกับเวลาของข้อมูลเอนทิตี → บนหน้าจอ เอนทิตีโผล่ช้าหรือดูหยุดนิ่งอยู่กับที่
อาการ มองไม่เห็น/ตัวผี , กระตุก
ปัจจัย ความหน่วง
ใครเจอ ไคลเอนต์เดียวในเครื่องที่เปิดหลายจอ
เกิดเมื่อไร หลังอยู่เฉย ๆ สักพัก, หลังล็อกอิน/หลังปิดปรับปรุง
ผู้รับผิดชอบ ผู้รับผิดชอบหลัก พัฒนาไคลเอนต์ (ทีมพัฒนาเกม)
งานฝั่งทีมพัฒนาเกม ซิงก์เวลาใหม่เป็นระยะ และถ้าต่างกันมากให้รีเซ็ตทันที, ไม่ใช้ค่าที่วัดระหว่างโหลดหรือทันทีหลังตื่นจากโหมดประหยัดพลังงาน
บนกราฟ สูงเฉพาะบางกลุ่ม · ความคลาดเคลื่อนของการประมาณเวลาเซิร์ฟเวอร์แยกตามไคลเอนต์
จุดที่ต้องดู ให้ไคลเอนต์บันทึกเวลาเซิร์ฟเวอร์ที่ประมาณ, RTT, เวลาที่ซิงก์เวลาใหม่ และจำนวนครั้งที่พักหรือทิ้งข้อมูลเอนทิตี ลองจำลองอาการทันทีหลังโหลดหรือหลังตื่นจากโหมดประหยัดพลังงาน สัญญาณว่าใช่ เฉพาะไคลเอนต์ที่มีปัญหาที่ความคลาดเคลื่อนเกินเกณฑ์รีเซ็ต (Unity คือ hardResetThresholdSec ค่าเริ่มต้น 0.2 วินาที) มีบันทึกว่าพักข้อมูลเอนทิตีไว้เพราะเป็นอนาคตหรือทิ้งเพราะเป็นอดีต และเมื่อซิงก์เวลาใหม่ก็ปกติทันที สัญญาณว่าไม่ใช่ ความคลาดเคลื่อนต่ำแต่โผล่ช้า: น่าจะเป็น “งบการส่ง/ลำดับความสำคัญต่อการเชื่อมต่อ” หรือสาเหตุฝั่งการโหลด วิธีตรวจ ต้องมี log หรือเมตริกจากเซิร์ฟเวอร์/ไคลเอนต์เกม
แหล่งอ้างอิง 2 รายการ
ต้นเหตุของการส่งซ้ำใน TCP
20 สาเหตุ · บทในฉบับหลัก
ID rt-wireless · ผู้รับผิดชอบหลัก ภายนอก (ภายนอก) · ร่วมกับ อินฟราเซิร์ฟเวอร์ (ทีมอินฟรา), พัฒนาเซิร์ฟเวอร์ (ทีมพัฒนาเกม), พัฒนาไคลเอนต์ (ทีมพัฒนาเกม)
Wi-Fi และเครือข่ายมือถือจะลองส่งซ้ำในช่วงไร้สายอยู่หลายครั้ง ถ้ายังไม่สำเร็จก็จะทิ้งแพ็กเก็ตนั้น แล้ว TCP จะส่งแพ็กเก็ตที่ถูกทิ้งใหม่หลังจากนั้นพักใหญ่
ทำไม สัญญาณอ่อนหรือถูกรบกวนหนัก การส่งในช่วงไร้สายจึงล้มเหลวติดต่อกัน → ผลคือ อุปกรณ์ไร้สายลองใหม่จนเกินขีดจำกัด (ปกติไม่กี่ครั้งถึงสิบกว่าครั้ง) แล้วทิ้งแพ็กเก็ต → บนหน้าจอ ค้างนานเท่ากับเวลาที่ TCP รอส่งซ้ำ แพ็กเก็ตที่ตามมารออยู่ใน receive buffer แล้วทะลักออกมาเป็นอาการกรอเร็ว
อาการ ค้าง , กรอเร็ว , วาร์ป
ปัจจัย แพ็กเก็ตหาย, จิตเตอร์
ใครเจอ เราคนเดียว, คนในบ้านเดียวกัน
เกิดเมื่อไร สุ่มเป็นครั้งคราว, ระหว่างเดินทาง/ย้ายแมพ
ผู้รับผิดชอบ ผู้รับผิดชอบหลัก ภายนอก (ภายนอก) · ร่วมกับ อินฟราเซิร์ฟเวอร์ (ทีมอินฟรา), พัฒนาเซิร์ฟเวอร์ (ทีมพัฒนาเกม), พัฒนาไคลเอนต์ (ทีมพัฒนาเกม)
งานฝั่งทีมพัฒนาเกม เซิร์ฟเวอร์: เปิด TCP_NODELAY (ถ้าเปิด Nagle ไว้ จะไม่มีแพ็กเก็ตที่ตามมาให้ RACK ใช้ตัดสินว่าหาย), ระหว่างที่การส่งติดรอการส่งซ้ำ ให้ส่งเฉพาะอัปเดตสถานะล่าสุดโดยไม่สะสมอันเก่าไว้ (จำกัดปริมาณที่กองรอในเคอร์เนลด้วย TCP_NOTSENT_LOWAT) ไคลเอนต์: เปิด TCP_NODELAY (แพ็กเก็ตที่หายในทิศทางที่ส่งอินพุตของเรา OS ฝั่งไคลเอนต์เป็นผู้กู้คืน), แสดงสถานะเครือข่ายบนจอเมื่อแพ็กเก็ตหายติด ๆ กันหรือปิงพุ่ง
งานฝั่งทีมอินฟรา เร่งการกู้คืนแพ็กเก็ตหายด้วย RACK-TLP (เซิร์ฟเวอร์ป้องกันการหายในช่วงไร้สายไม่ได้ ทำได้แค่กู้คืนให้เร็วขึ้น), ตรวจว่าค่าเริ่มต้นของ Linux รุ่นใหม่ net.ipv4.tcp_recovery=1 (RACK) และ net.ipv4.tcp_early_retrans=3 (TLP) ไม่ถูกเปลี่ยน
งานฝั่งภายนอก แนะนำให้ผู้เล่นใช้สาย LAN, ใช้ 5 GHz หรือ 6 GHz, ย้ายตำแหน่งเราเตอร์หรือเปลี่ยนช่องสัญญาณ
ตัวเลขที่ควรรู้ ถ้าแพ็กเก็ตหายในช่วงไร้สาย 1% แพ็กเก็ตเกม 100 ตัวจะหายไป 1 ตัว ถ้ารับ 10 ตัวใน 1 วินาที ก็จะหยุดแวบราวทุก 10 วินาที ถ้าไม่มี RACK-TLP แต่ละครั้งจะหยุดนานเท่ากับ RTO (ปิง + 200 ms ขึ้นไป)
บนกราฟ สูงเฉพาะบางกลุ่ม · อัตราการส่งซ้ำต่อการเชื่อมต่อ, RTT (ปิง) ต่อการเชื่อมต่อ
จุดที่ต้องดู ping หลายร้อยครั้งจาก PC ของผู้เล่นไปยังเราเตอร์ (gateway) และไปยังเซิร์ฟเวอร์เกม เทียบแพ็กเก็ตหายและช่วงแกว่งของความหน่วง แล้ววัดใหม่หลังเปลี่ยนเป็นสาย LAN หรือเน็ตมือถือ ฝั่งเซิร์ฟเวอร์ดู retrans และ rtt (ค่าเฉลี่ย/ส่วนเบี่ยงเบน) ของการเชื่อมต่อผู้เล่นคนนั้นด้วย ss -ti สัญญาณว่าใช่ ping แค่ถึงเราเตอร์ก็เห็นแพ็กเก็ตหายหรือความหน่วงขึ้นลงไม่นิ่งแล้ว และปัญหาหายไปเมื่อเปลี่ยนเป็นสาย LAN ฝั่งเซิร์ฟเวอร์เห็น retrans และส่วนเบี่ยงเบนของ RTT สูงเฉพาะการเชื่อมต่อของผู้เล่นคนนั้น สัญญาณว่าไม่ใช่ ถึงเราเตอร์ยังปกติ แต่แพ็กเก็ตเริ่มหายหลังจากนั้น: น่าจะเป็นฝั่ง ISP หรือเส้นทาง (“คิวคอขวดล้น”, “เส้นทางเปลี่ยน/เส้นทาง ECMP ที่เสีย”) ถ้าผู้เล่น ISP เดียวกันหลายคนแย่ลงพร้อมกัน ให้เริ่มดูจากช่วงของ ISP วิธีตรวจ ตรวจที่สภาพแวดล้อมฝั่งผู้เล่น
รายละเอียดเพิ่มเติม การลองใหม่ของอุปกรณ์ไร้สายทำให้เกิดจิตเตอร์ (ครั้งละหลาย ms) และจะกลายเป็นแพ็กเก็ตหายก็ต่อเมื่อเกินขีดจำกัดการลองใหม่เท่านั้น ยิ่งคุณภาพสัญญาณไร้สายแย่ลง อาการจึงหนักขึ้นตามลำดับ “จิตเตอร์ → ค้างเป็นครั้งคราว → ค้างบ่อย” ตอนที่ย้ายจากเราเตอร์ (AP) ตัวหนึ่งไปอีกตัว (โรมมิ่ง) บางครั้งแพ็กเก็ตหายต่อเนื่องนานหลายสิบ ms ถึงหลายวินาที ส่วนเครือข่ายมือถือส่งซ้ำมากในช่วงระหว่างเครื่องกับเสาสัญญาณ จึงมักแสดงออกมาเป็นความหน่วงพุ่งหลายร้อย ms มากกว่าแพ็กเก็ตหาย
กรณีจริง Square Enix 2021: FINAL FANTASY XIV แออัดช่วงเปิดตัวภาคเสริม และ error ในคิวล็อกอิน
แหล่งอ้างอิง 8 รายการ
ID rt-queue-drop · ผู้รับผิดชอบหลัก อินฟราเครือข่าย (ทีมอินฟรา) · ร่วมกับ ภายนอก (ภายนอก), พัฒนาไคลเอนต์ (ทีมพัฒนาเกม)
จุดที่แคบที่สุดบนเส้นทาง เช่น เราเตอร์, ลิงก์เชื่อมระหว่าง ISP หรือลิงก์ของดาต้าเซ็นเตอร์ เมื่อคิวตรงนั้นเต็ม แพ็กเก็ตที่มาใหม่จะถูกทิ้ง
ทำไม วิดีโอ, การดาวน์โหลด และทราฟฟิกของผู้ใช้คนอื่นทำให้ช่วงคอขวดเต็ม → ผลคือ ระหว่างที่คิวเต็ม แพ็กเก็ตที่มาใหม่ถูกทิ้งติดต่อกัน (tail drop) แพ็กเก็ตที่ไม่ถูกทิ้งก็ต้องรออยู่ท้ายคิวที่เต็มแน่น → บนหน้าจอ แพ็กเก็ตหายหลายตัวพร้อมกัน จึงค้างนานแล้วตามด้วยอาการกรอเร็ว เป็นบ่อยช่วงหัวค่ำ
อาการ ค้าง , กรอเร็ว , ดีดกลับ
ปัจจัย แพ็กเก็ตหาย, ความหน่วง
ใครเจอ คนในบ้านเดียวกัน, บางพื้นที่/บาง ISP, ทั้งเซิร์ฟเวอร์
เกิดเมื่อไร ช่วงพีคหัวค่ำ, ตอนคนแห่มารวมกัน
ผู้รับผิดชอบ ผู้รับผิดชอบหลัก อินฟราเครือข่าย (ทีมอินฟรา) · ร่วมกับ ภายนอก (ภายนอก), พัฒนาไคลเอนต์ (ทีมพัฒนาเกม)
งานฝั่งทีมพัฒนาเกม แสดงสถานะเครือข่ายบนจอเมื่อแพ็กเก็ตหายติด ๆ กันหรือปิงพุ่ง (แจ้งว่าอาจมีการส่งข้อมูลปริมาณมากบนเน็ตเดียวกัน)
งานฝั่งทีมอินฟรา เผื่อแบนด์วิดท์ของลิงก์ดาต้าเซ็นเตอร์ให้พอ, ตรวจตัวนับการทิ้งจากคิว (output drops) ของลิงก์และพอร์ตสวิตช์ของเรา, ถ้าช่วงของ ISP ตันให้อ้อมไปใช้ลิงก์หรือ peering อื่น
งานฝั่งภายนอก แนะนำให้ผู้เล่นเปิด SQM (fq_codel, CAKE) และ ECN บนเราเตอร์ (ให้ลดความเร็วก่อนที่คิวจะล้น), ขอให้ ISP ขยายช่วงที่เป็นคอขวด
ตัวเลขที่ควรรู้ ช่วงที่คิวล้น แพ็กเก็ตจำนวนมากที่เข้ามาในช่วงหลายสิบ ms นั้นจะหายไปพร้อมกัน แพ็กเก็ตมักหายติดกันและตัวที่ส่งซ้ำก็มักหายอีก จึงมักลากยาวไปจนถึง RTO
บนกราฟ สูงเฉพาะบางช่วงเวลา · อัตราการส่งซ้ำ, RTT (ปิง)
จุดที่ต้องดู อัตราการส่งซ้ำของเซิร์ฟเวอร์ (ค่าที่เพิ่มขึ้นของ TcpRetransSegs ÷ TcpOutSegs จากการรัน nstat ทุก 1 นาที) และ RTT ต่อการเชื่อมต่อ แยกตามพื้นที่, ISP และช่วงเวลา ดูคู่กับการทิ้งขาออก (ifOutDiscards) ของลิงก์และพอร์ตสวิตช์ของเรา รัน mtr ไปยังพื้นที่ที่มีปัญหาทั้งช่วงพีคและช่วงที่คนน้อยแล้วเทียบกัน สัญญาณว่าใช่ อัตราการส่งซ้ำขึ้นเฉพาะช่วงพีคหัวค่ำ และ RTT ขึ้นก่อนแพ็กเก็ตจะหาย (คิวกำลังเต็ม) ใน mtr แพ็กเก็ตหายและความหน่วงเพิ่มพร้อมกันตั้งแต่ hop หนึ่งไปจนสุดทาง เฉพาะช่วงพีค สัญญาณว่าไม่ใช่ RTT ไม่ขึ้นก่อนแพ็กเก็ตหาย: น่าจะเป็น “policer ทิ้งส่วนที่เกิน” ถ้าหายในระดับใกล้เคียงกันตลอดไม่ว่าช่วงเวลาไหน น่าจะเป็น “ข้อผิดพลาดทางกายภาพ” หรือ “เส้นทางเปลี่ยน/เส้นทาง ECMP ที่เสีย” วิธีตรวจ ใช้เครื่องมือฝั่งอินฟรา (ไม่ต้องใช้โค้ดเกม)
กรณีจริง Riot Games 2015: ทราฟฟิก League of Legends ที่วิ่งอ้อมไปไกล และ Riot Direct
แหล่งอ้างอิง 9 รายการ
ID rt-burst · ผู้รับผิดชอบหลัก พัฒนาเซิร์ฟเวอร์ (ทีมพัฒนาเกม) · ร่วมกับ อินฟราเซิร์ฟเวอร์ (ทีมอินฟรา), อินฟราเครือข่าย (ทีมอินฟรา)
ถ้าเซิร์ฟเวอร์ส่งอัปเดตของผู้เล่นหลายพันคนออกไปรวดเดียวในทุกทิก บัฟเฟอร์เล็ก ๆ ของสวิตช์หรือขีดจำกัดชั่วขณะของคลาวด์จะล้นภายในไม่ถึง 1 ms และแพ็กเก็ตบางส่วนถูกทิ้ง
ทำไม ส่งแพ็กเก็ตของทุกคนออกไปพร้อมกันตอนเริ่มทิก → ผลคือ บัฟเฟอร์ของพอร์ตสวิตช์ที่ทราฟฟิกจากหลายเซิร์ฟเวอร์มารวมกัน (หลายร้อย KB ถึงหลาย MB ต่อพอร์ต) หรือขีดจำกัดของอินสแตนซ์คลาวด์ล้นชั่วขณะ (อัตราการใช้งานเฉลี่ยต่ำ) → บนหน้าจอ หลายคนวาร์ปหรือหยุดแวบพร้อมกัน, ดูจากเมตริกค่าเฉลี่ยจะไม่เห็นสาเหตุ
อาการ วาร์ป , ค้าง , กรอเร็ว
ปัจจัย แพ็กเก็ตหาย
ใครเจอ บางจุด/บางแชนแนล, ทั้งเซิร์ฟเวอร์
เกิดเมื่อไร ตอนคนแห่มารวมกัน
ผู้รับผิดชอบ ผู้รับผิดชอบหลัก พัฒนาเซิร์ฟเวอร์ (ทีมพัฒนาเกม) · ร่วมกับ อินฟราเซิร์ฟเวอร์ (ทีมอินฟรา), อินฟราเครือข่าย (ทีมอินฟรา)
งานฝั่งทีมพัฒนาเกม กระจายการส่งของหนึ่งทิกให้ทั่วช่วงเวลาของทิก (การที่การเชื่อมต่อหลายพันรายการกองรวมกันตอนเริ่มทิก pacing ต่อการเชื่อมต่อช่วยได้ไม่มาก), เหลื่อมเวลาเริ่มทิกของแต่ละเซิร์ฟเวอร์, จำกัดความเร็วสูงสุดของการเชื่อมต่อที่ส่งข้อมูลใหญ่ด้วย SO_MAX_PACING_RATE
งานฝั่งทีมอินฟรา เครื่องเซิร์ฟเวอร์/OS: จำกัดความเร็วส่งรวมของทั้งเซิร์ฟเวอร์ (shaper ของ OS เซิร์ฟเวอร์, tc ของ Linux), เกลี่ยการส่งรวดเดียวของการเชื่อมต่อเดียวให้สม่ำเสมอด้วย pacing (คิว fq ของ Linux, BBR) เครือข่าย: ใช้สวิตช์ที่บัฟเฟอร์ใหญ่, ตรวจตัวนับการทิ้งขาออกของพอร์ตสวิตช์ด้วยช่วงเวลาสั้น ๆ (ดูจากอัตราการใช้งานเฉลี่ยจะไม่เห็น)
ตัวเลขที่ควรรู้ พอร์ต 10 Gbps ส่งข้อมูลได้ราว 1.25 MB ใน 1 ms ถ้าทิกของหลายเซิร์ฟเวอร์ตรงกันแล้วมารวมที่พอร์ตเดียว บัฟเฟอร์จะเต็มในพริบตา
บนกราฟ สูงตามจำนวนคนและโหลด · จำนวนการทิ้งขาออกของพอร์ตสวิตช์, อัตราการส่งซ้ำ
จุดที่ต้องดู การทิ้งขาออก (ifOutDiscards) ของพอร์ตสวิตช์ที่เซิร์ฟเวอร์ต่ออยู่และพอร์ตชั้นบนถัดไป เก็บทุกไม่กี่วินาที ถ้าเป็นคลาวด์ดู bw_out_allowance_exceeded และ pps_allowance_exceeded จาก ethtool -S เก็บการส่งซ้ำในช่วงเวลาเดียวกันด้วย bcc tcpretrans แล้วเทียบกัน สัญญาณว่าใช่ อัตราการใช้งานเฉลี่ยรายนาทีต่ำ แต่การทิ้งขาออกหรือ allowance exceeded เพิ่มขึ้น และเพิ่มตามจำนวนผู้เล่นออนไลน์พร้อมกันและจำนวนคนที่รวมตัวอยู่จุดเดียว การส่งซ้ำเกิดในหลายการเชื่อมต่อของเซิร์ฟเวอร์นั้นในจังหวะเดียวกัน โดยไม่กระจุกที่ช่วง IP ของผู้เล่นกลุ่มใด (ISP/พื้นที่) สัญญาณว่าไม่ใช่ CRC และ input error ที่พอร์ตเดียวกันเพิ่มขึ้นด้วย: น่าจะเป็น “ข้อผิดพลาดทางกายภาพ” ถ้าตัวนับการทิ้งของ NIC หรือ softnet dropped ที่เซิร์ฟเวอร์ฝั่งรับเพิ่มขึ้น น่าจะเป็น “เครื่องเซิร์ฟเวอร์ฝั่งรับทิ้งแพ็กเก็ต” วิธีตรวจ ใช้เครื่องมือฝั่งอินฟรา (ไม่ต้องใช้โค้ดเกม)
รายละเอียดเพิ่มเติม pacing ทำงานแยกกันในแต่ละการเชื่อมต่อ การกองรวมที่เกิดจากการเชื่อมต่อหลายพันรายการต่างส่งแพ็กเก็ตหนึ่งสองตัวตอนเริ่มทิก pacing ต่อการเชื่อมต่อช่วยได้ไม่มาก เซิร์ฟเวอร์เกมต้องกระจายจังหวะการส่งเอง ในทางกลับกัน เมื่อการเชื่อมต่อเดียวส่งข้อมูลใหญ่ NIC จะหั่นข้อมูลหลายสิบ KB เป็นขนาดแพ็กเก็ตแล้วส่งออกติดกัน (TSO) การกองรวมแบบนี้ pacing ช่วยกระจายได้ดี
แหล่งอ้างอิง 7 รายการ
ID rt-policer · ผู้รับผิดชอบหลัก อินฟราเครือข่าย (ทีมอินฟรา) · ร่วมกับ อินฟราเซิร์ฟเวอร์ (ทีมอินฟรา), พัฒนาเซิร์ฟเวอร์ (ทีมพัฒนาเกม)
แพ็กเกจเน็ตของ ISP, ขีดจำกัดของอินสแตนซ์คลาวด์ และอุปกรณ์ป้องกัน DDoS บางครั้งจะทิ้งแพ็กเก็ตที่เกินความเร็วที่กำหนดทันทีโดยไม่เข้าคิว
ทำไม ปริมาณที่ส่งในชั่วขณะเกินความเร็วหรือ burst ที่อนุญาต → ผลคือ แพ็กเก็ตส่วนที่เกินถูกทิ้งทันทีโดยไม่เข้าคิว (policing) → บนหน้าจอ ทุกจังหวะที่ burst ใหญ่ แพ็กเก็ตหายหลายตัว จึงค้างแล้วตามด้วยอาการกรอเร็ว, ความเร็วเฉลี่ยดูต่ำกว่าขีดจำกัด
อาการ ค้าง , กรอเร็ว , วาร์ป
ปัจจัย แพ็กเก็ตหาย
ใครเจอ ทั้งเซิร์ฟเวอร์, บางพื้นที่/บาง ISP, เราคนเดียว
เกิดเมื่อไร ตอนคนแห่มารวมกัน, ช่วงพีคหัวค่ำ
ผู้รับผิดชอบ ผู้รับผิดชอบหลัก อินฟราเครือข่าย (ทีมอินฟรา) · ร่วมกับ อินฟราเซิร์ฟเวอร์ (ทีมอินฟรา), พัฒนาเซิร์ฟเวอร์ (ทีมพัฒนาเกม)
งานฝั่งทีมพัฒนาเกม กระจายปริมาณที่ส่งรวดเดียวในแต่ละทิกให้ทั่วช่วงทิก เพื่อลดปริมาณการส่งชั่วขณะให้ต่ำกว่า burst ที่อนุญาต, ถ้าติดขีดจำกัดจำนวนแพ็กเก็ตต่อวินาที ให้รวมข้อความของหนึ่งทิกไว้ในแพ็กเก็ตเดียว
งานฝั่งทีมอินฟรา เครือข่าย: ตรวจตัวนับส่วนเกินของ policer บนอุปกรณ์, ใช้ shaper แทน policer, เพิ่ม burst ที่อนุญาต เครื่องเซิร์ฟเวอร์/OS: ตรวจเมตริกการเกินขีดจำกัดของคลาวด์ (AWS ดู bw_out_allowance_exceeded และ pps_allowance_exceeded จาก ethtool -S), อัปเกรดอินสแตนซ์, ทำ pacing ที่เซิร์ฟเวอร์ (คิว fq ของ Linux)
ตัวเลขที่ควรรู้ shaper (เข้าคิวเพื่อหน่วงไว้) ทำให้ความหน่วงเพิ่ม ส่วน policer (ทิ้งทันที) ทำให้แพ็กเก็ตหายเพิ่ม การเชื่อมต่อเกมแบบ TCP อาจหยุดหลายร้อย ms จากการหายเพียงครั้งเดียว ถ้าแค่เกินขีดจำกัดชั่วครู่ policer มักส่งผลหนักกว่า
บนกราฟ ชนเพดานแล้วแบนราบ · ปริมาณการส่งที่วัดด้วยช่วงเวลาสั้น, ตัวนับส่วนเกินของ policer/allowance
จุดที่ต้องดู ตัวนับ exceed และการทิ้งของอุปกรณ์ที่มี policer ถ้าเป็นคลาวด์ดู bw_out_allowance_exceeded และ pps_allowance_exceeded จาก ethtool -S การเชื่อมต่อที่แพ็กเก็ตหาย ดู RTT ก่อนหายจาก rtt ของ ss -ti หรือจาก packet capture สัญญาณว่าใช่ ตัวนับส่วนเกินเพิ่มขึ้น และปริมาณการส่งที่วัดด้วยช่วงเวลาสั้นแบนราบเหมือนถูกตัดที่ค่าหนึ่ง RTT ไม่ขึ้นก่อนหาย และแพ็กเก็ตหลายตัวหายพร้อมกันเฉพาะจังหวะที่ burst ใหญ่ สัญญาณว่าไม่ใช่ RTT ขึ้นก่อนแพ็กเก็ตหาย: น่าจะเป็นคิวล้น (“คิวคอขวดล้น”, “บัฟเฟอร์ตื้นล้นเพราะ burst จากฝั่งส่ง”) ถ้าตัวนับส่วนเกินไม่ขยับ น่าจะเป็นสาเหตุอื่น วิธีตรวจ ใช้เครื่องมือฝั่งอินฟรา (ไม่ต้องใช้โค้ดเกม)
แหล่งอ้างอิง 5 รายการ
ID rt-physical · ผู้รับผิดชอบหลัก อินฟราเครือข่าย (ทีมอินฟรา) · ร่วมกับ อินฟราเซิร์ฟเวอร์ (ทีมอินฟรา), ภายนอก (ภายนอก)
สายที่ชำรุด, คอนเน็กเตอร์ไฟเบอร์ที่มีฝุ่น และโมดูลออปติกที่หมดอายุการใช้งาน ทำให้เกิด bit error และอุปกรณ์จะทิ้งแพ็กเก็ตที่เสียไปเงียบ ๆ
ทำไม บิตกลับค่าเพราะสาย, โมดูลออปติก หรือคอนเน็กเตอร์เสีย → ผลคือ อุปกรณ์ทิ้งแพ็กเก็ตที่ checksum (CRC) ไม่ตรง → บนหน้าจอ เฉพาะคนที่ผ่านเส้นทางนั้นหยุดแวบสั้น ๆ แล้วกรอเร็วอยู่เป็นระยะ, ไม่ขึ้นกับช่วงเวลา
อาการ ค้าง , กรอเร็ว , วาร์ป
ปัจจัย แพ็กเก็ตหาย
ใครเจอ บางจุด/บางแชนแนล, คนในบ้านเดียวกัน
เกิดเมื่อไร ตลอดเวลา
ผู้รับผิดชอบ ผู้รับผิดชอบหลัก อินฟราเครือข่าย (ทีมอินฟรา) · ร่วมกับ อินฟราเซิร์ฟเวอร์ (ทีมอินฟรา), ภายนอก (ภายนอก)
งานฝั่งทีมอินฟรา ตรวจทั้งสองปลายของลิงก์ (CRC error สะสมที่ฝั่งรับของทิศทางที่เสีย) เครือข่าย: ตรวจตัวนับ CRC และ input error ของพอร์ตอุปกรณ์, ตรวจความแรงสัญญาณแสง (ข้อมูลโมดูลออปติกของสวิตช์), ทำความสะอาดคอนเน็กเตอร์ไฟเบอร์, เปลี่ยนสายหรือโมดูลออปติก เครื่องเซิร์ฟเวอร์/OS: ตรวจ rx_crc_errors ใน ethtool -S ของเซิร์ฟเวอร์ (ชื่อต่างกันเล็กน้อยตามไดรเวอร์), ตรวจความแรงสัญญาณแสง (ethtool -m), เปลี่ยนสายหรือ NIC ฝั่งเซิร์ฟเวอร์
งานฝั่งภายนอก ถ้าเป็นช่วงในบ้านผู้เล่น แนะนำให้เปลี่ยนสาย LAN หรือเราเตอร์, ถ้าเป็นช่วงลิงก์ของ ISP แจ้งให้ ISP ตรวจสาย
ตัวเลขที่ควรรู้ แพ็กเก็ตหายแค่ 0.1% ก็คือหนึ่งครั้งในแพ็กเก็ตเกม 1,000 ตัว ถ้ามีคนผ่านเส้นทางนั้นหลายสิบคน ทุกไม่กี่วินาทีจะมีใครสักคนหยุดแวบ bit error เกิดกับแพ็กเก็ตใหญ่ได้ง่ายกว่า
บนกราฟ สูงเฉพาะบางกลุ่ม · จำนวน CRC error ต่อพอร์ต, อัตราการส่งซ้ำต่อเซิร์ฟเวอร์/ต่อพอร์ต
จุดที่ต้องดู ตัวนับ CRC ที่ปลายทั้งสองข้างของลิงก์ เซิร์ฟเวอร์ดู rx_crc_errors ใน ethtool -S หรือ crc ใน ip -s -s link สวิตช์ดู FCS error (dot3StatsFCSErrors) และ input error (ifInErrors) ของพอร์ต ถ้าเป็นลิงก์ไฟเบอร์ ดูความแรงแสงขาเข้าจาก ethtool -m และข้อมูลโมดูลออปติกของสวิตช์ สัญญาณว่าใช่ CRC error ของพอร์ตหนึ่งเพิ่มขึ้นเรื่อย ๆ ไม่ขึ้นกับช่วงเวลา และอัตราการส่งซ้ำสูงเฉพาะเซิร์ฟเวอร์และการเชื่อมต่อที่ผ่านพอร์ตนั้น ความแรงแสงขาเข้าต่ำกว่าลิงก์ชนิดเดียวกันเส้นอื่น สัญญาณว่าไม่ใช่ CRC ไม่ขยับแต่การทิ้งขาออกเพิ่มขึ้นอย่างเดียว: น่าจะเป็นคิวล้น (“บัฟเฟอร์ตื้นล้นเพราะ burst จากฝั่งส่ง”, “คิวคอขวดล้น”) ถ้า late collision ฝั่งหนึ่งกับ CRC อีกฝั่งเพิ่มขึ้นพร้อมกัน น่าจะเป็น “duplex ไม่ตรงกัน” วิธีตรวจ ใช้เครื่องมือฝั่งอินฟรา (ไม่ต้องใช้โค้ดเกม)
แหล่งอ้างอิง 3 รายการ
ID rt-duplex · ผู้รับผิดชอบหลัก อินฟราเครือข่าย (ทีมอินฟรา) · ร่วมกับ อินฟราเซิร์ฟเวอร์ (ทีมอินฟรา)
ถ้าฝั่งหนึ่งใช้ auto-negotiation แต่อีกฝั่งล็อกความเร็วและ duplex ไว้ ฝั่งหนึ่งจะทำงานแบบ half duplex และทุกครั้งที่มีโหลดจะเกิด collision จนแพ็กเก็ตหาย
ทำไม ล็อกค่าความเร็วและ duplex ไว้ที่อุปกรณ์ฝั่งเดียว → ผลคือ ฝั่งหนึ่งทำงานแบบ full duplex อีกฝั่งเป็น half duplex จึงเกิด collision และ late collision → บนหน้าจอ ปกติไม่มีอาการ แต่พอทราฟฟิกเพิ่ม ทุกคนที่ผ่านอุปกรณ์นั้นค้างแล้วตามด้วยอาการกรอเร็ว
อาการ ค้าง , กรอเร็ว
ปัจจัย แพ็กเก็ตหาย
ใครเจอ ทั้งเซิร์ฟเวอร์, บางจุด/บางแชนแนล
เกิดเมื่อไร ตอนคนแห่มารวมกัน, ช่วงพีคหัวค่ำ
ผู้รับผิดชอบ ผู้รับผิดชอบหลัก อินฟราเครือข่าย (ทีมอินฟรา) · ร่วมกับ อินฟราเซิร์ฟเวอร์ (ทีมอินฟรา)
งานฝั่งทีมอินฟรา ตั้งทั้งสองฝั่งเป็น auto-negotiation หรือล็อกทั้งสองฝั่งเป็นค่าเดียวกัน เครือข่าย: ดูความเร็วและ duplex จากสถานะพอร์ตสวิตช์, ดูตัวนับของพอร์ตว่าฝั่ง half duplex มี late collision เพิ่ม และฝั่ง full duplex มี CRC error และเฟรมที่สั้นเกิน (runt) เพิ่มหรือไม่ เครื่องเซิร์ฟเวอร์/OS: ตรวจความเร็วและ duplex ด้วย ethtool
ตัวเลขที่ควรรู้ สายทองแดง 1 Gbps ต้องใช้ auto-negotiation เสมอ และที่ 10 Gbps ขึ้นไปไม่มี half duplex เลย ปัจจุบันจึงมักเกิดกับอุปกรณ์เก่าที่ 100 Mbps หรือต่ำกว่า, พอร์ต management และบางจุดที่ต่อเข้ากับวงจรของผู้ให้บริการ
บนกราฟ สูงตามจำนวนคนและโหลด · จำนวน late collision และ CRC error ของพอร์ต, อัตราการส่งซ้ำ
จุดที่ต้องดู ความเร็วและ duplex จริงของทั้งสองฝั่งลิงก์ เซิร์ฟเวอร์รัน ethtool ตามด้วยชื่ออินเทอร์เฟซอย่างเดียว สวิตช์ดูสถานะพอร์ตหรือ dot3StatsDuplexStatus ใน SNMP ดู late collision (tx_window_errors ของเซิร์ฟเวอร์, dot3StatsLateCollisions ของสวิตช์) และ CRC error ไปพร้อมกัน สัญญาณว่าใช่ ฝั่งหนึ่งแสดงเป็น half duplex อีกฝั่งเป็น full duplex ทุกครั้งที่ทราฟฟิกเพิ่ม ฝั่ง half duplex มี late collision และฝั่ง full duplex มี CRC error เพิ่มขึ้นพร้อมกัน สัญญาณว่าไม่ใช่ ความเร็วและ duplex ทั้งสองฝั่งตรงกันแต่ CRC เพิ่มอย่างเดียว: น่าจะเป็น “ข้อผิดพลาดทางกายภาพ” ลิงก์ 10 Gbps ขึ้นไปไม่มี half duplex จึงตัดสาเหตุนี้ออก วิธีตรวจ ใช้เครื่องมือฝั่งอินฟรา (ไม่ต้องใช้โค้ดเกม)
แหล่งอ้างอิง 6 รายการ
ID rt-host-drop · ผู้รับผิดชอบหลัก อินฟราเซิร์ฟเวอร์ (ทีมอินฟรา)
แพ็กเก็ตมาถึงเซิร์ฟเวอร์แล้ว แต่ถูกทิ้งเพราะ ring buffer ของ NIC (บัฟเฟอร์ที่พักแพ็กเก็ตที่มาถึงไว้ชั่วคราว) ล้น หรือคอร์ที่เคอร์เนลใช้ประมวลผลขาเข้าทำงานเต็ม
ทำไม ผู้เล่นทะลักเข้ามา, อินเทอร์รัปต์กระจุกที่คอร์เดียว, CPU steal ของ VM, virtual switch โหลดเกิน → ผลคือ ถูกทิ้งที่ ring buffer (เช่น rx_missed_errors ซึ่งชื่อต่างกันตามไดรเวอร์) หรือที่คิวรับของเคอร์เนล (softnet dropped) → บนหน้าจอ ช่วงที่คนเยอะ อินพุตเข้าช้าและหยุดแวบพร้อมกันทั้งเซิร์ฟเวอร์
อาการ อินพุตดีเลย์ , ค้าง , กรอเร็ว , วาร์ป
ปัจจัย แพ็กเก็ตหาย, การหยุดชะงัก
ใครเจอ ทั้งเซิร์ฟเวอร์
เกิดเมื่อไร ตอนคนแห่มารวมกัน
ผู้รับผิดชอบ ผู้รับผิดชอบหลัก อินฟราเซิร์ฟเวอร์ (ทีมอินฟรา)
งานฝั่งทีมอินฟรา เพิ่มตัวนับการทิ้ง เช่น rx_missed_errors ใน ethtool -S และ dropped ใน /proc/net/softnet_stat เข้าในการมอนิเตอร์, เพิ่มขนาด ring buffer (ethtool -G), กระจาย RSS และอินเทอร์รัปต์ไปหลายคอร์, แยกคอร์ของเธรดเกมกับคอร์ที่ประมวลผลขาเข้า, เผื่อ CPU ให้เหลือ, ถ้าเป็น VM ให้ตรวจ CPU steal และโหลดของ virtual switch
ตัวเลขที่ควรรู้ แพ็กเก็ตที่เซิร์ฟเวอร์รับแล้วทิ้งไป ไคลเอนต์จะเป็นฝ่ายส่งใหม่ จึงไม่ค่อยเห็นในเมตริกการส่งซ้ำของเซิร์ฟเวอร์ สัญญาณจะโผล่ก่อนในตัวนับการทิ้ง เช่น rx_missed_errors ใน ethtool -S (ชื่อต่างกันตามไดรเวอร์) และ dropped ใน /proc/net/softnet_stat
บนกราฟ ชนเพดานแล้วแบนราบ · อัตราการใช้ softirq ต่อคอร์, ตัวนับการทิ้งของ NIC
จุดที่ต้องดู ตัวนับการทิ้งใน ethtool -S (เช่น rx_missed_errors, ส่วน mlx5 คือ rx_out_of_buffer และ rx_discards_phy), missed ใน ip -s -s link, คอลัมน์ที่ 2 (dropped) และคอลัมน์ที่ 3 (time_squeeze) ของ /proc/net/softnet_stat และ %soft (การประมวลผล soft interrupt) ต่อคอร์จาก mpstat -P ALL ถ้าเป็น VM ดู %steal ด้วย สัญญาณว่าใช่ ช่วงที่คนเยอะ ตัวนับการทิ้งหรือ softnet dropped เพิ่มขึ้น และ %soft ของคอร์ที่ประมวลผลขาเข้าตันอยู่ใกล้ 100% อินพุตช้าลงพร้อมกันในทุกการเชื่อมต่อของเซิร์ฟเวอร์นั้น สัญญาณว่าไม่ใช่ ตัวนับการทิ้งของเซิร์ฟเวอร์ไม่ขยับ และการส่งซ้ำกระจุกที่การเชื่อมต่อจากบางพื้นที่/บาง ISP: น่าจะเป็นแพ็กเก็ตหายระหว่างทาง ถ้าแพ็กเก็ตที่เซิร์ฟเวอร์ส่งไปหายระหว่างทาง TcpRetransSegs ใน nstat ของเซิร์ฟเวอร์จะเพิ่มขึ้น ส่วนตัวนับเหล่านี้ไม่ขยับ วิธีตรวจ ใช้เครื่องมือฝั่งอินฟรา (ไม่ต้องใช้โค้ดเกม)
แหล่งอ้างอิง 10 รายการ
ID rt-stateful-fw · ผู้รับผิดชอบหลัก อินฟราเครือข่าย (ทีมอินฟรา) · ร่วมกับ อินฟราเซิร์ฟเวอร์ (ทีมอินฟรา), พัฒนาเซิร์ฟเวอร์ (ทีมพัฒนาเกม), พัฒนาไคลเอนต์ (ทีมพัฒนาเกม)
ไฟร์วอลล์หรือ connection tracking ของ Linux (conntrack คือฟังก์ชันที่บันทึกการเชื่อมต่อที่ผ่านลงในตาราง) จะทิ้งแพ็กเก็ตเมื่อตารางเต็ม หรือเมื่อตัดสินว่าสถานะการเชื่อมต่อไม่ถูกต้อง
ทำไม ตาราง connection tracking เต็ม (table full) หรือเส้นทางขาไปกับขากลับต่างกันจนผ่านไฟร์วอลล์แค่ทิศทางเดียว (asymmetric routing) → ผลคือ ไฟร์วอลล์มองว่าเป็นแพ็กเก็ตของ “การเชื่อมต่อที่ไม่รู้จัก” หรือ “sequence number ที่อยู่นอกช่วง window” แล้วทิ้ง → บนหน้าจอ ถ้าตารางเต็ม การเชื่อมต่อใหม่จะถูกบล็อก, ถ้าเส้นทางเหลื่อมกัน เฉพาะคนที่ใช้เส้นทางนั้นจะส่งซ้ำวนไปจนหลุด
อาการ ค้าง , หลุด , เข้าเกมไม่ได้/โหลดไม่จบ
ปัจจัย แพ็กเก็ตหาย
ใครเจอ ทั้งเซิร์ฟเวอร์, บางพื้นที่/บาง ISP
เกิดเมื่อไร ตอนคนแห่มารวมกัน, หลังล็อกอิน/หลังปิดปรับปรุง, สุ่มเป็นครั้งคราว
ผู้รับผิดชอบ ผู้รับผิดชอบหลัก อินฟราเครือข่าย (ทีมอินฟรา) · ร่วมกับ อินฟราเซิร์ฟเวอร์ (ทีมอินฟรา), พัฒนาเซิร์ฟเวอร์ (ทีมพัฒนาเกม), พัฒนาไคลเอนต์ (ทีมพัฒนาเกม)
งานฝั่งทีมพัฒนาเกม เซิร์ฟเวอร์: เผื่อกรณีตารางเต็มด้วยการคุมการเชื่อมต่อที่ทะลักเข้ามาผ่านระบบคิวล็อกอิน, ใช้การเชื่อมต่อซ้ำเพื่อไม่ให้เปิดปิดการเชื่อมต่อสั้น ๆ ซ้ำไปมา (รวมถึงการเรียกระหว่างเซิร์ฟเวอร์), ปิดการเชื่อมต่อที่ heartbeat ขาดไปก่อน ไคลเอนต์: เมื่อเชื่อมต่อไม่สำเร็จหรือหลุด ให้ยืดช่วงเวลาลองใหม่ขึ้นเรื่อย ๆ และสุ่มกระจาย (เพื่อไม่ให้กลับมาทะลักพร้อมกันตอนตารางเต็ม)
งานฝั่งทีมอินฟรา เครือข่าย: เพิ่มขนาดตาราง connection tracking ของไฟร์วอลล์, เอาพอร์ตเกมออกจาก connection tracking, ปรับ routing ให้ขาไปและขากลับผ่านไฟร์วอลล์ตัวเดียวกัน, ตรวจการตั้งค่าการตรวจ TCP window ของไฟร์วอลล์ เครื่องเซิร์ฟเวอร์/OS: เพิ่มขนาดตารางของ Linux (nf_conntrack_max), เอาพอร์ตเกมออกจาก connection tracking (NOTRACK), ตรวจการตั้งค่าการตรวจ TCP window (nf_conntrack_tcp_be_liberal), ถ้าเป็น AWS ตรวจ conntrack_allowance_exceeded ด้วย
ตัวเลขที่ควรรู้ ขีดจำกัดเริ่มต้นของ conntrack ใน Linux (nf_conntrack_max) อยู่ที่หลายหมื่นถึงหลายแสนรายการ ขึ้นกับหน่วยความจำ เมื่อจำนวนปัจจุบัน (nf_conntrack_count) ชนขีดจำกัด จะมี log “nf_conntrack: table full, dropping packet”
บนกราฟ ชนเพดานแล้วแบนราบ · จำนวนรายการ conntrack (nf_conntrack_count), จำนวนการเชื่อมต่อใหม่ที่ล้มเหลว
จุดที่ต้องดู เซิร์ฟเวอร์ Linux ดู nf_conntrack_count กับ nf_conntrack_max, “nf_conntrack: table full, dropping packet” ใน dmesg, drop และ invalid ใน /proc/net/stat/nf_conntrack (หนึ่งบรรทัดต่อคอร์, เลขฐาน 16) ไฟร์วอลล์ดูการใช้ตารางเซสชันและ log การดรอป AWS ดู conntrack_allowance_exceeded ใน ethtool -S สัญญาณว่าใช่ จำนวนรายการแบนราบที่ขีดจำกัด และในเวลาเดียวกัน log table full กับ drop หรือ conntrack_allowance_exceeded เพิ่มขึ้น ถ้าเป็นเส้นทางไม่สมมาตร ขีดจำกัดยังเหลือ แต่ invalid และ log การดรอปของไฟร์วอลล์เพิ่มขึ้นในการเชื่อมต่อของเส้นทางหนึ่ง สัญญาณว่าไม่ใช่ จำนวนรายการยังห่างจากขีดจำกัด และ invalid กับ log การดรอปก็ไม่ขยับ: เป็นสาเหตุอื่น ถ้าตารางยังเหลือที่แต่ CPU หรือจำนวนแพ็กเก็ตต่อวินาทีของไฟร์วอลล์เต็ม น่าจะเป็น “อุปกรณ์กลางทางเกินขีดความสามารถ” วิธีตรวจ ใช้เครื่องมือฝั่งอินฟรา (ไม่ต้องใช้โค้ดเกม)
แหล่งอ้างอิง 5 รายการ Netfilter Conntrack Sysfs variables Linux kernel ค่าเริ่มต้นของ nf_conntrack_max เท่ากับจำนวน hash bucket (หน่วยความจำ÷16384, 1,024–262,144), จำนวนปัจจุบันคือ nf_conntrack_count, nf_conntrack_tcp_be_liberal ทำให้นับเป็น INVALID เฉพาะ RST ที่อยู่นอก window net/netfilter/nf_conntrack_core.c Linux kernel เมื่อตารางเต็มจะเขียน log “nf_conntrack: table full, dropping packet” แล้วทิ้ง (สถิติ drop เพิ่ม) แพ็กเก็ตที่ไม่ตรงกับสถานะการเชื่อมต่อจะทำให้สถิติ invalid เพิ่ม iptables-extensions(8) — Linux manual page netfilter ยกเว้นจาก connection tracking ด้วย CT --notrack ในตาราง raw Amazon EC2 security group connection tracking AWS ถ้าเกินขีดจำกัดจำนวนการเชื่อมต่อที่ติดตามได้ของแต่ละอินสแตนซ์ แพ็กเก็ตจะถูกทิ้ง ตรวจได้จาก conntrack_allowance_exceeded พร้อมคำแนะนำให้หลีกเลี่ยงเส้นทางไม่สมมาตร net/netfilter/nf_conntrack_standalone.c Linux kernel /proc/net/stat/nf_conntrack มีหนึ่งบรรทัดต่อคอร์ เป็นเลขฐาน 16 และมีคอลัมน์ entries, invalid, insert_failed, drop, early_drop ฯลฯ
ID rt-appliance-pps · ผู้รับผิดชอบหลัก อินฟราเครือข่าย (ทีมอินฟรา) · ร่วมกับ พัฒนาเซิร์ฟเวอร์ (ทีมพัฒนาเกม)
ไฟร์วอลล์, อุปกรณ์ป้องกันการบุกรุก (IPS) และอุปกรณ์ป้องกัน DDoS ตรวจแพ็กเก็ตที่ผ่านทีละตัว เมื่อเกินความสามารถในการตรวจ แพ็กเก็ตที่ประมวลผลไม่ทันจะถูกทิ้งตั้งแต่จังหวะนั้น
ทำไม ช่วงพีคหรืออีเวนต์ แพ็กเก็ตเกมเล็ก ๆ ทะลักเข้ามาเกินหลายแสนตัวต่อวินาที หรือกฎการตรวจหนัก → ผลคือ CPU หรือขีดจำกัดจำนวนแพ็กเก็ตต่อวินาทีของอุปกรณ์เต็ม อุปกรณ์จึงทิ้งแพ็กเก็ต ถ้าเป็น false positive แพ็กเก็ตปกติก็ถูกบล็อกด้วย → บนหน้าจอ ผู้เล่นบนทุกเซิร์ฟเวอร์ที่อยู่หลังอุปกรณ์นั้นค้างหรือวาร์ปพร้อมกัน, หนักขึ้นเฉพาะตอนคนแห่มารวมกัน
อาการ ค้าง , กรอเร็ว , วาร์ป , หลุด
ปัจจัย แพ็กเก็ตหาย, ความหน่วง
ใครเจอ ทั้งเซิร์ฟเวอร์, บางพื้นที่/บาง ISP
เกิดเมื่อไร ช่วงพีคหัวค่ำ, ตอนคนแห่มารวมกัน
ผู้รับผิดชอบ ผู้รับผิดชอบหลัก อินฟราเครือข่าย (ทีมอินฟรา) · ร่วมกับ พัฒนาเซิร์ฟเวอร์ (ทีมพัฒนาเกม)
งานฝั่งทีมพัฒนาเกม แชร์รูปแบบทราฟฟิกของเกม (พอร์ต, ขนาดแพ็กเก็ต, จำนวนแพ็กเก็ตต่อวินาที) ให้ทีมอินฟรา, รวมข้อความเล็ก ๆ ที่จะส่งในหนึ่งทิกแล้วส่งครั้งเดียวเพื่อลดจำนวนแพ็กเก็ต
งานฝั่งทีมอินฟรา ดู CPU, จำนวนแพ็กเก็ตต่อวินาที และตัวนับการดรอปของอุปกรณ์คู่กับเมตริกของเกม, คำนวณความจุของอุปกรณ์โดยอิงแพ็กเก็ตเล็ก, เอาพอร์ตเกมออกจากการตรวจที่หนัก, ปรับกฎป้องกัน DDoS ให้เข้ากับรูปแบบทราฟฟิกของเกม
ตัวเลขที่ควรรู้ ตัวเลข “10 Gbps” ในสเปกอุปกรณ์มักวัดด้วยแพ็กเก็ตใหญ่ 1,500 ไบต์ แพ็กเก็ตเกมขนาดราว 100 ไบต์จะมีจำนวนแพ็กเก็ตมากกว่า 10 เท่าขึ้นไปในแบนด์วิดท์เท่ากัน ต่อให้ลิงก์ดูว่าง ขีดจำกัดจำนวนแพ็กเก็ตต่อวินาทีก็จะเต็มก่อน
บนกราฟ ชนเพดานแล้วแบนราบ · จำนวนแพ็กเก็ตต่อวินาทีและอัตราการใช้ CPU ของอุปกรณ์, จำนวนการดรอปของอุปกรณ์
จุดที่ต้องดู CPU, จำนวนแพ็กเก็ตต่อวินาที และตัวนับการดรอปของอุปกรณ์ เทียบจำนวนแพ็กเก็ตของพอร์ตสวิตช์ด้านหน้าและด้านหลังอุปกรณ์ด้วยรอบการเก็บค่าเดียวกัน วางซ้อนบนหน้าจอเดียวกับจำนวนผู้เล่นออนไลน์พร้อมกันและอัตราการส่งซ้ำของเซิร์ฟเวอร์ สัญญาณว่าใช่ ช่วงพีคหรืออีเวนต์ จำนวนแพ็กเก็ตต่อวินาทีหรือ CPU ของอุปกรณ์ตันอยู่ที่ค่าหนึ่ง แพ็กเก็ตที่ออกจากอุปกรณ์น้อยกว่าที่เข้าไป และในเวลาเดียวกันอัตราการส่งซ้ำของทุกเซิร์ฟเวอร์ที่อยู่หลังอุปกรณ์ก็ขึ้นตาม สัญญาณว่าไม่ใช่ จำนวนแพ็กเก็ตด้านหน้าและด้านหลังอุปกรณ์เท่ากันและไม่มีการดรอปที่อุปกรณ์: เป็นสาเหตุอื่น ถ้าตัวนับการทิ้งของ NIC หรือ softnet dropped ของเซิร์ฟเวอร์เพิ่มขึ้น น่าจะเป็น “เครื่องเซิร์ฟเวอร์ฝั่งรับทิ้งแพ็กเก็ต” วิธีตรวจ ใช้เครื่องมือฝั่งอินฟรา (ไม่ต้องใช้โค้ดเกม)
แหล่งอ้างอิง 1 รายการ
ID rt-mtu · ผู้รับผิดชอบหลัก อินฟราเครือข่าย (ทีมอินฟรา) · ร่วมกับ อินฟราเซิร์ฟเวอร์ (ทีมอินฟรา), พัฒนาเซิร์ฟเวอร์ (ทีมพัฒนาเกม)
เมื่อขนาดที่ช่วงกลางทางรับได้เล็กลง แต่ข้อความแจ้งว่า “ใหญ่เกินไป” (ICMP) ถูกบล็อก แพ็กเก็ตใหญ่จะหายไปทุกครั้งไม่ว่าจะส่งซ้ำกี่รอบ
ทำไม ขนาดสูงสุดลดลงในช่วงที่ผ่าน VPN หรืออุโมงค์ (tunnel) และข้อความแจ้งว่าเกินขนาดถูกไฟร์วอลล์บล็อก → ผลคือ ฝั่งส่งไม่รู้สาเหตุ จึงส่งแพ็กเก็ตใหญ่ตัวเดิมซ้ำไปเรื่อย ๆ และ RTO เพิ่มเป็นสองเท่าทุกครั้ง → บนหน้าจอ ปกติไม่มีอาการ แต่ในจังหวะที่มีข้อมูลใหญ่วิ่ง เช่น เปิดกระเป๋า, ไปที่ที่คนเยอะ หรือโหลดตอนเข้าแมพ แพ็กเก็ตเล็กที่ตามมาก็หยุดไปหมด สุดท้ายหลุดหรือโหลดไม่จบ
อาการ ค้าง , หลุด , เข้าเกมไม่ได้/โหลดไม่จบ
ปัจจัย แพ็กเก็ตหาย
ใครเจอ บางพื้นที่/บาง ISP, เราคนเดียว
เกิดเมื่อไร ตอนทำแอ็กชันบางอย่าง, หลังล็อกอิน/หลังปิดปรับปรุง
ผู้รับผิดชอบ ผู้รับผิดชอบหลัก อินฟราเครือข่าย (ทีมอินฟรา) · ร่วมกับ อินฟราเซิร์ฟเวอร์ (ทีมอินฟรา), พัฒนาเซิร์ฟเวอร์ (ทีมพัฒนาเกม)
งานฝั่งทีมพัฒนาเกม ถ้าจะลดขนาดจากฝั่งเซิร์ฟเวอร์เอง ให้ตั้งขนาด segment สูงสุดของซ็อกเก็ต (TCP_MAXSEG), แค่ซอยข้อความให้เล็กในโค้ดเกมไม่ช่วยป้องกัน (TCP จะรวมข้อมูลที่จะส่งเป็นก้อนขนาด MSS ใหม่)
งานฝั่งทีมอินฟรา เครือข่าย: ปรับ MSS ที่อุปกรณ์ขอบเครือข่าย (clamping), อนุญาต ICMP แจ้งเกินขนาด (type 3 code 4, fragmentation needed) ที่ไฟร์วอลล์และ network ACL ของคลาวด์ เครื่องเซิร์ฟเวอร์/OS: ตั้งค่า path MTU, ตรวจว่าไฟร์วอลล์ของเซิร์ฟเวอร์และ security group ของคลาวด์ไม่บล็อก ICMP แจ้งเกินขนาด, ใช้ tcp_mtu_probing=1 ของ Linux เป็นตาข่ายรองรับชั้นสุดท้าย
ตัวเลขที่ควรรู้ ปกติ 1,500 ไบต์ ถ้าผ่านอุโมงค์จะเหลือราว 1,400 ถ้าแพ็กเก็ตเดิมถูกส่งซ้ำ 5–6 ครั้ง จะหยุดชะงักนานเกิน 10 วินาที
บนกราฟ สูงเฉพาะบางกลุ่ม · RTO และ backoff ต่อการเชื่อมต่อ, จำนวนการหลุดแยกตามพื้นที่/ISP
จุดที่ต้องดู การส่งซ้ำของการเชื่อมต่อที่มีปัญหาจาก packet capture ฝั่งเซิร์ฟเวอร์หรือ bcc tcpretrans -s (แสดง sequence number) และ mss, pmtu, backoff ของการเชื่อมต่อนั้นจาก ss -ti จากเซิร์ฟเวอร์ส่ง ping เล็กกับ ping 1,500 ไบต์ที่เปิด DF (ping -M do -s 1472) ไปยังที่อยู่ของผู้เล่นคนนั้นแล้วเทียบกัน สัญญาณว่าใช่ แพ็กเก็ตที่เต็มขนาด MSS ถูกส่งซ้ำด้วย sequence number เดิมไปเรื่อย ๆ โดยช่วงห่างเพิ่มเป็นสองเท่าทุกครั้ง ส่วนแพ็กเก็ตที่เล็กกว่าผ่านได้ ไม่มี ICMP แจ้งเกินขนาด (ตัวกรอง Wireshark icmp.type == 3 and icmp.code == 4) เข้ามา ping เล็กได้คำตอบ แต่ ping ใหญ่ที่เปิด DF หายเงียบ สัญญาณว่าไม่ใช่ แพ็กเก็ตเล็กก็หายด้วย: เป็นการหายที่ไม่เกี่ยวกับขนาด (“คิวคอขวดล้น”, “เส้นทางเปลี่ยน/เส้นทาง ECMP ที่เสีย”) ถ้า ICMP แจ้งเกินขนาดมาถึงและ pmtu ใน ss -ti ลดลง แปลว่า path MTU discovery ทำงานปกติ วิธีตรวจ ใช้เครื่องมือฝั่งอินฟรา (ไม่ต้องใช้โค้ดเกม)
รายละเอียดเพิ่มเติม tcp_mtu_probing=1 จะตัดสินว่าเป็น black hole แล้วลด MSS เหลือ 1,024 ไบต์ ก็ต่อเมื่อ RTO หมดเวลาต่อเนื่องไปหลายวินาที (เท่ากับ tcp_retries1=3) ระหว่างนั้นจะหยุดชะงัก จึงควรเก็บไว้เป็นตาข่ายรองรับชั้นสุดท้าย และทำ MSS clamping ที่ป้องกันไว้ล่วงหน้าเป็นอันดับแรก
แหล่งอ้างอิง 15 รายการ RFC 1191: Path MTU discovery IETF path MTU discovery: แพ็กเก็ตที่ใหญ่เกินจะได้รับแจ้งด้วย ICMP “fragmentation needed and DF set” (type 3 code 4) RFC 2923: TCP Problems with Path MTU Discovery IETF ปัญหา PMTU black hole ที่ ICMP ถูกบล็อกจนแพ็กเก็ตใหญ่หายไปเรื่อย ๆ RFC 4821: Packetization Layer Path MTU Discovery IETF วิธีที่ชั้น transport ค้นหาขนาดแพ็กเก็ตเองโดยไม่ใช้ ICMP (พื้นฐานของ tcp_mtu_probing ใน Linux) IP Sysctl Linux kernel tcp_mtu_probing: 0 ปิด, 1 เฉพาะเมื่อตรวจพบ black hole, 2 ตลอดเวลา (MSS เริ่มต้นคือ tcp_base_mss) tcp_retries1 ค่าเริ่มต้น 3 net/ipv4/tcp_timer.c Linux kernel เมื่อการส่งซ้ำจาก RTO ต่อเนื่องครบ tcp_retries1 ครั้ง จะถือว่าตรวจพบ black hole แล้วเปิด MTU probing เพื่อลด MSS include/net/tcp.h Linux kernel TCP_BASE_MSS = 1,024 ไบต์ RFC 6298: Computing TCP's Retransmission Timer IETF เพิ่ม RTO เป็นสองเท่าทุกครั้งที่ตัวจับเวลาส่งซ้ำหมดเวลา iptables-extensions(8) — Linux manual page netfilter TCPMSS --clamp-mss-to-pmtu: เลี่ยงปัญหาแพ็กเก็ตใหญ่ไปไม่ถึงเพราะช่วงที่บล็อก ICMP ด้วยการปรับ MSS ใน SYN tcp(7) — Linux manual page Linux man-pages TCP_MAXSEG: ขนาด segment สูงสุดของแพ็กเก็ตขาออก ถ้าตั้งก่อนเชื่อมต่อ MSS ที่แจ้งให้อีกฝั่งทราบก็จะเปลี่ยนด้วย Network maximum transmission unit (MTU) for your EC2 instance AWS internet gateway และ VPN ใช้ MTU 1,500, PMTUD ต้องใช้ ICMP type 3 code 4 และถ้า security group หรือ network ACL บล็อกไว้จะรับไม่ได้ MTU considerations | Cloud VPN Google Cloud MTU ของ Cloud VPN gateway คือ 1,460 ไบต์, payload MTU ของอุโมงค์ IPv4 คือ 1,406 ไบต์ (ผ่านอุโมงค์แล้วเหลือราว 1,400) Demonstrations of tcpretrans, the Linux eBPF/bcc version IO Visor แสดงหนึ่งบรรทัดต่อการส่งซ้ำแต่ละครั้ง และ -s แสดง sequence number ของแพ็กเก็ตที่ส่งซ้ำด้วย ss(8) — Linux manual page iproute2 mss, pmtu (path MTU) และ backoff (จำนวนครั้งที่ RTO เพิ่มเป็นสองเท่า) ใน ss -i ping(8) — Linux manual page iputils -M do เปิด DF และไม่ส่งแพ็กเก็ตที่ใหญ่กว่า path MTU ที่เคอร์เนลรู้, -s คือขนาดข้อมูล (ไม่รวม ICMP header 8 ไบต์) Display Filter Reference: Internet Control Message Protocol Wireshark display filter icmp.type และ icmp.code
ID rt-mapping · ผู้รับผิดชอบหลัก พัฒนาไคลเอนต์ (ทีมพัฒนาเกม) · ร่วมกับ พัฒนาเซิร์ฟเวอร์ (ทีมพัฒนาเกม), อินฟราเครือข่าย (ทีมอินฟรา), อินฟราเซิร์ฟเวอร์ (ทีมอินฟรา)
ถ้าอุปกรณ์กลางทางลบ mapping (รายการที่บันทึกว่าจะส่งต่อการเชื่อมต่อนี้ไปที่ไหน) ของการเชื่อมต่อที่ idle แพ็กเก็ตถัดไปที่ส่งจะไปไม่ถึง การเชื่อมต่อจะส่งซ้ำวนไปจนหลุด หรืออุปกรณ์ตอบกลับด้วยการปฏิเสธการเชื่อมต่อ (RST) แล้วหลุดทันที
ทำไม การเชื่อมต่อที่ไม่มีแพ็กเก็ตวิ่งอยู่พักหนึ่ง (AFK, อยู่ในล็อบบี้) → ผลคือ NAT ของเราเตอร์, CGNAT ของ ISP, ไฟร์วอลล์, โหลดบาลานเซอร์ หรือ security group บนคลาวด์ลบ mapping ที่ idle → บนหน้าจอ พอกลับมาขยับ การส่งซ้ำต่อเนื่องจนหลุด หรือหลุดทันที
อาการ หลุด , ค้าง
ปัจจัย แพ็กเก็ตหาย
ใครเจอ เราคนเดียว, บางพื้นที่/บาง ISP
เกิดเมื่อไร หลังอยู่เฉย ๆ สักพัก
ผู้รับผิดชอบ ผู้รับผิดชอบหลัก พัฒนาไคลเอนต์ (ทีมพัฒนาเกม) · ร่วมกับ พัฒนาเซิร์ฟเวอร์ (ทีมพัฒนาเกม), อินฟราเครือข่าย (ทีมอินฟรา), อินฟราเซิร์ฟเวอร์ (ทีมอินฟรา)
งานฝั่งทีมพัฒนาเกม ไคลเอนต์: ส่ง heartbeat โดยเว้นช่วงไม่เกินครึ่งหนึ่งของ idle timeout ที่สั้นที่สุด (mapping ในเราเตอร์ของผู้เล่นและ CGNAT ของ ISP จะต่ออายุแน่นอนก็ต่อเมื่อมีแพ็กเก็ตขาออกจากฝั่งใน และเราเปลี่ยน timeout เหล่านั้นไม่ได้ ไคลเอนต์จึงต้องเป็นฝ่ายส่ง), เชื่อมต่อใหม่อัตโนมัติเมื่อหลุด เซิร์ฟเวอร์: ตอบ heartbeat และถ้าไม่ได้รับนานเกินกำหนดให้ปิดการเชื่อมต่อเองก่อน (ลดช่วง TCP keepalive ด้วย socket option เช่น TCP_KEEPIDLE, ตรวจจับให้เร็วด้วย TCP_USER_TIMEOUT), ใช้ session token เพื่อต่อเซสชันเดิม
งานฝั่งทีมอินฟรา เครือข่าย: รวบรวม idle timeout ของไฟร์วอลล์และโหลดบาลานเซอร์บนเส้นทางแล้วแชร์ให้ทีมพัฒนาเกม, เพิ่มค่าในไฟร์วอลล์และโหลดบาลานเซอร์ของเราถ้าจำเป็น เครื่องเซิร์ฟเวอร์/OS: ตรวจเวลา connection tracking ของ security group บนคลาวด์แล้วแชร์ให้ทีมพัฒนาเกม
ตัวเลขที่ควรรู้ เวลาที่คง TCP mapping ไว้ต่างกันไปตามอุปกรณ์ ตั้งแต่ไม่กี่นาทีถึงหลายชั่วโมง ถ้า security group บนคลาวด์ตั้งให้ติดตามการเชื่อมต่อ อินสแตนซ์ประเภท AWS Nitro v6 จะลบรายการที่ติดตามหลัง 350 วินาทีโดยค่าเริ่มต้น (ประเภทอื่น 5 วัน ดูรายการ “connection tracking ของ security group บนคลาวด์หมดอายุ”) ค่าเริ่มต้นของ TCP keepalive ใน Linux คือ “ตรวจเมื่อ idle ครบ 2 ชั่วโมง” จึงช้ากว่าอุปกรณ์ส่วนใหญ่
บนกราฟ การเชื่อมต่อหลุดพร้อมกัน · จำนวนครั้งที่หลุด, ระยะเวลา idle ก่อนหลุด
จุดที่ต้องดู packet capture ฝั่งเซิร์ฟเวอร์ช่วงไม่กี่นาทีสุดท้ายก่อนการเชื่อมต่อหลุด การเชื่อมต่อที่ยังอยู่ดูเวลา idle จาก lastsnd และ lastrcv (ms ที่ผ่านไปนับจากส่งและรับครั้งล่าสุด) ของ ss -ti และดู TcpExtTCPAbortOnTimeout (จำนวนการเชื่อมต่อที่ยกเลิกเพราะตัวจับเวลาหมด) ใน nstat ด้วย สัญญาณว่าใช่ การเชื่อมต่อที่หลุดทุกรายการมีเวลา idle ก่อนหลุดเกินค่าใกล้เคียงกัน (idle timeout ของอุปกรณ์บนเส้นทาง เช่น 350 วินาทีของ security group บนอินสแตนซ์ AWS Nitro v6) และตั้งแต่แพ็กเก็ตแรกหลัง idle มีแต่การส่งซ้ำโดยไม่มี ACK จนยกเลิก หรือได้ RST กลับมาทันที สัญญาณว่าไม่ใช่ หลุดระหว่างเล่นด้วยโดยไม่เกี่ยวกับเวลา idle: เป็นสาเหตุอื่น (“เส้นทางเปลี่ยน/เส้นทาง ECMP ที่เสีย”, “ไฟร์วอลล์/connection tracking ทิ้งแพ็กเก็ต”) ถ้าการเชื่อมต่อมี heartbeat วิ่งโดยเว้นช่วงไม่เกินครึ่งหนึ่งของ idle timeout ที่สั้นที่สุด ให้ตัดสาเหตุนี้ออก วิธีตรวจ ใช้เครื่องมือฝั่งอินฟรา (ไม่ต้องใช้โค้ดเกม)
แหล่งอ้างอิง 8 รายการ
ID rt-path · ผู้รับผิดชอบหลัก อินฟราเครือข่าย (ทีมอินฟรา) · ร่วมกับ พัฒนาเซิร์ฟเวอร์ (ทีมพัฒนาเกม), ภายนอก (ภายนอก)
แพ็กเก็ตจะหายไปในช่วงไม่กี่วินาทีที่เส้นทางอินเทอร์เน็ตเปลี่ยน หรือในการเชื่อมต่อที่ถูกจัดให้วิ่งบนเส้นทางที่เสียจากหลายเส้นทาง ECMP
ทำไม BGP คำนวณเส้นทางใหม่ หรืออุปกรณ์/ลิงก์ของเส้นทางหนึ่งในหลายเส้นทาง (ECMP, LAG) เสีย → ผลคือ แพ็กเก็ตหายชั่วคราวระหว่างสลับเส้นทาง หรือเฉพาะการเชื่อมต่อที่วิ่งบนเส้นทางนั้นหายอยู่ตลอด → บนหน้าจอ จู่ ๆ ก็ค้างไปไม่กี่วินาทีแล้วตามด้วยอาการกรอเร็ว หรือ “เชื่อมต่อใหม่แล้วดีขึ้น” (ถูกจัดไปเส้นทางอื่น)
อาการ ค้าง , กรอเร็ว , วาร์ป
ปัจจัย แพ็กเก็ตหาย
ใครเจอ บางพื้นที่/บาง ISP
เกิดเมื่อไร สุ่มเป็นครั้งคราว
ผู้รับผิดชอบ ผู้รับผิดชอบหลัก อินฟราเครือข่าย (ทีมอินฟรา) · ร่วมกับ พัฒนาเซิร์ฟเวอร์ (ทีมพัฒนาเกม), ภายนอก (ภายนอก)
งานฝั่งทีมพัฒนาเกม เก็บสถิติการส่งซ้ำต่อการเชื่อมต่อ (TCP_INFO) ไว้เพื่อดึง IP, พอร์ต และเวลาของคนที่เจอปัญหาได้, อย่าตัดการเชื่อมต่อที่หยุดไปไม่กี่วินาทีทันที
งานฝั่งทีมอินฟรา มอนิเตอร์อัตราการส่งซ้ำแยกตามพื้นที่/ISP, ตรวจว่าเชื่อมต่อใหม่แล้วเส้นทางเปลี่ยนหรือไม่, จัดหาลิงก์จากหลาย ISP, ตรวจหาลิงก์ที่เสียในเส้นทาง ECMP/LAG ของอุปกรณ์เรา, วัดเส้นทางด้วยพอร์ต TCP เดียวกับเกม (ใช้ mtr --tcp --port เพราะเส้นทางถูกกำหนดจากที่อยู่และพอร์ต ping ทั่วไปจึงอาจวิ่งไปอีกเส้นทางและดูปกติ)
งานฝั่งภายนอก รายงานเส้นทางที่เสียให้ ISP โดยแนบผลวัดเส้นทางด้วยพอร์ต TCP เดียวกับเกมและผลเทียบก่อน/หลังเชื่อมต่อใหม่
บนกราฟ ขึ้นเป็นขั้นบันไดจากจุดหนึ่ง · RTT (ปิง), อัตราการส่งซ้ำแยกตามพื้นที่/ISP
จุดที่ต้องดู รวมการส่งซ้ำแยกตามการเชื่อมต่อด้วย bcc tcpretrans -c เพื่อดึงที่อยู่และพอร์ตของผู้เล่นที่เจอปัญหา แล้วรัน mtr ด้วยพอร์ต TCP เดียวกับเกม (mtr -T -P PORT) ทั้งจากเซิร์ฟเวอร์ไปหาผู้เล่นและจากผู้เล่นมาหาเซิร์ฟเวอร์แล้วเทียบกัน เทียบผลก่อนและหลังเชื่อมต่อใหม่ด้วย สัญญาณว่าใช่ ตั้งแต่จุดเวลาหนึ่ง RTT ของพื้นที่หรือ ISP หนึ่งเปลี่ยนเป็นขั้นบันไดและแพ็กเก็ตหายกระจุกอยู่ไม่กี่วินาที หรือแม้ใน ISP เดียวกัน มีเพียงบางการเชื่อมต่อ (คู่ที่อยู่/พอร์ต) ที่ส่งซ้ำอยู่ตลอดและดีขึ้นเมื่อเชื่อมต่อใหม่ บางครั้ง ping ธรรมดาดูปกติ แต่เห็นแพ็กเก็ตหายเฉพาะใน TCP mtr สัญญาณว่าไม่ใช่ ทุกการเชื่อมต่อของ ISP นั้นแย่ลงพร้อมกันช่วงพีคหัวค่ำ: น่าจะเป็น “คิวคอขวดล้น” ถ้าแย่อยู่คนเดียวและแพ็กเก็ตหายตั้งแต่ ping ไปถึงเราเตอร์ น่าจะเป็น “แพ็กเก็ตหายช่วงไร้สาย” วิธีตรวจ ใช้เครื่องมือฝั่งอินฟรา (ไม่ต้องใช้โค้ดเกม)
กรณีจริง Cloudflare 2020: คอนฟิกแบ็กโบนของ Cloudflare ผิดพลาด ทำให้ทราฟฟิกบางเมืองหายไป
แหล่งอ้างอิง 5 รายการ
ID rt-spurious-delay · ผู้รับผิดชอบหลัก ภายนอก (ภายนอก) · ร่วมกับ อินฟราเซิร์ฟเวอร์ (ทีมอินฟรา), พัฒนาไคลเอนต์ (ทีมพัฒนาเกม)
แพ็กเก็ตยังอยู่ครบและแค่มาถึงช้ามากชั่วครู่ แต่ถ้าความหน่วงนั้นนานกว่า RTO ฝั่งส่งจะตัดสินว่าหายแล้วส่งซ้ำ
ทำไม bufferbloat, โหมดประหยัดพลังงานของ Wi-Fi, การเปลี่ยนสถานะวิทยุของมือถือ หรือ VM ถูกพักการทำงาน ทำให้ความหน่วงพุ่งชั่วขณะหลายร้อย ms → ผลคือ RTO หมดเวลาก่อนจึงส่งซ้ำ แล้วแพ็กเก็ตต้นฉบับก็มาถึงตามมา (ฝั่งรับได้รับซ้ำ) → บนหน้าจอ อาการค้างและกรอเร็วมาจากความหน่วงพุ่งเอง การส่งซ้ำโดยไม่จำเป็นแทบไม่ทำให้ค้างนานขึ้น แค่ดันเมตริกการส่งซ้ำให้สูงจนถูกเข้าใจผิดว่าแพ็กเก็ตหาย
อาการ ค้าง , กรอเร็ว , อินพุตดีเลย์
ปัจจัย ความหน่วง, จิตเตอร์
ใครเจอ เราคนเดียว, ทั้งเซิร์ฟเวอร์
เกิดเมื่อไร สุ่มเป็นครั้งคราว, หลังอยู่เฉย ๆ สักพัก
ผู้รับผิดชอบ ผู้รับผิดชอบหลัก ภายนอก (ภายนอก) · ร่วมกับ อินฟราเซิร์ฟเวอร์ (ทีมอินฟรา), พัฒนาไคลเอนต์ (ทีมพัฒนาเกม)
งานฝั่งทีมพัฒนาเกม ไคลเอนต์ Android 10 ขึ้นไปให้ขอโหมด Wi-Fi ความหน่วงต่ำระหว่างเล่น (Wi-Fi lock แบบ WIFI_MODE_FULL_LOW_LATENCY มีผลเฉพาะเมื่อจอเปิดอยู่และเกมอยู่เบื้องหน้า) เพื่อลดความหน่วงพุ่งจากโหมดประหยัดพลังงาน
งานฝั่งทีมอินฟรา หลีกเลี่ยงอินสแตนซ์แบบ burstable, อย่าลดค่าต่ำสุดของ RTO ต่ำเกินไป, คง F-RTO และ timestamps ไว้ (tcp_frto, tcp_timestamps), ดูเมตริกการส่งซ้ำคู่กับ TCPSpuriousRTOs และ TCPDSACKRecv ของ nstat เพื่อไม่ให้เข้าใจผิดว่าแพ็กเก็ตหาย
งานฝั่งภายนอก แนะนำให้ผู้เล่นใช้ SQM บนเราเตอร์และปิดโหมดประหยัดพลังงานของ Wi-Fi เพื่อลดความหน่วงพุ่งที่ต้นเหตุ
ตัวเลขที่ควรรู้ Linux ตรวจจับ RTO ที่ไม่จำเป็นด้วย F-RTO และบางครั้งก็ย้อนการลดอัตราการส่งกลับคืน ตรวจได้จาก TCPSpuriousRTOs (จำนวนครั้งที่ตัดสินว่าเป็น RTO ที่ไม่จำเป็น) และ TCPDSACKRecv (จำนวนครั้งที่ฝั่งรับแจ้งว่า “ได้รับไปแล้ว”) ใน nstat
บนกราฟ พุ่งแบบสุ่มเป็นครั้งคราว · RTT (ปิง), จำนวน RTO ที่ไม่จำเป็น
จุดที่ต้องดู ค่าที่เพิ่มขึ้นของ TcpExtTCPTimeouts (RTO หมดเวลา), TcpExtTCPSpuriousRTOs, TcpExtTCPDSACKRecv และ TcpExtTCPLostRetransmit จากการรัน nstat ทุก 1 นาที ดูไปพร้อมกัน ถ้ามี packet capture ใช้ตัวกรอง Wireshark tcp.analysis.spurious_retransmission สัญญาณว่าใช่ เมื่อ RTO เพิ่ม TcpExtTCPSpuriousRTOs หรือ TcpExtTCPDSACKRecv ก็เพิ่มตาม และในเวลาเดียวกัน RTT พุ่งเป็นหลายร้อย ms ใน capture ฝั่งรับมีทั้งแพ็กเก็ตต้นฉบับและแพ็กเก็ตที่ส่งซ้ำมาถึง สัญญาณว่าไม่ใช่ TcpExtTCPSpuriousRTOs และ DSACK ไม่ขยับ แต่ TcpExtTCPLostRetransmit (แพ็กเก็ตที่ส่งซ้ำก็หายอีก) เพิ่มขึ้น: เป็นแพ็กเก็ตหายจริง ถ้า RTT ไม่พุ่งแต่ DSACK สูงอยู่ตลอด น่าจะเป็น “fast retransmit โดยไม่จำเป็นเพราะแพ็กเก็ตสลับลำดับ” วิธีตรวจ ใช้เครื่องมือฝั่งอินฟรา (ไม่ต้องใช้โค้ดเกม)
แหล่งอ้างอิง 11 รายการ
ID rt-reorder · ผู้รับผิดชอบหลัก อินฟราเครือข่าย (ทีมอินฟรา) · ร่วมกับ อินฟราเซิร์ฟเวอร์ (ทีมอินฟรา)
เมื่อแพ็กเก็ตสลับลำดับเพราะวิ่งผ่านหลายเส้นทางหรือลิงก์ที่รวมกัน ฝั่งรับจะแจ้งว่า “มีแพ็กเก็ตขาดหาย” ด้วย duplicate ACK และฝั่งส่งจะส่งแพ็กเก็ตที่ไม่ได้หายซ้ำ
ทำไม อุปกรณ์ที่แบ่งเส้นทางเป็นรายแพ็กเก็ต, LAG (การรวมลิงก์) ที่กระจายเป็นรายแพ็กเก็ต และจังหวะที่เส้นทางเปลี่ยน ทำให้ลำดับสลับกัน → ผลคือ แพ็กเก็ตหลังมาถึงก่อน duplicate ACK สะสมครบ 3 ตัว → fast retransmit → บนหน้าจอ แพ็กเก็ตเกมที่วิ่งห่าง ๆ แทบไม่ได้รับผล อัปเดตใหญ่ในที่ที่คนเยอะและการดาวน์โหลดแพตช์ช้าลง และบางครั้งกระตุก
อาการ กระตุก , อินพุตดีเลย์
ปัจจัย จิตเตอร์
ใครเจอ บางพื้นที่/บาง ISP, ทั้งเซิร์ฟเวอร์
เกิดเมื่อไร ตลอดเวลา, ตอนคนแห่มารวมกัน
ผู้รับผิดชอบ ผู้รับผิดชอบหลัก อินฟราเครือข่าย (ทีมอินฟรา) · ร่วมกับ อินฟราเซิร์ฟเวอร์ (ทีมอินฟรา)
งานฝั่งทีมอินฟรา เครือข่าย: กระจายเป็นรายการเชื่อมต่อแทนรายแพ็กเก็ต (ใช้ hash ของที่อยู่และพอร์ตกับ ECMP/LAG) เครื่องเซิร์ฟเวอร์/OS: ใช้ RACK (ตัดสินการหายตามเวลา ทนต่อการสลับลำดับ และเมื่อตรวจพบการส่งซ้ำโดยไม่จำเป็นจาก DSACK จะขยายช่วงที่ยอมให้สลับลำดับเองอัตโนมัติ), ตรวจระดับการสลับลำดับที่ Linux ประเมินเองในแต่ละการเชื่อมต่อ (ค่า reordering ใน ss -ti ค่าเริ่มต้น tcp_reordering=3)
บนกราฟ สูงตลอดตั้งแต่แรก · จำนวนครั้งที่ตรวจพบการสลับลำดับ, จำนวน DSACK ที่ได้รับ
จุดที่ต้องดู TcpExtTCPSACKReorder และ TcpExtTCPTSReorder (จำนวนครั้งที่ตรวจพบการสลับลำดับ) กับ TcpExtTCPDSACKRecv ใน nstat ส่วนแต่ละการเชื่อมต่อดู reordering (แสดงเมื่อไม่ใช่ 3) และ reord_seen ใน ss -ti ใน packet capture ใช้ตัวกรอง Wireshark tcp.analysis.out_of_order สัญญาณว่าใช่ ตัวนับการสลับลำดับและ DSACK ขึ้นเรื่อย ๆ ไม่ขึ้นกับช่วงเวลา และค่า reordering ของการเชื่อมต่อที่ผ่านเส้นทางหรืออุปกรณ์หนึ่งสูงกว่า 3 ใน capture ฝั่งรับ แพ็กเก็ตหลังมาก่อน และแพ็กเก็ตก่อนหน้าก็ตามมาในไม่ช้า สัญญาณว่าไม่ใช่ ตัวนับการสลับลำดับไม่ขยับ แต่ TcpExtTCPLostRetransmit เพิ่ม: เป็นแพ็กเก็ตหายจริง ถ้า DSACK เพิ่มเฉพาะจังหวะที่ RTT พุ่ง น่าจะเป็น “การส่งซ้ำโดยไม่จำเป็นเพราะความหน่วงพุ่ง” วิธีตรวจ ใช้เครื่องมือฝั่งอินฟรา (ไม่ต้องใช้โค้ดเกม)
แหล่งอ้างอิง 9 รายการ
ID rt-ack-path · ผู้รับผิดชอบหลัก ภายนอก (ภายนอก) · ร่วมกับ พัฒนาไคลเอนต์ (ทีมพัฒนาเกม)
ข้อมูลมาถึงเรียบร้อย แต่ถ้า ACK ที่บอกว่า “ได้รับแล้ว” ไปติดอยู่ในคิวอัปโหลดที่เต็มจนช้าหรือหาย ฝั่งส่งจะตัดสินว่าหายแล้วส่งซ้ำ
ทำไม อัปโหลดเต็มเพราะมีคนในบ้านอัปโหลดวิดีโอหรือสำรองข้อมูลขึ้นคลาวด์ → ผลคือ ACK ติดอยู่ในคิวของเราเตอร์ช้าไปหลายร้อย ms หรือถูกทิ้งเพราะคิวล้น → บนหน้าจอ แพ็กเก็ตเกมที่เซิร์ฟเวอร์ส่งมาส่วนใหญ่มาตรงเวลา แต่อินพุตของเราที่กองอยู่ในคิวอัปโหลดเดียวกันไปช้า จึงเกิดอินพุตดีเลย์และดีดกลับ บางครั้งมีการส่งซ้ำโดยไม่จำเป็น
อาการ อินพุตดีเลย์ , ดีดกลับ
ปัจจัย ความหน่วง, แพ็กเก็ตหาย
ใครเจอ คนในบ้านเดียวกัน
เกิดเมื่อไร สุ่มเป็นครั้งคราว, ช่วงพีคหัวค่ำ
ผู้รับผิดชอบ ผู้รับผิดชอบหลัก ภายนอก (ภายนอก) · ร่วมกับ พัฒนาไคลเอนต์ (ทีมพัฒนาเกม)
งานฝั่งทีมพัฒนาเกม แสดงสถานะเครือข่ายบนจอเมื่อปิงพุ่ง, ขึ้นคำแนะนำ “ตรวจโปรแกรมที่กำลังอัปโหลด”
งานฝั่งภายนอก แนะนำให้ผู้เล่นใช้ SQM บนเราเตอร์เพื่อให้คิวอัปโหลดสั้น, ให้แพ็กเก็ตเล็ก (ACK) ไปก่อน, จำกัดความเร็วอัปโหลด (อัปโหลดวิดีโอ, สำรองข้อมูลขึ้นคลาวด์)
ตัวเลขที่ควรรู้ ACK ตัวหลังยืนยันแทนตัวก่อนหน้าได้ ACK หายไปไม่กี่ตัวจึงมักไม่เป็นไร ปัญหาอยู่ที่ ACK ที่ติดอยู่ในคิวจนช้า
บนกราฟ สูงเฉพาะบางกลุ่ม · RTT (ปิง) ต่อการเชื่อมต่อ
จุดที่ต้องดู ping ไปเซิร์ฟเวอร์เกมจาก PC ของผู้เล่น เทียบระหว่างตอนเปิดและปิดการอัปโหลด (อัปโหลดวิดีโอ, สำรองข้อมูลขึ้นคลาวด์) ฝั่งเซิร์ฟเวอร์ดู rtt ของการเชื่อมต่อผู้เล่นคนนั้นด้วย ss -ti สัญญาณว่าใช่ ping ขึ้นเป็นหลายร้อย ms เฉพาะตอนอัปโหลด และเกิดอินพุตดีเลย์และดีดกลับ พอหยุดอัปโหลดก็กลับมาปกติในไม่ช้า ฝั่งเซิร์ฟเวอร์เห็น rtt ของการเชื่อมต่อนั้นขึ้นในช่วงเดียวกัน สัญญาณว่าไม่ใช่ แพ็กเก็ตหายและความหน่วงเกิดโดยไม่เกี่ยวกับการอัปโหลด: น่าจะเป็น “แพ็กเก็ตหายช่วงไร้สาย” หรือสาเหตุฝั่งเส้นทาง ถ้าช้าเฉพาะทิศทางจากเซิร์ฟเวอร์ไปหาผู้เล่นและไม่เกี่ยวกับการอัปโหลด น่าจะเป็น “คิวคอขวดล้น” วิธีตรวจ ตรวจที่สภาพแวดล้อมฝั่งผู้เล่น
แหล่งอ้างอิง 4 รายการ
ID rt-rto-setting · ผู้รับผิดชอบหลัก อินฟราเซิร์ฟเวอร์ (ทีมอินฟรา) · ร่วมกับ พัฒนาเซิร์ฟเวอร์ (ทีมพัฒนาเกม)
ถ้าลดค่าต่ำสุดของ RTO มากเกินไป แค่ช้านิดเดียวก็เกิดการส่งซ้ำโดยไม่จำเป็น ส่วนค่าเริ่มต้น (200 ms) ก็นานเกินไปสำหรับเกม ทุกครั้งที่แพ็กเก็ตหายจึงหยุดนาน
ทำไม ลดค่าต่ำสุดของ RTO ลงมากเพื่อใช้ในดาต้าเซ็นเตอร์ หรือใช้ค่าเริ่มต้นตามเดิมกับเส้นทางอินเทอร์เน็ต → ผลคือ ถ้าต่ำ แค่ความหน่วงชั่วขณะก็ส่งซ้ำทะลัก ถ้าสูง หายทุกครั้งก็ต้องรอนาน → บนหน้าจอ ถ้าใช้ค่าเริ่มต้น แพ็กเก็ตหายครั้งเดียวจะค้างหลายร้อย ms แล้วตามด้วยอาการกรอเร็ว ถ้าลดต่ำเกินไป อาการค้างจะลดลงแต่การส่งซ้ำโดยไม่จำเป็นพุ่งจนเปลืองแบนด์วิดท์
อาการ ค้าง , กรอเร็ว , อินพุตดีเลย์
ปัจจัย ความหน่วง
ใครเจอ ทั้งเซิร์ฟเวอร์
เกิดเมื่อไร ตลอดเวลา
ผู้รับผิดชอบ ผู้รับผิดชอบหลัก อินฟราเซิร์ฟเวอร์ (ทีมอินฟรา) · ร่วมกับ พัฒนาเซิร์ฟเวอร์ (ทีมพัฒนาเกม)
งานฝั่งทีมพัฒนาเกม ถ้าใช้ Linux 6.15 ขึ้นไป พิจารณาลดเพดาน RTO ของการเชื่อมต่อเกมด้วย TCP_RTO_MAX_MS (เวลาจนถึงการเลิกเชื่อมต่อก็สั้นลงด้วย จึงควรกำหนดเวลาตัดสินว่าการเชื่อมต่อขาดด้วย TCP_USER_TIMEOUT ไปพร้อมกัน), ลดค่าต่ำสุดของ RTO ด้วย socket option TCP_RTO_MIN_US (6.15 ขึ้นไป) เฉพาะการเชื่อมต่อภายในระหว่างเซิร์ฟเวอร์, พิจารณาใช้ socket option TCP_THIN_LINEAR_TIMEOUTS กับการเชื่อมต่อเกมเท่านั้น เพื่อไม่ให้ RTO ที่เกิดต่อเนื่องเพิ่มเป็นสองเท่า
งานฝั่งทีมอินฟรา ลด rto_min แยกตามเส้นทางเฉพาะการเชื่อมต่อภายในระหว่างเซิร์ฟเวอร์, เส้นทางอินเทอร์เน็ตคงค่าเริ่มต้นไว้แต่เสริมด้วย RACK-TLP และการตั้งค่า thin stream (tcp_thin_linear_timeouts)
ตัวเลขที่ควรรู้ RTO ของ Linux = เวลาไปกลับ + max(200 ms, ส่วนเบี่ยงเบนของ RTT×4) ล้มเหลวแต่ละครั้งจะเพิ่มเป็นสองเท่า สูงสุด 120 วินาที Linux 6.15 ขึ้นไปลดเพดานนี้ลงได้ถึง 1 วินาทีด้วย TCP_RTO_MAX_MS
บนกราฟ สูงตลอดตั้งแต่แรก · RTO ต่อการเชื่อมต่อ, จำนวน RTO ที่ไม่จำเป็น
จุดที่ต้องดู การตั้งค่าต่ำสุดของ RTO บนเซิร์ฟเวอร์ (rto_min ใน ip route show, Linux 6.11 ขึ้นไปดู sysctl net.ipv4.tcp_rto_min_us) กับ rto และ rtt ใน ss -ti และค่าที่เพิ่มขึ้นของ TcpExtTCPSpuriousRTOs ใน nstat สัญญาณว่าใช่ บนเซิร์ฟเวอร์ที่ลดค่าต่ำสุดลง rto ของการเชื่อมต่ออินเทอร์เน็ตแนบชิด rtt และ TcpExtTCPSpuriousRTOs เพิ่มขึ้นมาก ถ้าใช้ค่าเริ่มต้นตามเดิม rto ของการเชื่อมต่อเกมสูงกว่า rtt ตั้งแต่ 200 ms ขึ้นไป และแพ็กเก็ตหายแต่ละครั้งจะหยุดนานเท่านั้น สัญญาณว่าไม่ใช่ rto เป็นไปตามสูตรปกติ (rtt + ราว 200 ms) และ RTO ที่ไม่จำเป็นก็น้อย แต่การหยุดนานผิดปกติ: น่าจะเป็นฝั่งแพ็กเก็ตหายต่อเนื่องหรือวิธีกู้คืน (“thin stream กู้คืนช้า”, “อุปกรณ์กลางทางตัด TCP option ทิ้ง”) วิธีตรวจ ใช้เครื่องมือฝั่งอินฟรา (ไม่ต้องใช้โค้ดเกม)
แหล่งอ้างอิง 12 รายการ RFC 6298: Computing TCP's Retransmission Timer IETF RTO = SRTT + max(G, 4·RTTVAR), แนะนำอย่างน้อย 1 วินาที, เพิ่มเป็นสองเท่าทุกครั้งที่ล้มเหลว, ถ้าจะกำหนดค่าสูงสุดต้องไม่น้อยกว่า 60 วินาที include/net/tcp.h Linux kernel TCP_RTO_MIN ของ Linux 200 ms, TCP_RTO_MAX 120 วินาที net/ipv4/tcp_input.c Linux kernel RTO ของ Linux คือ SRTT + rttvar และ rttvar จะไม่ต่ำกว่าค่าต่ำสุดของ RTO (ค่าเริ่มต้น 200 ms) tcp: add the ability to control max RTO Linux kernel เพิ่ม socket option TCP_RTO_MAX_MS (1–120 วินาที) ตั้งแต่ Linux 6.15 tcp: add sysctl_tcp_rto_min_us Linux kernel เพิ่ม tcp_rto_min_us ซึ่งเป็นค่าต่ำสุดของ RTO เริ่มต้นของทั้งเซิร์ฟเวอร์ ตั้งแต่ Linux 6.11 tcp: support TCP_RTO_MIN_US for set/getsockopt use Linux kernel เพิ่ม socket option TCP_RTO_MIN_US สำหรับกำหนดค่าต่ำสุดของ RTO รายซ็อกเก็ต ตั้งแต่ Linux 6.15 IP Sysctl Linux kernel tcp_rto_min_us ค่าเริ่มต้น 200000 (ตัวเลือกเส้นทาง rto_min และ socket option TCP_RTO_MIN_US มีผลก่อน), tcp_rto_max_ms 1,000–120,000 (ค่าเริ่มต้น 120,000), tcp_thin_linear_timeouts ip-route(8) — Linux manual page iproute2 ตัวเลือก rto_min รายเส้นทาง: ค่าต่ำสุดของ RTO เมื่อสื่อสารกับปลายทางนั้น Thin-streams and TCP Linux kernel ใช้ TCP_THIN_LINEAR_TIMEOUTS ปิด exponential backoff เฉพาะการเชื่อมต่อแบบ thin stream ได้ tcp(7) — Linux manual page Linux man-pages TCP_USER_TIMEOUT: เวลาที่รอข้อมูลที่ยังไม่ได้รับการยืนยันก่อนปิดการเชื่อมต่อ ss(8) — Linux manual page iproute2 rto (ms) และ rtt ใน ss -i SNMP counter Linux kernel TcpExtTCPSpuriousRTOs: RTO ที่ไม่จำเป็นซึ่ง F-RTO ตรวจพบ
ID rt-thin · ผู้รับผิดชอบหลัก พัฒนาเซิร์ฟเวอร์ (ทีมพัฒนาเกม) · ร่วมกับ อินฟราเซิร์ฟเวอร์ (ทีมอินฟรา), พัฒนาไคลเอนต์ (ทีมพัฒนาเกม)
ถ้าส่งแพ็กเก็ตเล็ก ๆ ห่าง ๆ แบบเกม RTO จะมาถึงก่อนที่ “แพ็กเก็ตที่ตามมา 3 ตัว” จะครบ เมื่อหายเท่ากัน จึงหยุดนานกว่าการส่งข้อมูลปริมาณมากอยู่มาก
ทำไม แพ็กเก็ตห่างกันราว 100 ms แพ็กเก็ตที่ยังไม่ได้รับ ACK (in-flight) จึงมีอยู่ไม่กี่ตัว → ผลคือ กว่า duplicate ACK จะครบ 3 ตัวต้องใช้เวลาเกิน 300 ms จึงเป็น RTO (ปิง + 200 ms) ที่ทำงานก่อน ถ้าหายต่อเนื่องก็เพิ่มเป็นสองเท่าทุกครั้ง → บนหน้าจอ แพ็กเก็ตหายครั้งเดียวค้างราว 0.3 วินาที ถ้าตัวที่ส่งซ้ำหายอีก จะค้างเกือบ 1 วินาทีแล้วตามด้วยอาการกรอเร็ว
อาการ ค้าง , กรอเร็ว
ปัจจัย แพ็กเก็ตหาย, การหยุดชะงัก
ใครเจอ เราคนเดียว, ทั้งเซิร์ฟเวอร์
เกิดเมื่อไร สุ่มเป็นครั้งคราว
ผู้รับผิดชอบ ผู้รับผิดชอบหลัก พัฒนาเซิร์ฟเวอร์ (ทีมพัฒนาเกม) · ร่วมกับ อินฟราเซิร์ฟเวอร์ (ทีมอินฟรา), พัฒนาไคลเอนต์ (ทีมพัฒนาเกม)
งานฝั่งทีมพัฒนาเกม เซิร์ฟเวอร์: เปิด TCP_NODELAY (ถ้าเปิด Nagle ไว้ จะไม่มีแพ็กเก็ตที่ตามมาให้ RACK ใช้ตัดสิน), ส่งแพ็กเก็ตเรียลไทม์ด้วยการส่งซ้ำที่ทำเองบน UDP ไคลเอนต์: เปิด TCP_NODELAY, ส่งแพ็กเก็ตเรียลไทม์แบบเดียวกับเซิร์ฟเวอร์ (UDP)
งานฝั่งทีมอินฟรา ใช้ RACK-TLP (ค่าเริ่มต้นของ Linux รุ่นใหม่), ใช้ tcp_thin_linear_timeouts เพื่อไม่ให้ RTO ที่เกิดต่อเนื่องเพิ่มเป็นสองเท่า
ตัวเลขที่ควรรู้ ถ้าแพ็กเก็ตห่างกัน 100 ms และปิง 60 ms กว่าจะถึง fast retransmit ใช้เวลาราว 360 ms (จนแพ็กเก็ตที่ตามมา 3 ตัวมาถึงและการยืนยันกลับมา) ส่วน RTO ประมาณ 260 ms ถ้าใช้ RACK จะส่งซ้ำทันทีที่การยืนยันของแพ็กเก็ตถัดไปกลับมา ที่ราว 160 ms ถ้าแพ็กเก็ตห่างกันเกิน 200 ms RACK ก็ไม่เร็วกว่า RTO
บนกราฟ ขาดช่วงแล้วมารวดเดียว · ปริมาณที่รับต่อการเชื่อมต่อ, จำนวนครั้งที่ RTO หมดเวลา
จุดที่ต้องดู เทียบค่าที่เพิ่มขึ้นของ TcpExtTCPTimeouts (RTO หมดเวลา), TcpExtTCPFastRetrans (fast retransmit), TcpExtTCPLossProbes และ TcpExtTCPLossProbeRecovery (TLP) ใน nstat และดู rto กับ backoff ของการเชื่อมต่อเกมด้วย ss -ti ตรวจค่า net.ipv4.tcp_recovery, tcp_early_retrans และ tcp_sack ของเซิร์ฟเวอร์ด้วย สัญญาณว่าใช่ ในบรรดาการส่งซ้ำ RTO หมดเวลามากกว่า fast retransmit และเห็นการเชื่อมต่อเกมที่ backoff มากกว่า 0 (กำลังเจอ RTO) บ่อย ระหว่างที่หยุด ปริมาณที่รับเป็น 0 พอกู้คืนได้ข้อมูลก็ทะลักมาพร้อมกัน สัญญาณว่าไม่ใช่ การส่งข้อมูลปริมาณมากบนเซิร์ฟเวอร์เดียวกันก็หยุดนานพอกัน: เป็นปัญหาแพ็กเก็ตหายที่ไม่เกี่ยวกับรูปแบบการเชื่อมต่อ ถ้ากระจุกที่การเชื่อมต่อที่ไม่มี SACK หรือ timestamps น่าจะเป็น “อุปกรณ์กลางทางตัด TCP option ทิ้ง” วิธีตรวจ ใช้เครื่องมือฝั่งอินฟรา (ไม่ต้องใช้โค้ดเกม)
รายละเอียดเพิ่มเติม เดิม Linux เคยมีตัวเลือกส่งซ้ำเมื่อได้ duplicate ACK เพียง 1 ตัวสำหรับ thin stream (tcp_thin_dupack) แต่ถูกถอดออกในปี 2017 ปัจจุบัน RACK ทำหน้าที่นั้นแทน ถ้าเปิด Nagle อยู่ (ปิด TCP_NODELAY) ระหว่างรอการยืนยันของแพ็กเก็ตที่หาย TCP จะไม่ส่งแพ็กเก็ตใหม่ด้วย RACK จึงไม่มีแพ็กเก็ตที่ตามมาให้ใช้ตัดสิน และต้องรอจนถึง RTO
แหล่งอ้างอิง 11 รายการ Thin-streams and TCP Linux kernel thin stream ที่ส่งห่าง ๆ แบบเกม fast retransmit ทำงานได้ไม่ดี จึงต้องพึ่ง timeout ที่ยาว เกณฑ์คือแพ็กเก็ตที่ยังไม่ได้รับ ACK (in-flight) น้อยกว่า 4 ตัว RFC 5681: TCP Congestion Control IETF ทำ fast retransmit เมื่อได้รับ duplicate ACK ตัวที่สาม RFC 8985: The RACK-TLP Loss Detection Algorithm for TCP IETF RACK ตัดสินการหายจากการที่แพ็กเก็ตซึ่งส่งทีหลังส่งถึงแล้ว เวลารอของ TLP คือ 2·SRTT (ถ้ามีแพ็กเก็ตที่ยังไม่ได้รับการยืนยันเพียงตัวเดียว จะบวกเวลาเผื่อ delayed ACK) include/net/tcp.h Linux kernel TCP_RTO_MIN 200 ms, เกณฑ์ thin stream (แพ็กเก็ต in-flight น้อยกว่า 4 ตัว) และการลองใหม่แบบ linear 6 ครั้ง tcp: remove thin_dupack feature Linux kernel ลบ thin_dupack ในเดือนมกราคม 2017 (Linux 4.11) พร้อมคำอธิบายว่า RACK ทำหน้าที่นั้นแทน IP Sysctl Linux kernel tcp_thin_linear_timeouts: ถ้าเป็น thin stream RTO จะไม่เพิ่มเป็นสองเท่าในช่วงสูงสุด 6 ครั้งแรก (ปิดเป็นค่าเริ่มต้น) tcp(7) — Linux manual page Linux man-pages TCP_NODELAY ปิดอัลกอริทึม Nagle net/ipv4/proc.c Linux kernel ชื่อตัวนับที่ nstat แสดง: TCPTimeouts, TCPFastRetrans, TCPLossProbes, TCPLossProbeRecovery net/ipv4/tcp_timer.c Linux kernel TCPTimeouts เพิ่มขึ้นเมื่อตัวจับเวลาส่งซ้ำ (RTO) หมดเวลา SNMP counter Linux kernel TcpExtTCPFastRetrans (การส่งซ้ำขณะที่ไม่ได้อยู่ในสถานะ Loss), TcpExtTCPLossProbes (ส่ง TLP) และ TcpExtTCPLossProbeRecovery (กู้คืนการหายด้วย TLP) ss(8) — Linux manual page iproute2 rto (ms) และ backoff (จำนวนครั้งที่ RTO เพิ่มเป็นสองเท่า) ใน ss -i
ID rt-sack-stripped · ผู้รับผิดชอบหลัก อินฟราเครือข่าย (ทีมอินฟรา) · ร่วมกับ อินฟราเซิร์ฟเวอร์ (ทีมอินฟรา)
ถ้าไฟร์วอลล์หรืออุปกรณ์เร่งความเร็วบางตัวลบหรือแก้ TCP option เมื่อแพ็กเก็ตหายหลายตัว จะกู้คืนได้แค่ตัวเดียวต่อหนึ่งรอบไปกลับ หรือ window (ปริมาณที่ส่งได้ในครั้งเดียว) จะเล็กลงจนช้า
ทำไม “TCP normalization” ของไฟร์วอลล์ หรืออุปกรณ์เร่งความเร็วรุ่นเก่าลบ option SACK, timestamps และ window scaling → ผลคือ ถ้าแพ็กเก็ตหายหลายตัว จะกู้คืนได้ทีละตัวต่อรอบไปกลับ, window ถูกจำกัดไว้ที่ 64 KB → บนหน้าจอ ทุกครั้งที่หายจะค้างนานขึ้นมาก (ไม่มี SACK ก็ใช้ RACK-TLP ไม่ได้) แล้วตามด้วยอาการกรอเร็ว การส่งข้อมูลปริมาณมากอย่างแพตช์ก็ช้า
อาการ ค้าง , กรอเร็ว
ปัจจัย การหยุดชะงัก, ความหน่วง
ใครเจอ บางพื้นที่/บาง ISP, ทั้งเซิร์ฟเวอร์
เกิดเมื่อไร ตลอดเวลา
ผู้รับผิดชอบ ผู้รับผิดชอบหลัก อินฟราเครือข่าย (ทีมอินฟรา) · ร่วมกับ อินฟราเซิร์ฟเวอร์ (ทีมอินฟรา)
งานฝั่งทีมอินฟรา เครือข่าย: ปิดการตั้งค่า TCP normalization ของอุปกรณ์นั้น, ตรวจ sequence randomization ของไฟร์วอลล์ด้วย, เทียบ option ใน SYN จาก packet capture ที่ปลายทั้งสองฝั่ง เครื่องเซิร์ฟเวอร์/OS: ตรวจว่าการเชื่อมต่อที่ไม่มี sack และ wscale ใน ss -ti กระจุกที่เส้นทางใดหรือไม่ (PC Windows บางเครื่องไม่ใช้ ts ตามการตั้งค่า การที่ขาดแค่ ts จึงอาจเป็นเรื่องปกติ), ตรวจว่า net.ipv4.tcp_sack ของเซิร์ฟเวอร์เป็น 1
บนกราฟ สูงตลอดตั้งแต่แรก · จำนวนการกู้คืนที่เริ่มโดยไม่มี SACK (TcpExtTCPRenoRecovery)
จุดที่ต้องดู ดูว่าแต่ละการเชื่อมต่อใน ss -ti มี sack และ wscale หรือไม่ ดูสัดส่วน TcpExtTCPRenoRecovery (การกู้คืนที่เริ่มโดยไม่มี SACK) ต่อ TcpExtTCPSackRecovery และ TcpExtTCPSACKDiscard (จำนวน SACK block ที่ทิ้งเพราะตัวเลขไม่สอดคล้องกัน) ใน nstat เส้นทางที่สงสัยให้ capture SYN ที่ปลายทั้งสองฝั่งแล้วเทียบ option (เช่น tcp.options.sack_perm ใน Wireshark) สัญญาณว่าใช่ เฉพาะการเชื่อมต่อที่ผ่านเส้นทางหรืออุปกรณ์หนึ่งที่ไม่มี sack และ wscale และสัดส่วน TcpExtTCPRenoRecovery สูง option อนุญาต SACK ที่มีใน SYN ฝั่งส่งไม่มีใน SYN ฝั่งรับ ถ้าสาเหตุคือ sequence randomization option จะยังอยู่ แต่ TcpExtTCPSACKDiscard เพิ่มขึ้น สัญญาณว่าไม่ใช่ ทุกการเชื่อมต่อไม่มี sack: ตรวจค่า net.ipv4.tcp_sack ของเซิร์ฟเวอร์ก่อน ถ้า option ครบและ TcpExtTCPSACKDiscard ไม่ขยับ การกู้คืนช้ามาจากที่อื่น (“thin stream กู้คืนช้า”) วิธีตรวจ ใช้เครื่องมือฝั่งอินฟรา (ไม่ต้องใช้โค้ดเกม)
รายละเอียดเพิ่มเติม ถึง option ยังอยู่ SACK ก็อาจเสียได้ ถ้า sequence randomization ของไฟร์วอลล์เปลี่ยนแค่ sequence number ใน header แต่ไม่แก้ตัวเลขใน SACK ฝั่งส่งจะทิ้ง SACK ที่ตัวเลขไม่สอดคล้องกัน กรณีที่ปิด tcp_sack=0 บนเซิร์ฟเวอร์ไว้ตอนเกิดปัญหาความปลอดภัยของ SACK ในปี 2019 แล้วลืมเปิดคืน ก็ให้ผลแบบเดียวกัน
แหล่งอ้างอิง 10 รายการ
ID rt-zero-window · ผู้รับผิดชอบหลัก พัฒนาไคลเอนต์ (ทีมพัฒนาเกม) · ร่วมกับ พัฒนาเซิร์ฟเวอร์ (ทีมพัฒนาเกม), อินฟราเซิร์ฟเวอร์ (ทีมอินฟรา)
ถ้าโปรแกรมฝั่งรับอ่านซ็อกเก็ตไม่ทันจนบัฟเฟอร์เต็ม ฝั่งส่งจะหยุดส่งและส่งแค่ zero window probe ปัญหานี้ไม่ได้อยู่ที่เน็ต
ทำไม เฟรมของไคลเอนต์หยุดชะงักหรือเธรดของเซิร์ฟเวอร์ติดขัด จึงอ่านซ็อกเก็ตไม่ได้ → ผลคือ receive window เป็น 0 ฝั่งส่งจึงหยุดส่งและส่งแค่ probe (ช่วงห่างค่อย ๆ ยาวขึ้น) → บนหน้าจอ ค้างแล้วตามด้วยอาการกรอเร็ว ใน packet capture เห็น “ZeroWindow” และไม่มีแพ็กเก็ตหาย
อาการ ค้าง , กรอเร็ว
ปัจจัย การหยุดชะงัก
ใครเจอ เราคนเดียว, ทั้งเซิร์ฟเวอร์
เกิดเมื่อไร ตอนคนแห่มารวมกัน, สุ่มเป็นครั้งคราว
ผู้รับผิดชอบ ผู้รับผิดชอบหลัก พัฒนาไคลเอนต์ (ทีมพัฒนาเกม) · ร่วมกับ พัฒนาเซิร์ฟเวอร์ (ทีมพัฒนาเกม), อินฟราเซิร์ฟเวอร์ (ทีมอินฟรา)
งานฝั่งทีมพัฒนาเกม ตรวจจากฝั่งที่ส่ง ZeroWindow ใน packet capture ก่อน (ฝั่งที่อ่านซ็อกเก็ตไม่ทัน), อ่านข้อมูลขาเข้าจากเครือข่ายต่อเนื่องในเธรดแยก, ตั้งขนาด receive buffer ให้เหมาะสม ไคลเอนต์: แก้ต้นเหตุที่ทำให้เฟรมหยุดชะงัก เช่น การโหลดและ GC เซิร์ฟเวอร์: แก้ต้นเหตุที่ทำให้เธรดที่อ่านซ็อกเก็ตติดขัด
งานฝั่งทีมอินฟรา เพิ่ม TcpExtTCPToZeroWindowAdv ใน nstat ของเซิร์ฟเวอร์ (จำนวนครั้งที่เซิร์ฟเวอร์แจ้ง receive window เป็น 0) เข้าในการมอนิเตอร์ (ถ้าเพิ่มขึ้นแปลว่าเป็นฝั่งเซิร์ฟเวอร์ ให้ส่งต่อฝ่ายพัฒนาเซิร์ฟเวอร์), จัดเตรียม packet capture ฝั่งเซิร์ฟเวอร์ให้
บนกราฟ ขาดช่วงแล้วมารวดเดียว · ปริมาณที่รับต่อการเชื่อมต่อ, จำนวนครั้งที่เกิด zero window
จุดที่ต้องดู หาฝั่งที่แจ้ง window เป็น 0 ใน packet capture ด้วยตัวกรอง Wireshark tcp.analysis.zero_window ส่วนใน nstat ของเซิร์ฟเวอร์ให้แยกดู TcpExtTCPToZeroWindowAdv (เซิร์ฟเวอร์แจ้ง window เป็น 0) กับ TcpExtTCPWinProbe (ส่ง probe ไปเพราะอีกฝั่งแจ้ง window เป็น 0) และดู Recv-Q ของซ็อกเก็ตเซิร์ฟเวอร์ (ไบต์ที่โปรแกรมยังไม่ได้อ่านใน ss) สัญญาณว่าใช่ ระหว่างที่หยุด ไม่มีการส่งซ้ำ มีแต่ zero window กับ probe วิ่งไปมา ถ้า TcpExtTCPToZeroWindowAdv ของเซิร์ฟเวอร์หรือ Recv-Q ของซ็อกเก็ตเซิร์ฟเวอร์เพิ่มขึ้น แปลว่าเซิร์ฟเวอร์อ่านไม่ทัน ถ้า TcpExtTCPWinProbe เพิ่มขึ้น แปลว่าไคลเอนต์อ่านไม่ทัน สัญญาณว่าไม่ใช่ ใน capture ไม่มี zero window และข้อมูลเดิมถูกส่งซ้ำ: น่าจะเป็นสาเหตุฝั่งแพ็กเก็ตหายหรือการส่งซ้ำโดยไม่จำเป็น วิธีตรวจ ใช้เครื่องมือฝั่งอินฟรา (ไม่ต้องใช้โค้ดเกม)
กรณีจริง Roblox 2021: Roblox ล่ม 73 ชั่วโมง: การแย่งทรัพยากรในคลัสเตอร์ service discovery (Consul)
แหล่งอ้างอิง 7 รายการ
ID rt-syn · ผู้รับผิดชอบหลัก พัฒนาเซิร์ฟเวอร์ (ทีมพัฒนาเกม) · ร่วมกับ อินฟราเซิร์ฟเวอร์ (ทีมอินฟรา), อินฟราเครือข่าย (ทีมอินฟรา), พัฒนาไคลเอนต์ (ทีมพัฒนาเกม)
ถ้าคำขอเชื่อมต่อหายไปเพราะคิวรอเชื่อมต่อ (backlog) ล้นหรือถูกไฟร์วอลล์บล็อก OS ฝั่งไคลเอนต์จะส่งใหม่ โดยเริ่มหลัง 1 วินาทีและเว้นช่วงห่างขึ้นเรื่อย ๆ
ทำไม การเชื่อมต่อทะลักทันทีหลังปิดปรับปรุงจนคิวรอเชื่อมต่อของเซิร์ฟเวอร์ล้น หรือไฟร์วอลล์/ระบบป้องกัน DDoS ทิ้ง SYN → ผลคือ OS ฝั่งไคลเอนต์ส่ง SYN ซ้ำตามช่วงที่กำหนด โดยเริ่มหลัง 1 วินาที (Linux รุ่นเก่า 1 วินาที → 2 วินาที → 4 วินาที) → บนหน้าจอ หลังกดปุ่มเชื่อมต่อ ช้าไปเป็นวินาทีพอดี ๆ เช่น 1 วินาที, 3 วินาที และถ้าล้มเหลวต่อเนื่องจะเข้าเกมไม่ได้หรือโหลดไม่จบ
อาการ เข้าเกมไม่ได้/โหลดไม่จบ
ปัจจัย แพ็กเก็ตหาย
ใครเจอ ทั้งเซิร์ฟเวอร์, บางพื้นที่/บาง ISP
เกิดเมื่อไร หลังล็อกอิน/หลังปิดปรับปรุง
ผู้รับผิดชอบ ผู้รับผิดชอบหลัก พัฒนาเซิร์ฟเวอร์ (ทีมพัฒนาเกม) · ร่วมกับ อินฟราเซิร์ฟเวอร์ (ทีมอินฟรา), อินฟราเครือข่าย (ทีมอินฟรา), พัฒนาไคลเอนต์ (ทีมพัฒนาเกม)
งานฝั่งทีมพัฒนาเกม เซิร์ฟเวอร์: เพิ่มอาร์กิวเมนต์ backlog ของ listen (พร้อมกับ somaxconn), ทำให้เซิร์ฟเวอร์เกมเรียก accept ได้ทัน, ใช้ระบบคิวล็อกอิน ไคลเอนต์: ยืดช่วงเวลาลองเชื่อมต่อใหม่ (สุ่มกระจาย)
งานฝั่งทีมอินฟรา เครื่องเซิร์ฟเวอร์/OS: ตรวจคิวรอเชื่อมต่อของเซิร์ฟเวอร์ล้นจาก TcpExtListenOverflows และ TcpExtListenDrops ใน nstat และคำเตือน “Possible SYN flooding” ใน log, เพิ่ม somaxconn (พร้อมกับอาร์กิวเมนต์ของ listen), ใช้ SYN cookie เครือข่าย: ผ่อนการจำกัด SYN ของไฟร์วอลล์และระบบป้องกัน DDoS
ตัวเลขที่ควรรู้ SYN ที่ส่งซ้ำครั้งแรกของ Linux (รวมถึง Android) อยู่ที่ 1 วินาที เคอร์เนลรุ่นเก่าหลังจากนั้นจะเพิ่มช่วงห่างเป็นสองเท่าและส่งซ้ำที่วินาทีที่ 1, 3, 7, 15 … ส่วนตั้งแต่ 6.5 ขึ้นไปจะส่งซ้ำห้าครั้งที่ 1, 2, 3, 4, 5 วินาที แล้วจึงเพิ่มเป็นสองเท่า (7, 11, 19 วินาที …) ตามค่า tcp_syn_linear_timeouts=4 มือถือ Android จำนวนมากยังใช้เคอร์เนลตอนวางจำหน่ายแม้จะอัปเดต OS แล้ว จึงอาจต่างกันไปตามเครื่องแม้เป็น Android เวอร์ชันเดียวกัน ไม่ว่าแบบไหน ถ้าล้มเหลวทั้งหมดจะเลิกหลังประมาณ 2 นาที Windows เริ่มเพิ่มจาก 1 วินาทีหรือ 3 วินาที แล้วแต่เวอร์ชันและการตั้งค่า และส่งซ้ำแค่ 2–4 ครั้ง จึงเลิกภายใน 20–30 วินาที (ดูค่าของ PC เครื่องนั้นได้จาก Max SYN Retransmissions ใน netsh int tcp show global)
บนกราฟ พุ่งทันทีหลังเปิดเซิร์ฟ/ปิดปรับปรุง · จำนวนครั้งที่พยายามเชื่อมต่อ, จำนวนครั้งที่คิวรอเชื่อมต่อล้น
จุดที่ต้องดู TcpExtListenOverflows และ TcpExtListenDrops ใน nstat ของเซิร์ฟเวอร์ กับคำเตือน “Possible SYN flooding on port” ใน dmesg และใช้ ss -lnt ดูว่า Recv-Q ของซ็อกเก็ตที่รอเชื่อมต่อ (จำนวนการเชื่อมต่อที่รอ accept) ชน Send-Q (ขีดจำกัด backlog) หรือไม่ ตรวจจาก capture ฝั่งเซิร์ฟเวอร์ว่า SYN มาถึงหรือไม่ และเซิร์ฟเวอร์ส่ง SYN-ACK กลับหรือไม่ สัญญาณว่าใช่ ช่วงที่การเชื่อมต่อทะลักทันทีหลังปิดปรับปรุง TcpExtListenOverflows เพิ่มขึ้นและ Recv-Q ติดเพดาน Send-Q ใน capture เห็น SYN จากไคลเอนต์เดิมมาซ้ำเป็นช่วงห่างระดับวินาที แต่เซิร์ฟเวอร์ไม่ตอบ สัญญาณว่าไม่ใช่ SYN ไม่มาถึงเซิร์ฟเวอร์และตัวนับของเซิร์ฟเวอร์ก็ไม่ขยับ: ไฟร์วอลล์หรือระบบป้องกัน DDoS ด้านหน้าทิ้งไป ให้ดูการจำกัด SYN และ log การดรอปของอุปกรณ์นั้น ถ้าเซิร์ฟเวอร์ส่ง SYN-ACK แล้วแต่ยังเชื่อมต่อช้า น่าจะเป็นแพ็กเก็ตหายในทิศทางขากลับ วิธีตรวจ ใช้เครื่องมือฝั่งอินฟรา (ไม่ต้องใช้โค้ดเกม)
แหล่งอ้างอิง 11 รายการ include/net/tcp.h Linux kernel RTO แรก TCP_TIMEOUT_INIT = 1 วินาที (ค่าเริ่มต้นตาม RFC 6298) RFC 6298: Computing TCP's Retransmission Timer IETF RTO เริ่มต้น 1 วินาที เพิ่มเป็นสองเท่าทุกครั้งที่ส่งซ้ำ IP Sysctl Linux kernel tcp_syn_retries ค่าเริ่มต้น 6, tcp_syn_linear_timeouts ค่าเริ่มต้น 4 (SYN RTO 1, 1, 1, 1, 1, 2, 4 …), ส่งซ้ำครั้งสุดท้ายที่ 67 วินาทีและเลิกที่ 131 วินาที, somaxconn ค่าเริ่มต้น 4096, tcp_syncookies ค่าเริ่มต้น 1 tcp: make the first N SYN RTO backoffs linear Linux kernel commit ที่เปลี่ยนการส่ง SYN ซ้ำช่วงแรกให้เว้นช่วงคงที่ ตั้งแต่ Linux 6.5 (ค่าเริ่มต้น 4 ตามแบบของ macOS และ iOS) Android common kernels Android (Google) รองรับ common kernel 5.10–6.18 ไปพร้อมกัน และใช้เคอร์เนลของแพลตฟอร์มก่อนหน้า (เช่น android14-6.1) กับการวางจำหน่ายหรืออัปเกรดเครื่อง Android รุ่นใหม่ได้ TcpMaxConnectRetransmissions Microsoft ค่าเริ่มต้นของ Windows รุ่นเก่า: ส่ง SYN ซ้ำ 2 ครั้ง รอครั้งแรก 3 วินาทีแล้วเพิ่มเป็นสองเท่า หลังครั้งสุดท้ายรออีกสองเท่าแล้วเลิก (3+6+12=21 วินาที) TCP/IP connectivity issues troubleshooting Microsoft จำนวนครั้งที่ส่ง SYN ซ้ำต่างกันไปตาม OS ตรวจได้จาก Max SYN Retransmissions ใน netsh int tcp show global listen(2) — Linux manual page Linux man-pages อาร์กิวเมนต์ backlog ของ listen ถูกตัดตาม somaxconn (ค่าเริ่มต้น 4096 ตั้งแต่ Linux 5.4 ก่อนหน้านั้น 128) SNMP counter Linux kernel เมื่อคิว accept เต็ม SYN จะถูกทิ้ง และ TcpExtListenOverflows กับ TcpExtListenDrops เพิ่มขึ้นพร้อมกัน, TcpExtTCPSynRetrans net/ipv4/tcp_input.c Linux kernel ข้อความ log “Possible SYN flooding on port …” net/ipv4/tcp_diag.c Linux kernel สำหรับซ็อกเก็ตที่รอเชื่อมต่อ Recv-Q ใน ss คือจำนวนการเชื่อมต่อที่รอ accept และ Send-Q คือขีดจำกัด backlog
ขั้นตอนตามสถานการณ์
แลคหลังลงแพตช์ ใช้เมื่อการแจ้งปัญหาแลคเพิ่มขึ้นตั้งแต่แพตช์หรือ deploy ครั้งใดครั้งหนึ่ง เช่น มีการแจ้งว่า “ผิดปกติตั้งแต่อัปเดตรอบนี้” เข้ามาหลายราย หรือกราฟขึ้นเป็นขั้นบันไดจากเวลาหนึ่งแล้วคงอยู่ที่ระดับนั้น
ระบุเวลาเริ่มให้แน่ชัด แล้วรวบรวมการเปลี่ยนแปลงทั้งหมดก่อนและหลังเวลานั้น : หาเวลาที่การแจ้งปัญหาเริ่มเข้ามามาก และเวลาที่กราฟขึ้นเป็นขั้นบันได แล้วจดการเปลี่ยนแปลงที่ออกไปก่อนและหลังช่วงนั้นให้ครบ ดูให้ครอบคลุมทั้งแพตช์ไคลเอนต์, การ deploy เซิร์ฟเวอร์, การเปลี่ยนคอนฟิก, การเปลี่ยนสคีมา DB (DDL) และการรีสตาร์ต, งานเครือข่ายและไฟร์วอลล์ และการเปลี่ยนอินฟรา (ประเภทอินสแตนซ์, เคอร์เนล, ไดรเวอร์) ถ้าใช้ฟีเจอร์ annotation ของเครื่องมือมอนิเตอร์ขีดเส้นแนวตั้งไว้บนทุกกราฟทุกครั้งที่ deploy ขั้นตอนนี้จะเสร็จได้เร็ว ถ้าแพตช์เกมกับงานอินฟราออกไปในรอบปิดปรับปรุงเดียวกัน ให้เก็บไว้เป็นสาเหตุที่เป็นไปได้ทั้งคู่ เรียกใครก่อน: ทั้งทีมพัฒนาเกมและทีมอินฟราที่ออกการเปลี่ยนแปลงนั้น (การ deploy และรีสตาร์ต , ประสิทธิภาพเปลี่ยนไปหลังอัปเดต OS/เคอร์เนล/ไดรเวอร์/เฟิร์มแวร์ , ล็อกจากการเปลี่ยนสคีมา (DDL) ระหว่างให้บริการ , คิวรีช้าเพราะ query plan เปลี่ยน , cold cache (หลังรีสตาร์ตใหม่ ๆ) ) แยกขอบเขต: บิลด์, อุปกรณ์, เซิร์ฟเวอร์ และพื้นที่ : ดูว่าความผิดปกติกระจุกอยู่ในมิติไหน แล้วเริ่มสงสัยตามนี้: ถ้าแย่เฉพาะผู้เล่นที่ใช้บิลด์ใหม่ คือไคลเอนต์ ถ้าแย่เฉพาะบาง OS, การ์ดจอ หรืออุปกรณ์ คือประสิทธิภาพไคลเอนต์หรือไดรเวอร์ ถ้าแย่เฉพาะบางเซิร์ฟเวอร์ แชนแนล หรือโซน คือเซิร์ฟเวอร์ ถ้าแย่เฉพาะบางประเทศหรือบาง ISP คือเส้นทางเครือข่าย ถ้าทุกคนแย่พร้อมกัน คือทรัพยากรที่ใช้ร่วมกัน (DB, โหลดบาลานเซอร์, เกตเวย์) หรือการ deploy เซิร์ฟเวอร์ที่เพิ่งออกไป ถ้า telemetry ของไคลเอนต์มีเลขบิลด์ ให้วางปิง, FPS, frame spike และจำนวนครั้งที่หลุดของบิลด์เก่ากับบิลด์ใหม่ไว้เทียบกัน ถ้าปิงเท่าเดิมแต่ FPS แย่ลงอย่างเดียว น่าจะเป็นที่ประสิทธิภาพไคลเอนต์มากกว่าเครือข่าย เรียกใครก่อน: ถ้ากระจุกตามบิลด์หรืออุปกรณ์ คือทีมพัฒนาเกม (ไคลเอนต์) ถ้ากระจุกตามเซิร์ฟเวอร์หรือแชนแนล คือทีมพัฒนาเกม (เซิร์ฟเวอร์) เมื่อเมตริกของโฮสต์ปกติ และทีมอินฟรา (เครื่องเซิร์ฟเวอร์/OS) เมื่อผิดปกติ ถ้ากระจุกตามประเทศหรือ ISP คือทีมอินฟรา (เครือข่าย) (เฟรมไทม์พุ่ง , โหลดแบบ synchronous และคอมไพล์ shader บนเมนเธรด , หน่วยความจำกราฟิก (VRAM) ไม่พอ , ไคลเอนต์แครช ) เทียบเวอร์ชันใหม่กับเวอร์ชันเก่าในช่วงเวลาเดียวกัน : ถ้าเทียบแค่ก่อนกับหลัง deploy การเปลี่ยนแปลงตามวันในสัปดาห์ ช่วงเวลา และอีเวนต์จะปนเข้ามาจนตัดสินได้ยาก ถ้าทำได้ ให้ลงเวอร์ชันใหม่บนเซิร์ฟเวอร์บางส่วน (canary) ก่อน แล้วเทียบกับเซิร์ฟเวอร์เวอร์ชันเก่าในช่วงเวลาเดียวกัน (กลุ่มควบคุม) ทั้งเวลาต่อทิก p50 และ p99, จำนวนทิกที่เกินงบ, CPU, หน่วยความจำ และอัตรา error ถ้า deploy ไปทั้งหมดแล้ว ให้เทียบกับวันเดียวกันของสัปดาห์ก่อนในช่วงเวลาเดียวกัน ถ้าดูแค่ค่าเฉลี่ยรวมของทุกเซิร์ฟเวอร์ ปัญหาในบางเซิร์ฟเวอร์หรือบางโซนจะถูกกลบ จึงต้องแยกดูตามเซิร์ฟเวอร์และโซน เรียกใครก่อน: ทีมพัฒนาเกม (เซิร์ฟเวอร์) (ทิกเกินงบเวลา , การจัดสรรหน่วยความจำพุ่ง , หน่วยความจำรั่ว , ปริมาณ broadcast พุ่ง ) เทียบ fingerprint ของทราฟฟิกก่อนและหลังแพตช์ : แม้ไม่รู้โค้ดเซิร์ฟเวอร์ ก็ตรวจได้จากค่าที่เห็นฝั่งเครือข่ายว่าแพตช์เปลี่ยนรูปแบบทราฟฟิกหรือไม่ ให้เทียบก่อนและหลังทั้งจำนวนแพ็กเก็ตต่อวินาทีต่อผู้เล่น (pps) และจำนวนไบต์, ขนาดแพ็กเก็ตเฉลี่ยและสูงสุด, จำนวนการเชื่อมต่อ และขนาด burst ขาออกที่ส่งออกไปพร้อมกันทุกทิก ถ้าแพ็กเก็ต UDP เริ่มใหญ่เกิน path MTU (ปกติ 1,500 ไบต์) จะเกิด IP fragmentation แค่ fragment เดียวหาย แพ็กเก็ตทั้งก้อนก็หาย และ NAT หรือไฟร์วอลล์บางตัวก็ทิ้ง fragment ไปเลย ผู้เล่นที่เส้นทางผ่านช่วงที่ MTU เล็ก (tunnel, VPN) จะเจอเฉพาะแพ็กเก็ตใหญ่ที่หายไป ถ้า pps เพิ่มขึ้น ให้ดูว่าชนขีดจำกัด PPS ของอินสแตนซ์บนคลาวด์ หรือขีดจำกัดการประมวลผลของไฟร์วอลล์และอุปกรณ์ป้องกัน DDoS หรือไม่ เรียกใครก่อน: ถ้า fingerprint เปลี่ยน ให้แนบหลักฐานส่งทีมพัฒนาเกม (เซิร์ฟเวอร์) ถ้า fingerprint เท่าเดิมแต่แพ็กเก็ตหายและการส่งซ้ำเพิ่มขึ้นอย่างเดียว คือทีมอินฟรา (เครือข่าย) (แพตช์ทำให้รูปแบบทราฟฟิกเปลี่ยน , IP fragmentation ของแพ็กเก็ต UDP , MTU black hole (เฉพาะแพ็กเก็ตใหญ่ที่หายซ้ำแล้วซ้ำอีก) , เกินขีดจำกัด PPS ของคลาวด์ , อุปกรณ์กลางทางเกินขีดความสามารถ (ไฟร์วอลล์/IPS/ระบบป้องกัน DDoS) , บัฟเฟอร์ตื้นล้นเพราะ burst จากฝั่งส่ง ) เทียบประเภทและจำนวนครั้งของคิวรี DB ก่อนและหลังแพตช์ : ถ้าความหน่วงของ DB สูงขึ้น ให้ดูก่อนว่าจำนวนคิวรี (QPS) สูงขึ้นด้วยหรือไม่ pg_stat_statements ของ PostgreSQL และสรุปแบบ digest ของ MySQL Performance Schema จะรวมคิวรีที่ต่างกันแค่ค่าไว้เป็นประเภทเดียว แล้วสะสมจำนวนครั้งที่รันและเวลารวมไว้ให้ เมื่อเทียบรายการคิวรีอันดับต้น ๆ ก่อนและหลังแพตช์ จะเห็นคิวรีที่เพิ่งเกิดขึ้นใหม่, คิวรีที่จำนวนครั้งเพิ่มขึ้นหลายเท่า (N+1) และคิวรีที่อ่านทั้งตารางโดยไม่ใช้อินเด็กซ์ (ใน MySQL ดูคอลัมน์ SUM_NO_INDEX_USED) เรียกใครก่อน: ถ้า QPS หรือรูปแบบคิวรีเปลี่ยน คือทีมพัฒนาเกม (เซิร์ฟเวอร์) ถ้าคิวรีเหมือนเดิมแต่ความหน่วงเพิ่มขึ้นอย่างเดียว คือทีมอินฟรา (DB: query plan, IOPS, ล็อก) (คิวรีที่ไม่มีอินเด็กซ์ , คนแห่ล็อกอินและคิวรี N+1 , คิวรีช้าเพราะ query plan เปลี่ยน , แคชสแตมปีด ) แยกชั้นด้วยเมตริกของโฮสต์และโปรเซสเซิร์ฟเวอร์ : ใช้ค่าที่เห็นจาก OS โดยไม่ต้องใช้โค้ด แยกว่าปัญหาอยู่ภายในตัวเซิร์ฟเวอร์หรือที่โฮสต์ ถ้า receive queue (Recv-Q) ของซ็อกเก็ตเซิร์ฟเวอร์สะสม แปลว่าโปรเซสเซิร์ฟเวอร์อ่านไม่ทัน (ทิกหยุดชะงัก, GC, ล็อก) ถ้าเธรดเดียวใช้ CPU 100% คือคอขวดที่เธรดเดียว ถ้าเวลาหยุดใน GC log เพิ่มขึ้น แปลว่ารูปแบบการใช้หน่วยความจำเปลี่ยนไป ดูด้วยว่า deploy ไปทั้งที่ยังตั้ง log level ไว้สูงจนการเขียน log เพิ่มขึ้นหรือไม่ ในทางกลับกัน ถ้า CPU steal, throttling หรือ NIC drop เพิ่มขึ้น ให้ดูอินฟราที่เปลี่ยนในเวลาเดียวกัน (ประเภทอินสแตนซ์, เคอร์เนล, ขีดจำกัดของคอนเทนเนอร์) เรียกใครก่อน: ถ้าเป็นสัญญาณจากภายในโปรเซส คือทีมพัฒนาเกม (เซิร์ฟเวอร์) ถ้าเป็นสัญญาณจากโฮสต์ คือทีมอินฟรา (เครื่องเซิร์ฟเวอร์/OS) (GC ของเซิร์ฟเวอร์หยุดทั้งระบบ , พื้นที่ที่รันบนเธรดเดียวโหลดเกิน (hotspot) , การเขียน log แบบ synchronous , CPU throttling ของคอนเทนเนอร์ (CFS quota) , CPU steal (VM) , ประสิทธิภาพเปลี่ยนไปหลังอัปเดต OS/เคอร์เนล/ไดรเวอร์/เฟิร์มแวร์ ) ย้อนกลับเพื่อยืนยัน แล้วบันทึกผลไว้ : ย้อนการเปลี่ยนแปลงที่น่าสงสัยที่สุดเฉพาะบางเซิร์ฟเวอร์หรือบางผู้เล่น (โรลแบ็ค, ปิด feature flag) หรือคืนคอนฟิกเป็นค่าเดิม แล้วดูว่าอาการหายไปด้วยหรือไม่ ถ้าดีขึ้นเฉพาะฝั่งที่ย้อนกลับ ก็ยืนยันสาเหตุได้ การย้อนกลับเองก็อาจทำให้ช้าไปชั่วครู่จากการรีสตาร์ตและ cold cache ถ้าไม่เร่งด่วนให้ทำในช่วงที่คนน้อย บันทึกผลพร้อม ID สาเหตุลงในบันทึกเหตุขัดข้อง และย้ายขีดจำกัดของขนาดแพ็กเก็ต, จำนวนคิวรี และเวลาต่อทิก ไปเป็นรายการตรวจก่อน deploy ของแพตช์ถัดไป เรียกใครก่อน: ทีมที่ออกการเปลี่ยนแปลงนั้น (การ deploy และรีสตาร์ต , cold cache (หลังรีสตาร์ตใหม่ ๆ) )
การขยายบริการไปประเทศหรือภูมิภาคใหม่ ใช้เมื่อเปิดให้บริการในประเทศใหม่ หรือเพิ่มรีเจียนหรือดาต้าเซ็นเตอร์ใหม่ ใช้ได้ทั้งตอนตรวจก่อนเปิด และตอนแยกแยะการแจ้งปัญหาแบบ “ในเกาหลีปกติดี มีแต่ผู้เล่นประเทศใหม่ที่แลค”
วัดคุณภาพเส้นทางแยกตาม ISP ท้องถิ่นก่อนเปิดบริการ : วัดการกระจายของเวลาไปกลับ (RTT), จิตเตอร์ และแพ็กเก็ตหาย จาก ISP หลัก (ASN) แต่ละรายของประเทศเป้าหมายไปยังที่ตั้งเซิร์ฟเวอร์เกมที่เป็นตัวเลือก ค่าเฉลี่ยตัวเดียวจะกลบความต่างระหว่าง ISP จึงต้องดูค่ามัธยฐานและเปอร์เซ็นไทล์ที่ 95 แยกตาม ISP และแยกช่วงพีคหัวค่ำกับช่วงเช้ามืด เครือข่ายวัดผลสาธารณะ RIPE Atlas ให้เลือกประเทศหรือ ASN แล้วส่ง ping และ traceroute จาก probe ทั่วโลกได้ หรือจะเปิด VM ชั่วคราวในรีเจียนที่เป็นตัวเลือกเพื่อวัดก็ได้ อุปกรณ์ระหว่างทางบางตัวจำกัดการตอบ ICMP ถ้าเป็นไปได้จึงควรวัดด้วยโปรโตคอลและพอร์ตเดียวกับเกมด้วย ถ้ามีแต่ ISP บางรายที่อ้อมผ่านเมืองที่อยู่ไกลผิดปกติ คือปัญหา peering หรือเส้นทาง ISP เลือกเส้นทางโดยดูต้นทุนก่อนความหน่วง ปลายทางที่อยู่ใกล้จึงอาจวิ่งอ้อมไปไกลได้ เรียกใครก่อน: ทีมอินฟรา (เครือข่าย) ถ้าเส้นทางเป็นเรื่องฝั่ง ISP คือภายนอก (ISP/IX) (ความหน่วงในการแพร่สัญญาณ (ระยะทางจริง) , เส้นทางวิ่งอ้อม , จุด peering แออัดช่วงพีค , เคเบิลใต้น้ำ/วงจรต่างประเทศขัดข้อง ) เทียบค่าที่วัดได้กับขีดจำกัดที่การออกแบบเกมรับได้ : นำ RTT และจิตเตอร์ที่วัดได้ไปเทียบกับช่วงเวลาตัดสินของเกม (เวลาตอบสนองสำหรับการหลบหรือการแพร์รี), ขีดจำกัดของ lag compensation, ความยาวของ interpolation buffer และขนาดบัฟเฟอร์อินพุต ตัวอย่างเช่น ถ้าช่วงเวลาตัดสินการแพร์รีคือ 0.2 วินาที ผู้เล่นที่ใช้ ISP ซึ่งดีเลย์ไปกลับรวมกับ interpolation buffer นานกว่านั้น จะช้าเกินไปแม้กดทันเวลา ถ้าขยาย lag compensation เพื่อชดเชย คราวนี้ฝั่งที่โดนโจมตีจะแจ้งเข้ามามากขึ้นว่า “หลบหลังกำแพงแล้วยังโดน” ถ้ามี ISP จำนวนมากที่เกินขีดจำกัด ทีมอินฟราควรพิจารณาวางรีเจียนหรือ edge PoP ให้ใกล้ขึ้น ส่วนทีมพัฒนาเกมควรทบทวนค่าการตัดสินผล, interpolation และ lag compensation บท “รูปแบบการซิงก์” ในคู่มือนี้ใช้เป็นตารางอ้างอิงได้ เรียกใครก่อน: ทีมพัฒนาเกม (เซิร์ฟเวอร์/ไคลเอนต์: ขีดจำกัดของการออกแบบ), ทีมอินฟรา (เครือข่าย: ที่ตั้งรีเจียนและ PoP) (ช่วงเวลาตัดสินสั้นจนปิงกินหมด , การตัดสินผลที่ไม่มี lag compensation , lag compensation มากเกินไป , ไม่มี interpolation buffer หรือสั้นเกินไป ) ตรวจ MTU และดูว่า UDP ผ่านได้หรือไม่ : ตรวจว่าแพ็กเก็ตที่ใหญ่ที่สุดของเกมผ่านเครือข่ายท้องถิ่นไปได้ครบทั้งก้อนหรือไม่ ส่งปิงที่ตั้งแฟล็ก Don't Fragment (DF) ไปหลายขนาดเพื่อวัด path MTU และดูว่ามีช่วงที่เล็กกว่า 1,500 ไบต์ เช่น PPPoE, tunnel หรือเครือข่ายมือถือหรือไม่ มาตรฐานสำหรับการส่งแบบ datagram อย่าง UDP (RFC 8899) แนะนำขนาดพื้นฐานที่ผ่านเส้นทางส่วนใหญ่ได้บน IPv4 ไว้ที่ 1,200 ไบต์ ถ้าแพ็กเก็ตใหญ่สุดของเกมเกินค่านี้ ให้ตกลงกับทีมพัฒนาเกมว่าจะลดขนาดหรือแบ่งส่ง ตรวจด้วยว่า Wi-Fi สาธารณะ เครือข่ายบริษัท หรือ ISP บางรายบล็อก UDP หรือพอร์ตเกม หรือจำกัดความเร็วหรือไม่ และดูว่ามีเส้นทางสำรองไว้ใช้ตอนโดนบล็อก (TCP, พอร์ต 443) หรือไม่ เรียกใครก่อน: ทีมอินฟรา (เครือข่าย) และทีมพัฒนาเกม (เซิร์ฟเวอร์: ขนาดแพ็กเก็ต) (MTU ไม่ตรงกัน (เฉพาะแพ็กเก็ตใหญ่ที่หาย) , MTU black hole (เฉพาะแพ็กเก็ตใหญ่ที่หายซ้ำแล้วซ้ำอีก) , IP fragmentation ของแพ็กเก็ต UDP , การจำกัด UDP และตรวจแพ็กเก็ตระดับประเทศหรือ ISP , ข้อจำกัดของ Wi-Fi สาธารณะและเครือข่ายบริษัท , ISP จำกัดความเร็วและจัดการทราฟฟิก ) วัด idle timeout ของ NAT/CGNAT แล้วปรับช่วงห่างของ heartbeat ให้เข้ากัน : วัดว่าเราเตอร์ตามบ้านและเครือข่ายมือถือ (CGNAT) ในประเทศนั้นลบ mapping ของการเชื่อมต่อ UDP ที่ idle ภายในเวลาเท่าไร ในการทดสอบแต่ละรอบ ให้อุปกรณ์ทดสอบส่งแพ็กเก็ตหนึ่งตัวไปยังเซิร์ฟเวอร์เพื่อสร้าง mapping จากนั้นอุปกรณ์ไม่ส่งอะไรเลย แล้วให้เซิร์ฟเวอร์ส่งแพ็กเก็ตกลับไปหาอุปกรณ์เมื่อครบเวลาที่กำหนดไว้ (30 วินาที, 60 วินาที, 120 วินาที …) เวลาที่อุปกรณ์เริ่มไม่ได้รับแพ็กเก็ตนั้นคือ idle timeout ของเครือข่ายนั้น มาตรฐาน (RFC 4787) กำหนดว่า UDP mapping ต้องไม่หมดอายุก่อน 2 นาที และแนะนำค่าเริ่มต้นตั้งแต่ 5 นาทีขึ้นไป แต่ค่าจริงต่างกันมากตามอุปกรณ์ และบางอุปกรณ์ลบเร็วกว่านั้น mapping จะต่ออายุได้แน่นอนก็ต่อเมื่อมีแพ็กเก็ตขาออกจากอุปกรณ์เท่านั้น ไคลเอนต์จึงต้องเป็นฝ่ายส่ง heartbeat และต้องดูว่าช่วงห่างนั้นไม่เกินครึ่งหนึ่งของค่าที่สั้นที่สุดในบรรดาค่าที่วัดได้ และ idle timeout ของโหลดบาลานเซอร์และ security group บนคลาวด์ เรียกใครก่อน: ทีมพัฒนาเกม (ไคลเอนต์: ช่วงห่างของ heartbeat, เซิร์ฟเวอร์: ค่าไทม์เอาต์), ทีมอินฟรา (คอนฟิกโหลดบาลานเซอร์และ security group) (NAT mapping หมดอายุ , IP ที่ ISP ให้ใช้ร่วมกัน (CGNAT) , mapping ของ NAT/โหลดบาลานเซอร์หมดอายุกลางการเชื่อมต่อ , idle timeout ของโหลดบาลานเซอร์ , connection tracking ของ security group บนคลาวด์หมดอายุ ) ตรวจบริการภายนอกและอุปกรณ์ความปลอดภัยที่ทราฟฟิกในประเทศนั้นต้องผ่าน : ตรวจว่าการล็อกอินผ่านแพลตฟอร์มท้องถิ่น, การชำระเงิน และการยืนยันตัวตนตอบกลับด้วยความเร็วปกติหรือไม่, DNS ท้องถิ่นแปลงที่อยู่ของเซิร์ฟเวอร์ล็อกอินและเซิร์ฟเวอร์แพตช์ได้ถูกต้องหรือไม่ และ CDN ส่งแพตช์จากจุดให้บริการที่อยู่ใกล้ประเทศนั้นหรือไม่ ดูว่าช่วง IP ของประเทศใหม่ไม่ติดกฎบล็อกตามประเทศหรือการจำกัดอัตราของระบบป้องกัน DDoS และไฟร์วอลล์ โดยเฉพาะช่วง IP ของ CGNAT ที่ผู้ใช้บริการหลายรายใช้ IP เดียวร่วมกัน ต้องไม่ถูกบล็อกไปทั้งก้อน เรียกใครก่อน: ทีมอินฟรา (อุปกรณ์ความปลอดภัย, DNS, CDN), ภายนอก (แพลตฟอร์ม, ผู้ให้บริการชำระเงิน, ISP) (การพึ่งพาเซอร์วิสภายนอก , DNS ขัดข้อง/ช้า , การอ้อมผ่านระบบป้องกัน DDoS และ false positive , IP ที่ ISP ให้ใช้ร่วมกัน (CGNAT) ) หลังเปิดบริการ ให้แยกดูตามประเทศและ ASN : ใส่ประเทศและ ASN ให้ IP ของไคลเอนต์ใน log การเชื่อมต่อและ log ของโหลดบาลานเซอร์ แล้วดู RTT, การส่งซ้ำ, จำนวนครั้งที่หลุด และเหตุผลที่หลุด (heartbeat ไทม์เอาต์, RST, เซิร์ฟเวอร์เตะออก) แยกตามประเทศและ ISP ฐานข้อมูลฟรีอย่าง MaxMind GeoLite ASN แปลง IP เป็น ASN และชื่อองค์กรได้ และให้เก็บ IP แบบย่อเป็นระดับ /24 หรือ ASN ตามกฎข้อมูลส่วนบุคคลของประเทศนั้น ถ้ากระจุกอยู่ที่ ASN เดียว ให้ดูเส้นทางของ ISP นั้น (ทีมอินฟรา, ภายนอก) ถ้าแย่ทั้งประเทศใหม่ ให้ดูระยะทางและขีดจำกัดของการออกแบบ (ทีมอินฟรา, ทีมพัฒนาเกม) ถ้าแย่เฉพาะช่วงหัวค่ำ ให้ดู peering ที่แออัดก่อน ถ้าผู้เล่นบางส่วนปิงสูงตลอด ให้ดูร่วมกับทีมพัฒนาเกม (เซิร์ฟเวอร์) ว่าถูกจัดไปรีเจียนที่ไกลเพราะ GeoIP ผิด, VPN หรือการจัดรีเจียนตามหัวปาร์ตี้หรือไม่ ถ้า synthetic monitoring ปกติแต่ค่าที่ผู้เล่นจริงเจอแย่ แปลว่าเป็นที่สภาพแวดล้อมของผู้เล่นหรือฝั่งไคลเอนต์ (จุด peering แออัดช่วงพีค , เส้นทางวิ่งอ้อม , คิวคอขวดล้น (แพ็กเก็ตหายจากความแออัด) , false positive ของการตรวจสอบที่กระจุกกับผู้ใช้บาง ISP , matchmaking/การจัดรีเจียนผิดพลาด ) ตรวจผลกระทบที่ผู้เล่นจากพื้นที่ไกลมีต่อผู้เล่นคนอื่น : เมื่อผู้เล่นที่เชื่อมต่อจากที่ไกลมีมากขึ้น ผลกระทบไม่ได้หยุดอยู่แค่หน้าจอของคนนั้น อินพุตของคนที่ช้ามาถึงเป็นก้อน ตัวละครของคนนั้นจึงขยับแบบกรอเร็วบนหน้าจอคนอื่น และติดการตรวจความเร็วหรือคูลดาวน์ของเซิร์ฟเวอร์ จนเกิดอาการดีดกลับหรือสกิลถูกปฏิเสธ ในกิมมิคที่ต้องเล่นเป็นปาร์ตี้ การตอบสนองที่ช้าของคนเดียวทำให้ทั้งปาร์ตี้ล้มเหลว และในแบบ lockstep ทุกคนต้องรอคนที่ช้าที่สุด หลังเปิดประเทศใหม่ ให้ดูว่าผู้เล่นเดิมแจ้งปัญหาแบบ “เห็นตัวละครบางตัวผิดปกติ” มากขึ้นหรือไม่ แล้วตกลงกับทีมพัฒนาเกมเรื่องบัฟเฟอร์อินพุต, ค่าที่ยอมให้คลาดเคลื่อนในการตรวจ และการแยกพื้นที่ในการจับคู่ เรียกใครก่อน: ทีมพัฒนาเกม (เซิร์ฟเวอร์) (คนเน็ตช้าขยับแบบกรอเร็วบนจอคนอื่น , false positive ของการตรวจสอบที่กระจุกกับผู้ใช้บาง ISP , เพื่อนในปาร์ตี้ที่ช้าหนึ่งคนกับกิมมิกบอส , lockstep ต้องรอผู้เล่นที่ช้าที่สุด )
กรณีเหตุขัดข้องจริง
คัดเฉพาะรายงาน postmortem ที่บริษัทเกมและบริษัทอินฟราเผยแพร่เอง
CCP Games 2014: เซิร์ฟเวอร์ EVE Online โหลดเกินในศึกกองยานขนาดใหญ่ที่ HED-GP เกิดอะไรขึ้น ในศึกกองยานขนาดใหญ่ที่ระบบดาว HED-GP ซึ่งบทวิเคราะห์ย้อนหลังเมื่อมกราคม 2014 กล่าวถึง เซิร์ฟเวอร์โหลดเกินอย่างหนัก Time Dilation (ฟีเจอร์ที่ทำให้เวลาในเกมช้าลงเมื่อโหลดเกิน) ลดลงไปแตะขีดต่ำสุดที่ 10% จนทั้งสนามรบกลายเป็นสโลว์โมชั่น แต่หลังจากนั้นโหลดก็ยังสะสมต่อไป ความล่าช้าของงานที่ประมวลผลการหยุดและการทำงานซ้ำของโมดูล (Dogma Lateness) สูงสุดถึง 193 วินาทีในเวลาเกม หรือประมาณ 32 นาทีในเวลาจริง ส่วนศึก 6VDT เมื่อกรกฎาคม 2013 ซึ่งมีขนาดใกล้เคียงกัน สูงสุดอยู่ที่ 42 วินาที (เวลาจริงประมาณ 7 นาที) สาเหตุ CCP ออกตัวไว้ก่อนว่ายังไม่แน่ใจ เพราะเครื่องมือวิเคราะห์ประสิทธิภาพก็เพิ่มโหลดในตัวเอง จึงไม่ได้รันในสถานการณ์แบบนี้ แล้วชี้สาเหตุที่น่าจะเป็นไว้สองอย่าง อย่างแรกคือโหลดที่ประมวลผลไม่ทันสะสมต่อเนื่องเมื่อการรบยืดเยื้อ อย่างที่สองคือการใช้โดรนที่เพิ่มขึ้น จำนวนโดรนที่ถูกปล่อยออกมาระหว่างการรบ (ไม่นับซ้ำ) อยู่ที่ 21,123 ลำใน 6VDT และ 38,852 ลำใน HED-GP มากกว่ากัน 84% การส่งข้อมูลที่ต้องแจ้งการกระทำของคนหนึ่งให้ทุกคนที่มองเห็นรู้ จะเพิ่มขึ้นตามกำลังสองของจำนวนคน (O(n²)) และโดรนสร้างข้อความต่อการโจมตีหนึ่งครั้งมากกว่า นอกจากนี้โค้ดที่โดรนใช้เลือกเป้าหมายก็มักไล่ดูเป้าหมายที่โจมตีได้ทั้งหมดในสนามรบเดียวกัน ต้นทุนจึงเพิ่มขึ้นเกือบเป็น n² บทเรียน เมื่อปริมาณงานในพื้นที่เดียวที่คนแห่มารวมกันเกินขีดจำกัด ทั้งพื้นที่นั้นจะเป็นสโลว์โมชั่น และยิ่งการรบยืดเยื้อ งานที่ประมวลผลไม่ทันก็ยิ่งสะสมจนอินพุตดีเลย์มากขึ้น สัญญาณที่ใช้ยืนยันคือเวลาต่อทิก, ปริมาณงานที่กองรอ, จำนวนผู้เล่น และจำนวนเอนทิตีของเซิร์ฟเวอร์ (โหนด) ที่ดูแลพื้นที่นั้น โดยมีจุดสังเกตคือพื้นที่อื่นยังปกติ ผู้รับผิดชอบหลักคือทีมพัฒนาเกม (เซิร์ฟเวอร์) จุดที่ต้องแก้คือขอบเขตของผู้รับที่ต้องแจ้งการกระทำหนึ่งครั้ง และต้นทุนการค้นหาเป้าหมายของ AI การออกแบบที่ทำให้เวลาในเกมช้าลงกำจัดการโหลดเกินไม่ได้ แต่ทำให้ทุกคนช้าลงในอัตราเดียวกัน จึงป้องกันไม่ให้การกระทำบางอย่างถูกเลื่อนออกไปไม่รู้จบ สาเหตุที่เกี่ยวข้อง ปริมาณ broadcast พุ่ง , ทิกเกินงบเวลา , ข้อความสะสมในคิว , พื้นที่ที่รันบนเธรดเดียวโหลดเกิน (hotspot) ต้นฉบับ CCP Games
Riot Games 2015: ทราฟฟิก League of Legends ที่วิ่งอ้อมไปไกล และ Riot Direct เกิดอะไรขึ้น บทความเทคนิคที่ Riot Games อธิบายว่าทำไมอินเทอร์เน็ตจึงไม่เหมาะกับเกมแบบเรียลไทม์ ทราฟฟิกจริงที่ผู้เล่น League of Legends แจ้งเข้ามาควรวิ่งจากซานฟรานซิสโกไปพอร์ตแลนด์โดยตรง แต่อ้อมผ่านลอสแอนเจลิส, เดนเวอร์ และซีแอตเทิล จึงใช้เวลา 70 ms ทั้งที่ถ้าไปตรงใช้แค่ 14 ms Riot อธิบายว่าเมื่อเราเตอร์ล้นจนแพ็กเก็ตถูกทิ้ง จะเห็นแชมเปี้ยนตัวอื่นกระโดดไปมาบนหน้าจอ และ projectile ดูเหมือนวาร์ป สาเหตุ Riot ชี้ว่าต้นเหตุคือเส้นทางและเราเตอร์ ผู้ให้บริการแบ็กโบนและ ISP ให้ความสำคัญกับต้นทุนก่อนความหน่วง จึงส่งทราฟฟิกตามเส้นทางที่ถูกที่สุด และเมื่อเส้นทางที่ BGP เลือกอ้อมไปไกล จำนวนเราเตอร์ที่ต้องผ่านก็เพิ่มขึ้น เราเตอร์รับภาระประมวลผลตามจำนวนแพ็กเก็ตโดยไม่ขึ้นกับขนาด แพ็กเก็ตเกมมีขนาดราว 55 ไบต์ ถ้าปริมาณข้อมูลเท่ากัน จำนวนแพ็กเก็ตจะมากกว่าแพ็กเก็ต 1,500 ไบต์ถึง 27 เท่า และเติมบัฟเฟอร์ขาเข้าของเราเตอร์ได้เร็วขึ้นตามไปด้วย Riot อธิบายว่าเราเตอร์จำนวนมากเลือกทิ้งแพ็กเก็ต UDP ก่อนเมื่อโหลดเกิน ทางแก้ของ Riot คือสร้างเครือข่ายของตัวเองชื่อ Riot Direct โดยวางเราเตอร์ไว้ที่ศูนย์กลางอินเทอร์เน็ตขนาดใหญ่ 10 แห่งในสหรัฐฯ และเชื่อมต่อตรง (peering) กับ ISP ให้ได้มากที่สุด ตามบทความตอนที่ 2 สัดส่วนผู้เล่นที่เล่นด้วยปิงต่ำกว่า 80 ms เพิ่มจาก 31% เป็น 50% ในเวลา 9 เดือนเศษ และหลังย้ายเซิร์ฟเวอร์เกมไปชิคาโก ก็กลายเป็น 80% ภายในคืนเดียว บทเรียน ถ้าในประเทศเดียวกัน มีแต่ผู้เล่นที่ใช้ ISP บางรายที่ปิงสูงผิดปกติ ให้สงสัยเส้นทาง สัญญาณที่ใช้ยืนยันคือการกระจายของ RTT แยกตาม ISP (ASN) และเมืองที่ทราฟฟิกผ่านซึ่งเห็นใน traceroute ผู้รับผิดชอบหลักคือทีมอินฟรา (เครือข่าย) แก้ด้วยการทำ peering ตรงกับ ISP, การเชื่อมต่อ IX และการเลือกที่ตั้งเซิร์ฟเวอร์ ส่วนนโยบายเส้นทางฝั่ง ISP ต้องประสานกับภายนอก (ISP) กรณีนี้ยังแสดงให้เห็นว่าแค่ย้ายเซิร์ฟเวอร์ไปใกล้จุดศูนย์กลางของกลุ่มผู้เล่นก็ได้ผลมาก สาเหตุที่เกี่ยวข้อง เส้นทางวิ่งอ้อม , ความหน่วงในการแพร่สัญญาณ (ระยะทางจริง) , คิวคอขวดล้น (แพ็กเก็ตหายจากความแออัด) ต้นฉบับ Riot Games
Riot Games 2020: โฮสต์ edge ของเซิร์ฟเวอร์ League of Legends ยุโรปและบราซิลโหลดเกิน เกิดอะไรขึ้น ปลายเดือนกุมภาพันธ์ 2020 เซิร์ฟเวอร์ EUW, EUNE และ BR ของ League of Legends ขัดข้องหลายครั้ง จำนวนเกมที่เริ่มใหม่ลดลงอย่างมาก บริการ backend อย่างระบบจับคู่และเซิร์ฟเวอร์เกมมีสถานะปกติทั้งหมด แต่แทบไม่มีทราฟฟิกเข้ามา Riot เลื่อนกำหนดการโหมดทัวร์นาเมนต์ (Clash) ออกไปหนึ่งสัปดาห์ เพื่อไม่ให้เปิดบนคลัสเตอร์ที่อาจไม่เสถียร บทวิเคราะห์ย้อนหลังไม่ได้ระบุว่าเหตุขัดข้องแต่ละครั้งกินเวลานานเท่าไร สาเหตุ มีสามเรื่องเกิดซ้อนกัน คำขอที่ส่งไปยังบริการหนึ่งถูกสร้างผิดรูปแบบ ในบางกรณีจึงล้มเหลวและถูกลองใหม่ไม่หยุด จนปริมาณคำขอพุ่งสูง ปัญหาความเข้ากันได้ที่รู้กันอยู่แล้วระหว่างระบบคอนเทนเนอร์กับเวอร์ชัน OS ทำให้หน่วยความจำภายใน OS รั่วอยู่ การอัปเกรดเสร็จแค่ประมาณ 60% ของสภาพแวดล้อมคอนเทนเนอร์ทั้งหมดของ Riot และคลัสเตอร์ยุโรปกับละตินอเมริกายังอยู่ระหว่างดำเนินการ คอนเทนเนอร์ edge ที่รับทราฟฟิกจากอินเทอร์เน็ต กรองแล้วส่งต่อไปยัง backend ถูกจัดวางให้อยู่แยกกันภายในชาร์ด (กลุ่มเซิร์ฟเวอร์) เดียวกัน แต่ไม่มีกลไกกันไว้ระหว่างต่างชาร์ด ทุกครั้งที่ขัดข้อง คอนเทนเนอร์ edge ของอย่างน้อยสามชาร์ดจึงไปกระจุกอยู่บนโฮสต์เครื่องเดียว การลองใหม่ที่พุ่งสูงมาซ้อนทับที่โฮสต์นั้น และหน่วยความจำรั่วก็ทำให้โฮสต์นั้นหยุดทำงาน บทเรียน ถ้าบริการ backend ทุกตัวตอบว่า “ปกติดี แต่ไม่มีทราฟฟิกเข้ามา” ให้ดูส่วนที่อยู่ด้านหน้า (edge, เกตเวย์, โหลดบาลานเซอร์) สัญญาณที่ใช้ยืนยันคือจำนวนการเชื่อมต่อขาเข้าแยกตามโฮสต์ว่ากระจุกอยู่ที่บางเครื่องหรือไม่ และอัตราความล้มเหลวและการลองใหม่ของคำขอบางประเภท ผู้รับผิดชอบหลักคือทีมพัฒนาเกม (เซิร์ฟเวอร์: คำขอที่ผิดรูปแบบและวิธีลองใหม่) ส่วนกฎการจัดวางคอนเทนเนอร์, การอัปเกรด OS และ alert เมื่อโหลดกระจุก เป็นหน้าที่ของทีมอินฟรา (เครื่องเซิร์ฟเวอร์/OS) Riot แก้โค้ดของคำขอ ปรับไม่ให้การลองใหม่พุ่งขึ้นฉับพลัน และตั้ง alert เมื่อโหลดกระจุกไว้จนกว่าจะพัฒนาการกระจายข้ามชาร์ดเสร็จ สาเหตุที่เกี่ยวข้อง การผ่านเกตเวย์/พร็อกซี , ความล้มเหลวแบบลูกโซ่ ต้นฉบับ Riot Games
Riot Games 2021: League of Legends EUW ขัดข้อง 5 ชั่วโมง: DB เสริมตัวเดียวทำให้ทั้งเซิร์ฟเวอร์หยุด เกิดอะไรขึ้น วันที่ 22 มกราคม 2021 เซิร์ฟเวอร์ EUW ของ League of Legends ทำงานผิดปกตินานกว่า 5 ชั่วโมงเล็กน้อย เมตริกจำนวนผู้เล่นที่ล็อกอินอยู่และจำนวนผู้เล่นที่อยู่ในเกมขาดหายไปพร้อมกัน และในช่วงระหว่างการรีสตาร์ตสองครั้ง แม้จำนวนคนล็อกอินจะเพิ่มขึ้น แต่แทบไม่มีเกมไหนเริ่มได้เลย สาเหตุ เซิร์ฟเวอร์หลักของ DB ที่ดูแลฟีเจอร์ที่ไม่สำคัญเกิดฮาร์ดแวร์เสีย และ DB นั้นไม่ได้ตั้งค่า failover อัตโนมัติไปยังเซิร์ฟเวอร์สำรอง แม้ connection pool จะแยกกันตาม DB แต่ทุก pool ใช้ thread pool เดียวกัน งานที่ส่งไปยัง DB ที่เสียไม่จบและถือครองเธรดไว้ จนเธรดที่ทั้งระบบต้องใช้หมด ท่ามกลาง alert ที่ถาโถมเข้ามา ทีมสงสัยการโจมตีเครือข่ายแบบมุ่งร้ายที่เพิ่งเจอเมื่อไม่นานมานี้และงานฮาร์ดแวร์ในภูมิภาคอื่นก่อน กว่าจะเห็น alert ของ DB ที่เสียก็ผ่านไปราว 1 ชั่วโมง ระบบทั้งหมดรันอยู่ใน JVM เดียว เมื่อ GC หยุดโปรเซสครั้งละหลายวินาทีท่ามกลางโหลดจากการเชื่อมต่อใหม่หลังรีสตาร์ต การเก็บเมตริกก็ขาดช่วงไปมาก คิวล็อกอินก็ไม่ได้จำกัดตามค่าที่ตั้งไว้ คนจึงไหลเข้ามาไม่สม่ำเสมอ บทเรียน แม้แต่ DB เสริมตัวเดียวที่คิดว่าไม่สำคัญ ก็ทำให้ทั้งระบบหยุดได้ผ่านทรัพยากรที่ใช้ร่วมกันอย่าง thread pool สัญญาณที่ใช้ยืนยันคือจำนวนคำขอที่รออยู่แยกตาม DB, อัตราการใช้งาน thread pool และสัดส่วนจำนวนเกมที่เริ่มได้ซึ่งต่ำเกินไปเมื่อเทียบกับจำนวนการล็อกอิน ผู้รับผิดชอบคือทีมพัฒนาเกม (เซิร์ฟเวอร์: แยก thread pool และตั้งไทม์เอาต์) และทีมอินฟรา (DB: failover อัตโนมัติ) เมื่อ alert ถาโถมเข้ามา มักสงสัยปัญหาที่เพิ่งเจอ (เช่น การโจมตี) ก่อน จึงควรตัดทีละอย่างตามลำดับการชี้สาเหตุ (ขอบเขต → ช่วงเวลา → ชั้น) หลังรีสตาร์ตให้ดูด้วยว่าคิวล็อกอินจำกัดคนที่เข้ามาตามค่าที่ตั้งไว้หรือไม่ สาเหตุที่เกี่ยวข้อง thread pool หมด , failover ของ DB , ความล้มเหลวแบบลูกโซ่ , GC ของเซิร์ฟเวอร์หยุดทั้งระบบ ต้นฉบับ Riot Games
Roblox 2021: Roblox ล่ม 73 ชั่วโมง: การแย่งทรัพยากรในคลัสเตอร์ service discovery (Consul) เกิดอะไรขึ้น เหตุเริ่มในช่วงบ่ายวันที่ 28 ตุลาคม 2021 (เวลาแปซิฟิก) จาก CPU โหลดสูงบนเซิร์ฟเวอร์ Consul เครื่องหนึ่ง เวลา 16:35 จำนวนผู้เล่นที่ออนไลน์อยู่ลดลงเหลือครึ่งหนึ่งของปกติ แล้วบริการทั้งหมดก็หยุด ผู้เล่นทุกคนกลับเข้ามาได้อีกครั้งก็ต่อเมื่อ 16:45 วันที่ 31 ตุลาคม รวมเวลา 73 ชั่วโมงนับจากเริ่มเกิดเหตุ Roblox ระบุว่ามีผู้ใช้งาน 50 ล้านคนทุกวัน สาเหตุ Roblox ใช้ HashiCorp Consul ทำ service discovery (ให้บริการต่าง ๆ หาที่อยู่ของกันและกัน), health check และ KV store โดยคลัสเตอร์ Consul ชุดเดียวรับหลายเวิร์กโหลดร่วมกัน ต้นเหตุมีสองอย่าง อย่างแรก ฟีเจอร์ streaming ตัวใหม่ของ Consul ที่ทยอยขยายการใช้งานมาหลายเดือน ถูกเปิดใช้กับบริการ routing ทราฟฟิกด้วยในวันก่อนเกิดเหตุ พร้อมเพิ่มจำนวนโหนดของบริการนั้นอีก 50% ภายใต้โหลดที่ทั้งอ่านและเขียนสูงมาก ฟีเจอร์นี้ทำให้เกิดการแย่งทรัพยากรที่ใช้ร่วมกันตัวหนึ่ง (Go channel) และเซิร์ฟเวอร์แบบ dual socket (NUMA) ที่มีคอร์มากกว่าซึ่งเปลี่ยนเข้าไประหว่างเกิดเหตุ ยิ่งทำให้การแย่งรุนแรงขึ้น อย่างที่สอง การจัดการรายการหน้าว่าง (freelist) ของ BoltDB ที่ Consul ใช้เก็บ Raft log ช้าลงอย่างผิดปกติ ทุกครั้งที่เพิ่มข้อมูลไม่เกิน 16 kB จะเขียนลงดิสก์ 7.8 MB ค่ามัธยฐานของความหน่วงในการเขียน KV ซึ่งปกติต่ำกว่า 300 ms กลายเป็น 2 วินาที และบนเซิร์ฟเวอร์ leader ที่ช้ายังพบ zero window ที่บัฟเฟอร์ TCP เต็มด้วย ระบบ telemetry พึ่ง Consul อยู่ เมตริกที่ต้องใช้หาสาเหตุจึงหายไปด้วย บทเรียน เมื่อระบบพื้นฐานที่หลายบริการพึ่งพาร่วมกัน (service discovery, ที่เก็บคอนฟิก, ระบบยืนยันตัวตน) ช้าลง ทุกฟีเจอร์จะหยุดพร้อมกัน สัญญาณที่ใช้ยืนยันคือความหน่วงในการเขียน, การเปลี่ยน leader และ CPU ของระบบนั้น รวมถึงการเปลี่ยนคอนฟิกก่อนเกิดเหตุ ผู้รับผิดชอบมีทั้งทีมพัฒนาเกม (เซิร์ฟเวอร์) และทีมอินฟรา (เครื่องเซิร์ฟเวอร์/OS) ต้องแยกระบบมอนิเตอร์ไม่ให้พึ่งระบบที่ถูกเฝ้าดู จึงจะยังเห็นเมตริกได้ระหว่างเกิดเหตุ ตอนกู้คืน แคชยังว่างอยู่ ถ้ารับคนเข้ามาพร้อมกันทั้งหมดระบบอาจล่มซ้ำ Roblox จึงใช้ DNS คุมสัดส่วนผู้เล่นที่ให้เข้ามา และเพิ่มทีละประมาณ 10% สาเหตุที่เกี่ยวข้อง ความล้มเหลวแบบลูกโซ่ , การแย่งล็อก , zero window (การหยุดที่ดูเหมือนการส่งซ้ำ) , cold cache (หลังรีสตาร์ตใหม่ ๆ) ต้นฉบับ Roblox
Square Enix 2021: FINAL FANTASY XIV แออัดช่วงเปิดตัวภาคเสริม และ error ในคิวล็อกอิน เกิดอะไรขึ้น ตั้งแต่ช่วง early access ของภาคเสริม Endwalker ในเดือนธันวาคม 2021 ทุกเวิลด์แออัดอย่างหนัก คิวล็อกอินยาวขึ้น และมักเกิด Error 2002 ตอนล็อกอินจากหน้าเลือกตัวละครหรือระหว่างรอในคิว นอกจากนี้ยังมีบางเวิลด์และบางโซนล่ม (Error 3001) และคิวไทม์เอาต์ (Error 4004) ด้วย ณ วันที่ประกาศ 11 ธันวาคม ซึ่งเป็นวันที่ 8 ของ early access ความแออัดก็ยังไม่หมดไป สาเหตุ Error 2002 เกิดได้สองกรณี กรณีแรกคือเมื่อจำนวนคนรอในแต่ละ logical data center เกิน 17,000 คน ซึ่งเป็นเพดานที่ตั้งไว้เพื่อกันไม่ให้คิวยาวจนเซิร์ฟเวอร์ล็อกอินล่ม ในกรณีนี้ไคลเอนต์จะถูกปิดไปเลย วันที่ 7 ธันวาคม มีการนำเครื่องสำรองสำหรับงานพัฒนามาเสริมเซิร์ฟเวอร์ล็อบบี้เพื่อยกเพดานขึ้น error นี้จึงลดลง แต่คิวกลับยาวขึ้น กรณีที่สองคือเมื่อเน็ตของผู้เล่นที่กำลังรอไม่เสถียร พอรอนานขึ้น การเชื่อมต่อที่ขาดไปชั่วครู่เพราะแพ็กเก็ตหายบนเส้นทางอินเทอร์เน็ตหรือ Wi-Fi ไม่เสถียรก็เกิดบ่อยขึ้น เซิร์ฟเวอร์ล็อบบี้จะรอการเชื่อมต่อใหม่ให้ราวหลายสิบวินาทีถึง 1 นาที ถ้าเชื่อมต่อกลับมาได้ในช่วงนั้นจะได้ต่อคิวจากตำแหน่งเดิม แต่ถ้าเกินจะต้องไปต่อท้ายคิว Square Enix ระบุว่าการแจ้งปัญหาส่วนใหญ่เป็นกรณีนี้ นอกจากนี้ยังเพิ่มเวิลด์ทันทีไม่ได้เพราะขาดแคลนเซมิคอนดักเตอร์ บทเรียน ยิ่งคิวยาว เน็ตที่ขาดช่วงสั้น ๆ ของผู้เล่นที่กำลังรอก็ยิ่งกลายเป็น error ในการเชื่อมต่อ แม้ความแออัดจะเท่ากัน error ก็ไปกระจุกที่คนที่ใช้ Wi-Fi หรือเน็ตไม่เสถียร จนกลายเป็นปัญหาที่ “เกิดกับบางคนเท่านั้น” สัญญาณที่ใช้ยืนยันคือความยาวคิว, เวลารอ และสัดส่วนการหลุดระหว่างรอคิวเมื่อแยกตามเหตุผลที่หลุด ผู้รับผิดชอบหลักคือทีมพัฒนาเกม (เซิร์ฟเวอร์: เพดานคิวและช่วงผ่อนผันการเชื่อมต่อใหม่) ส่วนการเพิ่มเซิร์ฟเวอร์ล็อบบี้และเซิร์ฟเวอร์เวิลด์ ทีมอินฟราทำร่วมกัน ถ้าตั้งช่วงผ่อนผันการเชื่อมต่อใหม่ให้นานพอ จะลดโอกาสที่เน็ตขาดช่วงสั้น ๆ ของผู้เล่นลุกลามจนเสียลำดับคิว สาเหตุที่เกี่ยวข้อง คิวล็อกอินชนเพดานและ grace period ตอนเชื่อมต่อใหม่ไม่พอ , Wi-Fi ถูกรบกวนหรือสัญญาณอ่อน , แพ็กเก็ตหายช่วงไร้สาย ต้นฉบับ Square Enix
Cloudflare 2020: คอนฟิกแบ็กโบนของ Cloudflare ผิดพลาด ทำให้ทราฟฟิกบางเมืองหายไป เกิดอะไรขึ้น เป็นเหตุขัดข้องด้านอินฟราประเภทที่เกมได้รับผลกระทบไปด้วย เพราะเกมจำนวนมากฝากเว็บ, API และการป้องกัน DDoS ไว้กับผู้ให้บริการ CDN วันที่ 17 กรกฎาคม 2020 ตั้งแต่ 21:12 ถึง 21:39 (UTC) รวม 27 นาที ทราฟฟิกรวมของเครือข่าย Cloudflare ลดลงประมาณ 50% ผลกระทบจำกัดอยู่ที่จุดให้บริการในบางเมืองของสหรัฐฯ, ยุโรป, รัสเซีย และบราซิลที่เชื่อมกับแบ็กโบน ส่วนจุดอื่นยังปกติ สาเหตุ ช่วงแบ็กโบนนิวอาร์ก–ชิคาโกขัดข้อง ทำให้ช่วงแอตแลนตา–วอชิงตันแออัด วิศวกรจึงแก้คอนฟิกเราเตอร์เพื่อลดทราฟฟิกแบ็กโบนที่แอตแลนตา สิ่งที่ต้องทำคือปิดทั้งรายการนโยบาย (term) แต่กลับปิดแค่เงื่อนไขข้างใน (prefix-list) เราเตอร์แอตแลนตาจึงประกาศเส้นทาง BGP ทั้งหมดด้วยลำดับความสำคัญที่สูงกว่า (local-preference 200) ไปทั่วแบ็กโบน ขณะที่แต่ละจุดให้บริการตั้งลำดับความสำคัญของเส้นทางไปยังเซิร์ฟเวอร์ของตัวเองไว้ที่ 100 ทราฟฟิกของทุกจุดที่เชื่อมกับแบ็กโบนจึงแห่ไปที่แอตแลนตา แอตแลนตาโหลดเกิน ส่วนจุดที่ได้รับผลกระทบแทบไม่เหลือทราฟฟิกให้ประมวลผล เมื่อถอดเราเตอร์แอตแลนตาออกจากแบ็กโบน ระบบก็กลับมาปกติ Cloudflare ระบุว่าเหตุนี้ไม่เกี่ยวกับการโจมตีหรือการเจาะระบบ บทเรียน ถ้าผู้เล่นในบางเมืองหรือบางพื้นที่เท่านั้นเจออาการหลุดหรือเข้าเกมไม่ได้/โหลดไม่จบพร้อมกัน ขณะที่ที่อื่นปกติ ให้สงสัยการเปลี่ยนคอนฟิกเส้นทางที่เพิ่งทำไปก่อน บนกราฟ CPU และทราฟฟิกจะพุ่งที่จุดเดียว ส่วนจุดที่ได้รับผลกระทบกลับดิ่งลงเกือบ 0 ผู้รับผิดชอบหลักคือทีมอินฟรา (เครือข่าย) ถ้าเป็นเหตุขัดข้องฝั่งผู้ให้บริการก็เป็นภายนอก Cloudflare ตัดสินใจตั้งเพดานจำนวนเส้นทางที่รับได้ (maximum-prefix) บนเซสชัน BGP ของแบ็กโบน และปรับลำดับความสำคัญไม่ให้จุดหนึ่งดึงทราฟฟิกของจุดอื่นไปได้ สาเหตุที่เกี่ยวข้อง เส้นทาง BGP เปลี่ยนและ converge ใหม่ , เส้นทางเปลี่ยน/เส้นทาง ECMP ที่เสีย ต้นฉบับ Cloudflare
Fastly 2021: Fastly CDN เกิด error ทั่วโลก เกิดอะไรขึ้น เป็นเหตุขัดข้องด้านอินฟราประเภทที่เกมได้รับผลกระทบไปด้วย เพราะเกมจำนวนมากส่งไฟล์แพตช์, launcher และหน้าเว็บผ่าน CDN วันที่ 8 มิถุนายน 2021 ตั้งแต่ 09:47 (UTC) เครือข่ายของ Fastly 85% ตอบกลับเป็น error ภายใน 49 นาที เครือข่าย 95% กลับมาปกติ และเหตุขัดข้องคลี่คลายเมื่อ 12:35 สาเหตุ ซอฟต์แวร์ที่เริ่ม deploy เมื่อ 12 พฤษภาคม มีบั๊กที่จะทำงานเมื่อคอนฟิกบางแบบของลูกค้าเจอเงื่อนไขบางอย่าง วันที่ 8 มิถุนายน ลูกค้ารายหนึ่งส่งการเปลี่ยนคอนฟิกที่ถูกต้องตามปกติขึ้นไป ทำให้เงื่อนไขนั้นครบพอดี Fastly ตรวจพบความผิดปกติภายใน 1 นาที และเมื่อหาคอนฟิกของลูกค้าที่เป็นต้นเหตุเจอแล้วปิดไป ระบบก็เริ่มกลับมา การ deploy ตัวแก้บั๊กเริ่มในวันเดียวกันเวลา 17:25 บทเรียน แม้โค้ดที่ deploy ไปหลายสัปดาห์แล้ว ถ้าเจอเงื่อนไขที่เกิดยาก ก็กลายเป็นเหตุขัดข้องทั่วโลกได้ในพริบตา สัญญาณที่ใช้ยืนยันฝั่งเกมคืออัตรา HTTP error ของคำขอแพตช์, launcher และเว็บที่สูงขึ้นพร้อมกันทุกภูมิภาค และหน้าสถานะของผู้ให้บริการ CDN จุดสังเกตคือ ถ้าการเชื่อมต่อเกมที่เข้าอยู่แล้วไม่ผ่าน CDN ก็ยังปกติ มีแค่การเชื่อมต่อใหม่, การดาวน์โหลดแพตช์ และการล็อกอินผ่านเว็บที่ใช้ไม่ได้ ผู้รับผิดชอบหลักคือภายนอก (ผู้ให้บริการ CDN) ส่วนทีมพัฒนาเกมและทีมอินฟราควรเตรียมเส้นทางสำรองไว้ เช่น ใช้ CDN ตั้งแต่สองเจ้าขึ้นไป หรือดึงตรงจากเซิร์ฟเวอร์ต้นทาง สาเหตุที่เกี่ยวข้อง การพึ่งพาเซอร์วิสภายนอก ต้นฉบับ Fastly
Meta 2021: คำสั่งเดียวบนแบ็กโบนของ Facebook ทำให้ DNS หายไปด้วย เกิดอะไรขึ้น เป็นเหตุขัดข้องด้านอินฟราที่ใช้เป็นบทเรียนกับเครือข่ายและ DNS ของบริษัทเกมเองได้ตรง ๆ วันที่ 4 ตุลาคม 2021 บริการของ Facebook (ปัจจุบันคือ Meta) เข้าใช้งานไม่ได้ทั่วโลก แบ็กโบนที่เชื่อมดาต้าเซ็นเตอร์ขาดทั้งหมด และฝั่งอินเทอร์เน็ตหาเซิร์ฟเวอร์ DNS ของ Facebook ไม่เจอ บทวิเคราะห์ย้อนหลังไม่ได้ระบุว่าเหตุขัดข้องกินเวลานานเท่าไร สาเหตุ ระหว่างงานบำรุงรักษาตามรอบ คำสั่งที่รันเพื่อตรวจความจุของแบ็กโบนทั่วโลกกลับตัดการเชื่อมต่อทั้งหมดของแบ็กโบนโดยไม่ได้ตั้งใจ และเครื่องมือ audit ที่ควรกันคำสั่งแบบนี้ก็กันไม่ได้เพราะมีบั๊ก เซิร์ฟเวอร์ DNS ในจุดให้บริการขนาดเล็กถูกออกแบบให้ถือว่าตัวเองผิดปกติและถอนการประกาศเส้นทาง BGP เองเมื่อสื่อสารกับดาต้าเซ็นเตอร์ไม่ได้ จึงเข้าถึงจากอินเทอร์เน็ตไม่ได้ทั้งที่เซิร์ฟเวอร์ DNS ยังทำงานอยู่ ทั้งเส้นทางเข้าถึงปกติและการเข้าถึงแบบ out-of-band ขาดหมด เครื่องมือภายในก็ใช้ DNS ไม่ได้ จึงต้องส่งวิศวกรไปที่ดาต้าเซ็นเตอร์ด้วยตัวเอง และขั้นตอนด้านความปลอดภัยทำให้ใช้เวลานานขึ้นอีก ตอนกู้คืน การใช้ไฟฟ้าของแต่ละดาต้าเซ็นเตอร์ลดลงไปหลายสิบ MW ทีมประเมินว่าถ้าคืนโหลดทั้งหมดพร้อมกัน อาจเสี่ยงตั้งแต่ระบบไฟฟ้าไปจนถึงแคช จึงค่อย ๆ เพิ่มโหลดทีละขั้น บทเรียน ถ้าเกิดอาการเข้าเกมไม่ได้/โหลดไม่จบพร้อมกันในทุกพื้นที่และทุก ISP ให้ดู DNS และเส้นทาง BGP ก่อนเซิร์ฟเวอร์เกม ตรวจจากนอกบริษัทได้ด้วยการคิวรี DNS จากภายนอกและข้อมูลเส้นทาง BGP ที่เปิดเผยสาธารณะ ผู้รับผิดชอบหลักคือทีมอินฟรา (เครือข่าย) ควรตรวจล่วงหน้าว่าเส้นทางเข้าถึงแบบ out-of-band ที่จะใช้ตอนเกิดเหตุและเครื่องมือภายในไม่ได้พึ่ง DNS และเครือข่ายชุดเดียวกัน และตอนกู้คืนให้ค่อย ๆ เพิ่มโหลดทีละขั้นเพื่อไม่ให้การเชื่อมต่อใหม่ทะลักเข้ามาพร้อมกัน สาเหตุที่เกี่ยวข้อง เส้นทาง BGP เปลี่ยนและ converge ใหม่ , DNS ขัดข้อง/ช้า ต้นฉบับ Meta
AWS 2021: เครือข่ายภายในของ AWS us-east-1 แออัด เกิดอะไรขึ้น เป็นเหตุขัดข้องด้านอินฟราประเภทที่เกมได้รับผลกระทบไปด้วย เพราะเกมจำนวนมากวางเซิร์ฟเวอร์, ระบบล็อกอิน และข้อมูลไว้บนคลาวด์สาธารณะ วันที่ 7 ธันวาคม 2021 เวลา 7:30 (เวลามาตรฐานแปซิฟิก) เครือข่ายภายในของรีเจียนเวอร์จิเนียเหนือ (us-east-1) เริ่มแออัด ตั้งแต่ 7:33 error และความหน่วงของ EC2 API เพิ่มขึ้นจนเปิดอินสแตนซ์ใหม่ได้ยาก (การเปิดอินสแตนซ์กลับมาได้เมื่อ 14:40) ตามมาด้วยล็อกอินคอนโซลไม่สำเร็จ, เปลี่ยนคอนฟิก Route 53 ไม่ได้ และเมตริก CloudWatch ล่าช้าและหายไปบางส่วน อุปกรณ์เครือข่ายกลับมาปกติเต็มที่เมื่อ 14:22 อินสแตนซ์ EC2 ที่รันอยู่แล้วและการตอบ DNS ที่มีอยู่เดิมไม่ได้รับผลกระทบ สาเหตุ งานอัตโนมัติที่เพิ่มความจุของบริการหนึ่งบนเครือข่ายหลัก ทำให้ไคลเอนต์จำนวนมากบนเครือข่ายภายในทำงานแบบที่ไม่คาดคิด จนความพยายามเชื่อมต่อพุ่งสูง อุปกรณ์ที่เชื่อมเครือข่ายภายในกับเครือข่ายหลักรับไม่ไหว การสื่อสารจึงล่าช้า และความล่าช้านั้นก็ยิ่งเพิ่มความพยายามเชื่อมต่อและการลองใหม่ ความแออัดจึงลากยาว ไคลเอนต์มีกลไก backoff ที่เพิ่มช่วงห่างระหว่างคำขอเมื่อแออัดแบบนี้ แต่ข้อบกพร่องที่แฝงอยู่ทำให้กลไกนั้นทำงานไม่ถูกต้อง ระบบมอนิเตอร์ภายในก็พึ่งเครือข่ายเดียวกัน ทีมปฏิบัติการจึงไม่มีเมตริกแบบเรียลไทม์ให้ดู ต้องอาศัย log ในการรับมือ บทเรียน ถ้าการลองใหม่ไม่ยืดช่วงห่างออกไป ความแออัดสั้น ๆ ก็กลายเป็นเหตุขัดข้องที่ยาวหลายชั่วโมง มองจากฝั่งเกม แม้เซิร์ฟเวอร์เกมที่รันอยู่แล้วจะปกติ แต่การเพิ่มเซิร์ฟเวอร์ใหม่ (autoscaling), ล็อกอิน, การจับคู่ และการชำระเงินที่ใช้ API ของคลาวด์ รวมถึงระบบมอนิเตอร์ ก็อาจใช้ไม่ได้ไปพร้อมกัน สัญญาณที่ใช้ยืนยันคือหน้าสถานะของผู้ให้บริการคลาวด์, อัตรา error ของ API คลาวด์ และการเปิดอินสแตนซ์ที่ล้มเหลว ผู้รับผิดชอบหลักคือภายนอก (ผู้ให้บริการคลาวด์) ทีมพัฒนาเกมควรใส่ exponential backoff ที่สุ่มช่วงห่างและจำกัดจำนวนครั้งให้การลองใหม่ทุกจุด ส่วนทีมอินฟราควรเตรียมความจุสำรองที่พอรับมือได้แม้เพิ่มเครื่องไม่ได้ และทางเลือกในรีเจียนอื่น สาเหตุที่เกี่ยวข้อง ความล้มเหลวแบบลูกโซ่ , autoscaling เพิ่มเครื่องไม่ทัน , การพึ่งพาเซอร์วิสภายนอก ต้นฉบับ AWS
Cloudflare 2025: DNS สาธารณะ 1.1.1.1 ของ Cloudflare ขัดข้อง เกิดอะไรขึ้น เป็นเหตุขัดข้องของ DNS resolver สาธารณะที่ผู้เล่นตั้งค่าเองในอุปกรณ์หรือเราเตอร์ เป็นประเภทที่ทุกเกมและทุกบริการใช้ไม่ได้พร้อมกันเฉพาะกับผู้เล่นที่ใช้ค่านั้น วันที่ 14 กรกฎาคม 2025 ตั้งแต่ 21:52 ถึง 22:54 (UTC) รวม 62 นาที resolver 1.1.1.1 ไม่ตอบกลับทั่วโลก Cloudflare ระบุว่าสำหรับผู้ใช้จำนวนมาก นี่หมายถึงแทบใช้บริการอินเทอร์เน็ตอะไรไม่ได้เลย การคิวรีผ่าน UDP, TCP และ DNS over TLS ได้รับผลกระทบ ส่วน DNS over HTTPS ซึ่งเชื่อมต่อด้วยชื่อโดเมนค่อนข้างเสถียร สาเหตุ วันที่ 6 มิถุนายน ระหว่างเตรียม service topology (คอนฟิกที่กำหนดว่าจะประกาศช่วง IP จากจุดให้บริการใด) ของบริการอื่นที่จะใช้ในอนาคต ช่วง IP ของ resolver 1.1.1.1 ถูกผูกรวมเข้าไปในคอนฟิกนั้นโดยไม่ตั้งใจ วันที่ 14 กรกฎาคม เมื่อมีการเปลี่ยนคอนฟิกของบริการนั้น จุดที่ประกาศช่วง IP ของ resolver ก็ลดจากทุกจุดเหลือเพียงจุดเดียวซึ่งออฟไลน์อยู่ เส้นทาง BGP จึงถูกถอนทั่วโลก การเปลี่ยนแปลงนี้กระจายไปทุกดาต้าเซ็นเตอร์ทันทีโดยไม่ผ่าน canary deploy เมื่อย้อนคอนฟิกกลับเวลา 22:20 ทราฟฟิกกลับมาราว 77% แต่ระหว่างนั้นคอนฟิก IP ที่จำเป็นบนเซิร์ฟเวอร์ edge ราว 23% ถูกลบไป ต้องตั้งค่าใหม่ จึงกลับมาปกติเมื่อ 22:54 Cloudflare ระบุว่าเป็นความผิดพลาดของคอนฟิกภายใน และไม่เกี่ยวกับการโจมตีหรือ BGP hijacking บทเรียน ถ้าเซิร์ฟเวอร์เกมและผู้เล่นคนอื่นปกติ แต่ผู้เล่นบางส่วนเท่านั้นเจออาการเข้าเกมไม่ได้/โหลดไม่จบกับเซิร์ฟเวอร์ล็อกอินหรือเซิร์ฟเวอร์แพตช์ ให้สงสัย DNS ที่ผู้เล่นกลุ่มนั้นใช้ จุดสังเกตคือเซสชันที่เชื่อมต่ออยู่แล้วยังอยู่ได้ มีแค่การเชื่อมต่อใหม่ที่ล้มเหลว ให้ผู้เล่นลองเปลี่ยนการตั้งค่า DNS หรือคิวรีที่อยู่เซิร์ฟเวอร์เองดู ก็แยกได้ทันที ผู้รับผิดชอบหลักคือภายนอก (ผู้ดูแล DNS/ISP) ถ้าทีมพัฒนาเกม (ไคลเอนต์) แยกข้อความแจ้งกรณีแปลงชื่อเป็น IP ไม่สำเร็จออกจาก error อื่น ฝ่ายบริการลูกค้าก็ชี้สาเหตุได้ทันที สาเหตุที่เกี่ยวข้อง DNS ขัดข้อง/ช้า , เส้นทาง BGP เปลี่ยนและ converge ใหม่ ต้นฉบับ Cloudflare
AWS 2025: DNS ของ DynamoDB ใน AWS us-east-1 ขัดข้อง และการกู้คืนที่ยืดเยื้อ เกิดอะไรขึ้น เป็นเหตุขัดข้องด้านอินฟราประเภทที่เกมได้รับผลกระทบไปด้วย เพราะเกมจำนวนมากวางเซิร์ฟเวอร์, ระบบล็อกอิน และข้อมูลไว้บนคลาวด์สาธารณะ ตั้งแต่ 23:48 วันที่ 19 ตุลาคม 2025 ถึง 14:20 วันที่ 20 (เวลาออมแสงแปซิฟิก) รีเจียนเวอร์จิเนียเหนือได้รับผลกระทบต่อเนื่องเป็นสามช่วง error ของ DynamoDB API เพิ่มขึ้นจนถึง 2:40 วันที่ 20, การเปิดอินสแตนซ์ EC2 ใหม่ล้มเหลวตั้งแต่ 2:25 ถึง 10:36 (ปัญหาการเชื่อมต่อของอินสแตนซ์ใหม่บางตัวคลี่คลายเมื่อ 13:50) และ error การเชื่อมต่อของ Network Load Balancer (NLB) บางตัวเพิ่มขึ้นตั้งแต่ 5:30 ถึง 14:09 สาเหตุ ระบบอัตโนมัติที่จัดการ DNS ของ DynamoDB มี race condition แฝงอยู่ ในบรรดาตัวรันที่นำแผน DNS ไปใช้ (DNS Enactor) ซึ่งทำงานอยู่ใน availability zone ต่างกัน มีตัวหนึ่งที่ช้าผิดปกติแล้วเขียนแผนเก่าทับแผนใหม่ ทันทีหลังจากนั้น งานเก็บกวาดของตัวรันอีกตัวก็ลบแผนเก่านั้นทิ้ง DNS record ของ endpoint ระดับรีเจียน (dynamodb.us-east-1.amazonaws.com) จึงกลายเป็นค่าว่าง ระบบอัตโนมัติแก้เองไม่ได้ ต้องให้คนกู้คืนด้วยมือ ระบบจัดการเซิร์ฟเวอร์จริง (physical server) ของ EC2 พึ่ง DynamoDB อยู่ ระหว่างนั้น lease ที่ถือไว้กับเซิร์ฟเวอร์จริงแต่ละเครื่องจึงหมดอายุ หลัง DynamoDB กลับมา เซิร์ฟเวอร์จริงมีมากเกินไป งานต่อ lease ใหม่จึงไทม์เอาต์ก่อนเสร็จ และงานที่ต้องลองใหม่ก็สะสมขึ้นอีก จนตกอยู่ในสภาพ “ล่มเพราะความแออัด (congestive collapse)” การตั้งค่าเครือข่ายของอินสแตนซ์ที่เพิ่งเปิดกระจายไปช้า health check ของ NLB จึงสลับไปมาระหว่างสำเร็จกับล้มเหลว และแม้แต่โหนดที่ปกติก็ถูกถอดออกจาก DNS แล้วกลับเข้ามาซ้ำไปมา บทเรียน DNS record ที่ผิดพลาดเพียงจุดเดียวลุกลามไปยังบริการอื่นที่พึ่งบริการนั้น และแม้ต้นเหตุจะคลี่คลายแล้ว งานที่กองรออยู่กับ health check ที่แกว่งไปมาก็ทำให้การกู้คืนใช้เวลาอีกหลายชั่วโมง มองจากฝั่งเกม เซิร์ฟเวอร์ที่รันอยู่แล้วอาจยังไหว แต่เปิดเซิร์ฟเวอร์ใหม่ไม่ได้ autoscaling จึงหยุด และเมื่อ health check แกว่ง โหลดบาลานเซอร์ก็อาจถอดเซิร์ฟเวอร์ที่ปกติออก สัญญาณที่ใช้ยืนยันคือหน้าสถานะของคลาวด์, อัตรา error ของ API บริการแบบ managed, การเปิดอินสแตนซ์ที่ล้มเหลว และจำนวน target ที่ปกติของโหลดบาลานเซอร์ ผู้รับผิดชอบหลักคือภายนอก (ผู้ให้บริการคลาวด์) ส่วนทีมอินฟราควรจำกัดจำนวนเซิร์ฟเวอร์ที่ถูกถอดออกพร้อมกันเพราะ health check ล้มเหลว และเตรียมทางเลือกในรีเจียนอื่น สาเหตุที่เกี่ยวข้อง การพึ่งพาเซอร์วิสภายนอก , ความล้มเหลวแบบลูกโซ่ , autoscaling เพิ่มเครื่องไม่ทัน , โหลดบาลานเซอร์กระจายไม่เท่ากัน/health check ตัดสินผิด , DNS ขัดข้อง/ช้า ต้นฉบับ AWS
อภิธานศัพท์
ปิง Ping, RTT. เวลาที่สัญญาณจากเราเดินทางไปถึงเซิร์ฟเวอร์แล้วกลับมา (ไปกลับ) ปิงที่เกมแสดงบางครั้งก็รวมเวลารอประมวลผลบนเซิร์ฟเวอร์ไว้ด้วย
ความหน่วง Latency. เวลาตั้งแต่แพ็กเก็ตออกเดินทางจนถึงปลายทาง มักหมายถึงทางเดียว จึงประมาณครึ่งหนึ่งของปิง
จิตเตอร์ Jitter. ความไม่สม่ำเสมอของช่วงเวลาที่แพ็กเก็ตมาถึง ต่อให้ปิงเฉลี่ยเท่ากัน ถ้าจิตเตอร์สูง ภาพก็จะกระตุก
แพ็กเก็ต Packet. ก้อนข้อมูลที่ส่งผ่านเครือข่ายในครั้งเดียว ปกติใหญ่สุด 1,500 ไบต์ ส่วนอัปเดตของเกมมีขนาดหลักสิบถึงหลักร้อยไบต์
แพ็กเก็ตหาย Packet loss. แพ็กเก็ตที่ส่งออกไปแล้วหายระหว่างทาง ไปไม่ถึงปลายทาง เกมที่ใช้ TCP แค่ 1% ก็รู้สึกได้ว่าหยุดแวบทุกไม่กี่วินาทีถึงสิบกว่าวินาที ส่วนเกม UDP ที่มี interpolation และส่งอินพุตซ้ำ อาจกลบได้ถึงระดับไม่กี่เปอร์เซ็นต์
แบนด์วิดท์ Bandwidth. ปริมาณข้อมูลสูงสุดที่ลิงก์ส่งได้ใน 1 วินาที (Mbps) เป็นคนละเรื่องกับว่าข้อมูลไปถึงเร็วแค่ไหน (ความหน่วง)
ทิก Tick. หน่วยที่เซิร์ฟเวอร์คำนวณสถานะเกมหนึ่งรอบ เซิร์ฟเวอร์ 20 ทิกคำนวณ 20 ครั้งใน 1 วินาที หรือทุก 50 ms
ทิกเรต Tick rate. จำนวนทิกใน 1 วินาที ยิ่งสูงยิ่งตอบสนองเร็ว แต่ค่าเซิร์ฟเวอร์และปริมาณข้อมูลที่ส่งก็เพิ่มขึ้น บางเกมตั้งความถี่ในการส่งแพ็กเก็ตให้ต่ำกว่าทิกเรตเพื่อประหยัดปริมาณข้อมูล
งบเวลาต่อทิก Tick budget. เวลาสูงสุดที่ต้องทำหนึ่งทิกให้เสร็จ ถ้าเกิน ทิกถัดไปจะช้าลงและช่วงห่างระหว่างทิกจะยืดออก
FPS Frames per second. จำนวนครั้งที่วาดภาพใน 1 วินาที ที่ 60 FPS หนึ่งเฟรมใช้เวลา 16.7 ms
เฟรมไทม์ Frame time. เวลาที่ใช้วาดหนึ่งเฟรม เฟรมที่พุ่งเป็นบางครั้งส่งผลต่อความรู้สึกมากกว่า FPS เฉลี่ย
สแนปช็อต Snapshot. สรุป “สถานะเกมตอนนี้” ที่เซิร์ฟเวอร์ส่งมาทุกทิก มีตำแหน่ง, HP, สถานะ ฯลฯ ส่วนใหญ่จะคัดส่งเฉพาะส่วนที่ต่างจากสถานะที่ฝั่งรับมีอยู่แล้ว (delta compression)
อินเทอร์โพเลชัน Interpolation. เทคนิคที่วาดเชื่อมระหว่างสแนปช็อตสองอันที่ได้รับ ให้ภาพดูลื่น แลกกับการแสดงภาพย้อนหลังไปเล็กน้อย
บัฟเฟอร์อินเทอร์โพเลชัน Interpolation buffer. เวลาที่จงใจวาดภาพช้าลงเพื่อทำ interpolation เป็นเวลาเผื่อสำหรับดูดซับจิตเตอร์และแพ็กเก็ตหายหนึ่งสองตัว ปกติเป็น 2 เท่าของระยะห่างระหว่างแพ็กเก็ต (ถ้ารับ 20 ครั้งใน 1 วินาทีคือ 100 ms) บางเกมจะเพิ่มค่านี้เองเมื่อจิตเตอร์สูงขึ้น
Extrapolation, Dead reckoning. เทคนิคที่เมื่อไม่มีแพ็กเก็ตใหม่ จะใช้ความเร็วล่าสุดคาดเดาว่าวัตถุจะไปอยู่ตรงไหนแล้ววาดตามนั้น ถ้าเดาผิดจะดูเหมือนวาร์ป เกมจำนวนมากจึงเดาไว้แค่ราว 0.25 วินาทีแล้วหยุด (ค่าเริ่มต้นของ Source Engine คือ 0.25 วินาที)
การคาดการณ์ฝั่งไคลเอนต์ Client-side prediction. เทคนิคที่ขยับตัวละครของเราให้เห็นก่อน โดยไม่รอเซิร์ฟเวอร์ยืนยัน
การแก้ตำแหน่งตามเซิร์ฟเวอร์ Reconciliation. เมื่อผลจากเซิร์ฟเวอร์มาถึง จะเทียบกับที่คาดการณ์ไว้แล้วแก้ตำแหน่งตัวละครของเราให้ถูก โดยเริ่มจากตำแหน่งที่เซิร์ฟเวอร์ยืนยันแล้ว และนำอินพุตที่ยังไม่ได้รับการยืนยันมาคำนวณซ้ำ ถ้าต่างกันมากจะเห็นเป็นอาการดีดกลับ
การชดเชยแลค Lag compensation. เทคนิคที่เซิร์ฟเวอร์ย้อนเวลากลับไปยังจังหวะที่ผู้โจมตีเห็นอยู่ แล้วค่อยตรวจว่าโดนหรือไม่ มีการจำกัดระยะย้อนสูงสุดไว้ เพื่อไม่ให้ฝ่ายที่โดนยิงรู้สึกไม่ยุติธรรม เกมยิงแข่งขันมักตั้งไว้ราว 0.2–0.25 วินาที และบางกรณีย้อนได้ถึง 1 วินาทีเหมือนค่าเริ่มต้นของ Source Engine
เซิร์ฟเวอร์ผู้ตัดสิน Authoritative server. การออกแบบให้เซิร์ฟเวอร์เป็นผู้ตัดสินผลสุดท้ายแต่ผู้เดียว ช่วยกันการโกงได้ แต่ทุกผลลัพธ์ต้องรอไปกลับเซิร์ฟเวอร์ จึงต้องใช้ prediction และการแสดงผลล่วงหน้ากลบเวลารอ
ล็อกสเต็ป Deterministic lockstep. วิธีที่ทุกคนส่งกันแค่อินพุต แล้วคำนวณเหมือนกันทุกประการในเทิร์นเดียวกัน อินพุตจะมีดีเลย์คงที่ติดมาด้วย และถ้าอินพุตของใครสักคนมาช้า ทุกคนต้องรอ
บัฟเฟอร์อินพุตฝั่งเซิร์ฟเวอร์ Server-side input buffer. บัฟเฟอร์ที่เซิร์ฟเวอร์เก็บอินพุตของแต่ละคนไว้เล็กน้อย แล้วดึงมาใช้ทีละหนึ่งอินพุตต่อทิก คนที่จิตเตอร์สูงก็ดูลื่นในสายตาคนอื่น แต่การกระทำของคนนั้นจะถูกยืนยันบนเซิร์ฟเวอร์ช้าลงตามไปด้วย
ลิสเซินเซิร์ฟเวอร์ Listen server. วิธีที่ PC ของผู้เล่นคนหนึ่งทั้งเล่นเกมและทำหน้าที่เป็นเซิร์ฟเวอร์ไปพร้อมกัน หัวห้องจะมีปิงเป็น 0 แต่ถ้าเน็ตหรือ PC ของหัวห้องช้า ทุกคนจะแลคไปด้วย
เฟสซิง Phasing. ฟีเจอร์ที่แสดง NPC และภูมิประเทศต่างกันตามความคืบหน้าของเควสต์ แม้จะอยู่ที่เดียวกัน ถ้าความคืบหน้าของสองตัวละครต่างกัน การที่ฝั่งหนึ่งไม่เห็น NPC ถือเป็นเรื่องปกติ
โรลแบ็คเน็ตโค้ด Rollback netcode (GGPO). วิธีที่คาดเดาอินพุตของอีกฝ่ายแล้วเดินเกมไปก่อน ถ้าอินพุตจริงไม่ตรงกับที่เดา จะย้อนกลับไปยังเฟรมในอดีตแล้วคำนวณใหม่ นิยมใช้ในเกมต่อสู้ คำนี้เป็นคนละความหมายกับการโรลแบ็คของ DB
การกดล่วงหน้า Input buffer, spell queue. การรับอินพุตถัดไปที่กดไว้ก่อนคูลดาวน์หรือท่าจะจบเล็กน้อย แล้วสั่งให้ทำงานทันทีที่จบ ช่วยไม่ให้มีเวลาไปกลับแทรกอยู่ระหว่างคอมโบ
การแสดงผลล่วงหน้า Client-side feedback. การเล่นแอนิเมชัน เสียง และเอฟเฟกต์ไปก่อนโดยไม่รอเซิร์ฟเวอร์ยืนยัน เฉพาะผลที่ต้องยืนยัน เช่น ดาเมจหรือของรางวัล จึงรอคำตอบจากเซิร์ฟเวอร์ ถ้าเซิร์ฟเวอร์ปฏิเสธ ต้องย้อนสิ่งที่แสดงไปแล้วกลับคืน
TCP Transmission Control Protocol. โปรโตคอลที่ส่งข้อมูลให้ครบและตามลำดับ ถ้าแพ็กเก็ตหาย จะไม่ส่งแพ็กเก็ตถัดไปให้เกมจนกว่าจะได้แพ็กเก็ตที่หายกลับมา
UDP User Datagram Protocol. โปรโตคอลที่ส่งตามที่ได้รับโดยไม่รับประกันอะไรเลย ไม่ต้องรอ แต่เกมต้องจัดการเรื่องแพ็กเก็ตหายและลำดับเอง
UDP แบบเชื่อถือได้ Reliable UDP (KCP, ENet…). วิธีที่เขียนการส่งซ้ำและการรับประกันลำดับเองบน UDP เฉพาะเท่าที่จำเป็น
HOL blocking Head-of-line blocking. ปรากฏการณ์ที่ตัวหน้าสุดติดอยู่ ทำให้ทุกตัวที่ตามหลังต้องรอ เป็นต้นเหตุของอาการกรอเร็วใน TCP
RTO Retransmission timeout. ตัวจับเวลาส่งซ้ำ คือเวลาที่ TCP รอก่อนจะตัดสินว่าแพ็กเก็ตหายแล้วส่งใหม่ Linux ใช้ปิง + 200 ms ขึ้นไป และเพิ่มเป็นสองเท่าทุกครั้งที่ล้มเหลว
อัลกอริทึม Nagle Nagle’s algorithm. ฟีเจอร์ของ TCP ที่เก็บข้อมูลเล็ก ๆ ไว้จนกว่า ACK ของข้อมูลก่อนหน้าจะมาถึง แล้วส่งรวดเดียวเพื่อลดจำนวนแพ็กเก็ต ในเกมส่วนใหญ่ควรปิด
TCP_NODELAY TCP_NODELAY. socket option สำหรับปิดอัลกอริทึม Nagle ข้อความเล็ก ๆ จะถูกส่งทันที
ACK แบบหน่วงเวลา Delayed ACK. ฟีเจอร์ที่ส่งการยืนยันว่าได้รับข้อมูลช้าลงเล็กน้อย โดยรวมไปกับข้อมูลอื่น Linux ปกติใช้ 40 ms (สูงสุด 200 ms) ส่วน Windows รุ่นเก่าใช้ 200 ms และรุ่นใหม่ใช้ 40 ms
บัฟเฟอร์ซ็อกเก็ต SO_SNDBUF / SO_RCVBUF. ขนาดพื้นที่รอส่งและรอรับที่ OS กันไว้ให้แต่ละซ็อกเก็ต เล็กเกินไปจะล้น ใหญ่เกินไปข้อมูลเก่าจะกองรออยู่
keepalive SO_KEEPALIVE. ฟีเจอร์ของ TCP ที่ตรวจว่าการเชื่อมต่อที่ idle อยู่ยังใช้ได้หรือไม่ ค่าเริ่มต้นปิดอยู่ และต่อให้เปิด ค่าเริ่มต้นก็จะตรวจหลังผ่านไป 2 ชั่วโมง
RST TCP reset. สัญญาณของ TCP ที่ตัดการเชื่อมต่อทันที ข้อมูลที่ยังส่งไม่ออกจะถูกทิ้ง
ฮาร์ตบีต Heartbeat. สัญญาณ “ยังอยู่” ที่เกมส่งเองเป็นระยะ ใช้ตรวจจับการเชื่อมต่อที่ขาดไปแล้ว และรักษาการเชื่อมต่อในอุปกรณ์ระหว่างทางไว้
ไทม์เอาต์ Timeout. เกณฑ์ที่ถือว่าล้มเหลวถ้าไม่มีการตอบกลับภายในเวลานี้ สั้นเกินไปจะตัดสินผิด ยาวเกินไปจะตรวจพบช้า
NAT Network Address Translation. ฟีเจอร์ที่เราเตอร์ใช้พาอุปกรณ์หลายเครื่องในบ้านออกอินเทอร์เน็ตด้วย public IP เดียว และบันทึกการเชื่อมต่อไว้ในตาราง NAT
CGNAT Carrier-grade NAT. NAT ขนาดใหญ่ที่ ISP ใช้แบ่ง IP เดียวให้ลูกค้าหลายราย
MTU Maximum Transmission Unit. ขนาดแพ็กเก็ตใหญ่สุดที่ส่งได้ในครั้งเดียว ปกติ 1,500 ไบต์ และจะเล็กกว่านั้นในช่วงที่ผ่าน VPN หรือ PPPoE
บัฟเฟอร์โบลต Bufferbloat. ปรากฏการณ์ที่อุปกรณ์เก็บคิวไว้ยาวเกินไป จนความหน่วงเพิ่มเป็นหลายร้อย ms
SQM Smart Queue Management (fq_codel, CAKE). ฟีเจอร์ของเราเตอร์ที่รักษาคิวให้สั้นและปล่อยข้อมูลแต่ละ flow อย่างเป็นธรรม เป็นวิธีแก้ bufferbloat
QoS Quality of Service. ฟีเจอร์ที่ให้ลำดับความสำคัญกับทราฟฟิกสำคัญเพื่อให้ส่งออกไปก่อน
พีริง Peering. จุดที่ ISP เชื่อมเครือข่ายของกันและกัน มักแออัดช่วงหัวค่ำ
BGP Border Gateway Protocol. กติกาที่ ISP ใช้บอกกันว่าจะส่งข้อมูลไปทางเส้นทางไหนบนอินเทอร์เน็ต ถ้าเปลี่ยน เส้นทางและปิงก็เปลี่ยนตาม
DDoS Distributed Denial of Service. การโจมตีที่ส่งทราฟฟิกปริมาณมหาศาลจากหลายแหล่งเพื่อทำให้บริการใช้การไม่ได้
สครับบิงเซ็นเตอร์ DDoS scrubbing center. จุดให้บริการของผู้ให้บริการป้องกัน DDoS ที่รับทราฟฟิกซึ่งมุ่งไปยังเซิร์ฟเวอร์ไว้ก่อนระหว่างถูกโจมตี กรองการโจมตีออก แล้วส่งต่อเฉพาะทราฟฟิกปกติ ถ้าจุดนี้อยู่ไกล เส้นทางก็จะยาวขึ้น
ไฟร์วอลล์ Firewall. อุปกรณ์หรือโปรแกรมที่ยอมให้เฉพาะการเชื่อมต่อที่อนุญาตผ่านไปได้ และติดตามการเชื่อมต่อด้วยตารางเซสชัน
โหลดบาลานเซอร์ Load balancer. อุปกรณ์ที่กระจายการเชื่อมต่อขาเข้าไปยังเซิร์ฟเวอร์หลายเครื่อง
ตารางเซสชัน Session table, conntrack. ตารางที่อุปกรณ์หรือ OS ใช้ติดตามการเชื่อมต่อที่มีอยู่ในขณะนั้น ขนาดมีขีดจำกัด
ไมโครเบิสต์ Microburst. ปรากฏการณ์ที่ค่าเฉลี่ยต่ำ แต่ทราฟฟิกกระจุกตัวในช่วงสั้นมาก ๆ ไม่ถึง 1 ms
NIC Network Interface Card. การ์ดเครือข่ายของเซิร์ฟเวอร์
ริงบัฟเฟอร์ Ring buffer. บัฟเฟอร์ที่เก็บแพ็กเก็ตที่ NIC รับมาไว้จนกว่า CPU จะดึงไปประมวลผล ใช้สล็อตจำนวนคงที่วนซ้ำไปเรื่อย ๆ เมื่อสล็อตเต็มหมด แพ็กเก็ตใหม่จะถูกทิ้ง
อินเทอร์รัปต์ Interrupt. สัญญาณที่อุปกรณ์ใช้บอก CPU ว่า “มีงานเข้ามาแล้ว”
RSS Receive Side Scaling. ฟีเจอร์ของ NIC ที่กระจายแพ็กเก็ตที่ได้รับไปยังหลาย receive queue เพื่อให้ CPU หลายคอร์ช่วยกันประมวลผล
PPS Packets per second. จำนวนแพ็กเก็ตต่อวินาที เซิร์ฟเวอร์เกมมักชนขีดจำกัดของตัวเลขนี้ก่อนแบนด์วิดท์
เคอร์เนล Kernel. แกนกลางของระบบปฏิบัติการ ดูแลเครือข่าย หน่วยความจำ และการแบ่ง CPU
backlog Listen backlog. คิวที่คำขอเชื่อมต่อใหม่รออยู่ระหว่างที่เซิร์ฟเวอร์ยังไม่รับไป เมื่อคิวเต็ม Linux จะทิ้งคำขอใหม่เงียบ ๆ ส่วน Windows จะส่งการตอบกลับว่าปฏิเสธ
TIME_WAIT TIME_WAIT. สถานะที่ฝั่งซึ่งปิดการเชื่อมต่อก่อนจะเก็บคู่พอร์ตนั้นไว้ชั่วครู่ (Linux 60 วินาที) เผื่อแพ็กเก็ตที่มาถึงช้า
CPU steal Steal time. เวลาที่ VM อยากใช้ CPU แต่ต้องรอ เพราะเครื่องจริงกำลังให้ CPU กับ VM ตัวอื่น ดูได้จากค่า st ใน top
CPU throttling CFS throttling. กลไกที่บังคับให้คอนเทนเนอร์หยุดจนถึงรอบถัดไป เมื่อใช้ CPU ครบโควตา (quota) ภายในรอบเวลาที่กำหนด (CFS period ปกติ 100 ms)
ไฟล์ดิสคริปเตอร์ File descriptor. หมายเลข (fd) ที่ติดกับไฟล์หรือการเชื่อมต่อแต่ละตัวที่โปรเซสเปิดไว้ จำนวนมีขีดจำกัด
เธรด Thread. หน่วยงานย่อยที่ทำงานอย่างอิสระภายในโปรแกรม หลายเธรดทำงานพร้อมกันได้
การสลับคอนเท็กซ์ Context switch. การที่ CPU สลับจากเธรดที่กำลังทำงานไปเป็นอีกเธรดหนึ่ง มีต้นทุน
ล็อก Lock, Mutex. กลไกที่กันไม่ให้หลายเธรดใช้ข้อมูลที่ใช้ร่วมกันพร้อมกัน ให้ใช้ได้ทีละเธรด
เดดล็อก Deadlock. สภาพที่เธรดต่าง ๆ รอล็อกที่อีกฝ่ายถืออยู่ จนหยุดนิ่งไปตลอดกาล
เธรดพูล Thread pool. กลุ่ม worker thread ที่สร้างเตรียมไว้ล่วงหน้า ถ้าทุกตัวไม่ว่าง งานใหม่ต้องรอ
I/O แบบอะซิงโครนัส epoll, IOCP, io_uring. วิธีที่ไม่รอ I/O แต่ไปทำงานอื่นก่อน แล้วรับแจ้งเตือนเมื่อ I/O เสร็จ
AOI Area of Interest. “ระยะที่มองเห็นได้” ของผู้เล่นแต่ละคน ส่งเฉพาะความเปลี่ยนแปลงภายในระยะนี้เพื่อลดปริมาณข้อมูล เพื่อลดต้นทุนการหาว่าใครอยู่ในระยะบ้าง ปกติจะแบ่งแมพเป็นตาราง (grid) แล้วดูเฉพาะเซลล์ที่อยู่ใกล้
บรอดแคสต์ Broadcast, fan-out. การส่งความเปลี่ยนแปลงหนึ่งอย่างไปให้ทุกคนที่มองเห็นได้ ถ้าคนที่รวมตัวกันต่างมองเห็นกันหมด ปริมาณที่ต้องส่งจะเพิ่มตามกำลังสองของจำนวนคน
GC Garbage collection. ฟีเจอร์ที่เก็บคืนหน่วยความจำที่ใช้แล้วทิ้งโดยอัตโนมัติ ระหว่าง GC โปรแกรมอาจหยุดทำงาน
ฮีป Heap. พื้นที่หน่วยความจำที่โปรแกรมขอจัดสรรมาใช้ตามต้องการระหว่างทำงาน
หน่วยความจำรั่ว Memory leak. บั๊กที่ไม่คืนหน่วยความจำที่ใช้เสร็จแล้ว ทำให้การใช้งานเพิ่มขึ้นเรื่อย ๆ ต่อให้มี GC ก็เกิดได้ ถ้ายังมีที่ใดอ้างอิงอ็อบเจกต์ที่ใช้เสร็จแล้วอยู่
สวอป Swap, paging. การย้ายหน่วยความจำบางส่วนไปไว้บนดิสก์เมื่อแรมไม่พอ ถ้าจะกลับมาใช้หน่วยความจำส่วนนั้นอีก จะช้ากว่าแรมกว่า 1,000 เท่า
OOM killer Out-of-memory killer. ฟีเจอร์ของ Linux ที่เมื่อหน่วยความจำหมด จะเลือกโปรเซสที่ใช้หน่วยความจำมากที่สุดแล้วบังคับปิด สำหรับคอนเทนเนอร์ แค่แตะขีดจำกัดหน่วยความจำก็ทำงานแล้ว
แคชมิส Cache miss. การที่ข้อมูลไม่อยู่ในแคชที่ใกล้ CPU ต้องไปอ่านถึงหน่วยความจำที่ช้ากว่า
IOPS I/O operations per second. จำนวนครั้งที่ดิสก์อ่านหรือเขียนได้ใน 1 วินาที ดิสก์บนคลาวด์มีขีดจำกัดตามที่จ่ายเงิน
fsync fsync. คำสั่งที่รอจนกว่าข้อมูลจะถูกบันทึกลงดิสก์จริง ๆ การเขียนปกติจะไปอยู่ในหน่วยความจำของ OS ก่อนแล้วค่อยถูกเขียนลงดิสก์ภายหลัง ถ้าไฟดับระหว่างนั้น ข้อมูลอาจหายได้ fsync ปลอดภัยแต่ช้า
เบิสต์เครดิต Burst credits. เครดิตสะสมที่ทำให้ดิสก์หรือเซิร์ฟเวอร์บนคลาวด์ทำงานได้เกินประสิทธิภาพพื้นฐานชั่วคราว เมื่อใช้จนหมดจะตกกลับไปที่ประสิทธิภาพพื้นฐาน
อินเด็กซ์ Index. ดัชนีของ DB ถ้าไม่มี ต้องอ่านทั้งตาราง
ฟูลสแกน Full table scan. คิวรีที่ไล่อ่านทุกแถวในตารางโดยไม่ใช้อินเด็กซ์
แผนการรันคิวรี Query plan. วิธีที่ DB เลือกว่าจะรันคิวรีตามลำดับใดและใช้อินเด็กซ์ใด ต่อให้โค้ดไม่เปลี่ยน ถ้า DB เปลี่ยนแผน คิวรีเดิมก็อาจช้าลงกะทันหันได้
ทรานแซกชัน Transaction. งานใน DB ที่ผูกรวมเป็นหนึ่งเดียวแบบ “สำเร็จทั้งหมดหรือไม่สำเร็จเลย” การเทรดต้องทำในทรานแซกชันเสมอ ระหว่างที่ยังไม่จบจะล็อกแถวที่แก้ไว้ จึงยิ่งสั้นยิ่งดี
คอนเนกชันพูล Connection pool. กลุ่มการเชื่อมต่อ DB ที่เปิดเตรียมไว้ล่วงหน้า ถ้าถูกใช้หมด คำขอใหม่ต้องรอ
ฮอตโรว์ Hot row. แถวเดียวที่คำขอจำนวนมากพยายามแก้พร้อมกัน เป็นต้นเหตุของการแย่งล็อก
การทำสำเนาข้อมูลล่าช้า Replication lag. ระยะเวลาที่ DB สำเนาตามไม่ทัน DB หลัก
โรลแบ็ค Rollback. การที่การบันทึกถูกยกเลิกแล้วกลับไปเป็นสถานะก่อนหน้า ผู้เล่นจะรู้สึกว่า “ไอเทมหาย”
แคช Cache (Redis etc.). การคัดลอกข้อมูลที่ใช้บ่อยไปเก็บในที่ที่เร็ว ช่วยลดโหลดของ DB
เช็กพอยต์ Checkpoint. งานที่ DB เขียนการเปลี่ยนแปลงที่สะสมไว้ในหน่วยความจำลงดิสก์ทีเดียวเป็นระยะ ขณะนั้นการบันทึกและการดึงข้อมูลอาจช้าลงชั่วครู่
เฟลโอเวอร์ Failover. การสลับไปใช้ฝั่งสำรองเมื่อเซิร์ฟเวอร์หลักหรือ DB หลักล่ม ระหว่างสลับจะบันทึกไม่ได้ชั่วครู่ และถ้า replication ตามไม่ทัน ข้อมูลช่วงสุดท้ายอาจหาย
MVCC Multi-version concurrency control. วิธีที่ DB เก็บเวอร์ชันเก่าไว้ชั่วคราว เพื่อไม่ให้คนอ่านกับคนแก้ขวางกัน ถ้ามีทรานแซกชันที่เปิดทิ้งไว้นาน เวอร์ชันเก่าจะสะสมจนช้าลง
แคชสแตมปีด Cache stampede. ปรากฏการณ์ที่แคชว่างลงพร้อมกัน จนคำขอแห่ไปที่ต้นทาง (DB)
เกตเวย์ Gateway. เซิร์ฟเวอร์ตัวกลางที่รับการเชื่อมต่อจากไคลเอนต์แล้วส่งต่อไปยังเซิร์ฟเวอร์เกมด้านหลัง
เซอร์กิตเบรกเกอร์ Circuit breaker. กลไกที่ตัดการเรียกเซอร์วิสที่ล้มเหลวต่อเนื่องไว้ชั่วคราวและตอบกลับเป็นล้มเหลวทันที เพื่อกัน cascading failure พอผ่านไปสักพักจะลองเรียกหนึ่งสองครั้ง ถ้ากลับมาใช้ได้แล้วจึงเปิดให้เรียกตามปกติอีกครั้ง
ความล้มเหลวแบบลูกโซ่ Cascading failure. การที่เหตุขัดข้องในจุดหนึ่งลามไปยังเซอร์วิสอื่นตาม call chain
ออโตสเกลลิง Autoscaling. ฟีเจอร์ที่เพิ่มหรือลดจำนวนเซิร์ฟเวอร์อัตโนมัติตามโหลด การเพิ่มเครื่องต้องใช้เวลา
วอตช์ด็อก Watchdog. ตัวจับเวลาที่เฝ้าดูว่าเซิร์ฟเวอร์หยุดทำงานหรือไม่ ถ้าลูปของเกมหยุดนานเกินเวลาที่กำหนด (หลายวินาทีถึงหลายสิบวินาที) จะบันทึกสถานะ (dump) ไว้ แล้วบังคับปิดเซิร์ฟเวอร์เพื่อให้เปิดใหม่
อัตราการใช้งาน Utilization. สัดส่วนเวลาที่ worker (ตัวที่ประมวลผลคำขอ เช่น คอร์ CPU, เธรด หรือการเชื่อมต่อ DB) ไม่ว่าง ถ้าเกิน 80–90% การรอจะเพิ่มขึ้นอย่างรวดเร็ว
p99 99th percentile. ค่าที่ 99 ครั้งใน 100 ครั้งเร็วกว่านี้ และราว 1 ครั้งช้ากว่านี้ สะท้อนแลคที่ผู้เล่นรู้สึกได้ดีกว่าค่าเฉลี่ย
V-Sync Vertical sync. ฟีเจอร์ที่ส่งเฟรมออกให้ตรงกับรอบการรีเฟรชของจอ ช่วยแก้ภาพฉีก (screen tearing) แต่ทำให้เกิดอินพุตดีเลย์ และถ้า FPS ตกต่ำกว่าอัตรารีเฟรช ภาพอาจกระตุกเพราะสลับไปมาระหว่าง 60 กับ 30
อัตรารีเฟรชแบบแปรผัน VRR, G-Sync, FreeSync. ฟีเจอร์ที่ให้จอเปลี่ยนภาพตามจังหวะที่เฟรมพร้อม ช่วยลดอาการกระตุกจากการสลับไปมาระหว่าง 60 กับ 30 ของ V-Sync และลดอินพุตดีเลย์
แอนตี้ชีต Anti-cheat. โมดูลความปลอดภัยที่ป้องกันการแฮ็กเกม ถ้าการตรวจสอบเป็นระยะหรือ heartbeat กับเซิร์ฟเวอร์ล้มเหลว ก็อาจทำให้เกิดอาการกระตุกหรือหลุดได้
โอเวอร์เลย์ Overlay. ฟีเจอร์ที่โปรแกรมแชต โปรแกรมอัดหน้าจอ หรือโปรแกรมแสดง FPS วาดภาพซ้อนทับบนหน้าจอเกม โปรแกรมเหล่านี้แทรกเข้าไปในขั้นตอนการวาดภาพของเกม จึงทำให้กระตุกได้
การคอมไพล์เชเดอร์ Shader compilation. งานแปลงโปรแกรมเอฟเฟกต์กราฟิกให้ใช้กับ GPU ได้ ถ้าไม่ทำไว้ล่วงหน้า ภาพจะหยุดแวบตอนเห็นเอฟเฟกต์นั้นครั้งแรก และเมื่ออัปเดตไดรเวอร์การ์ดจอ ผลที่เก็บไว้จะใช้ไม่ได้ ต้องคอมไพล์ใหม่
เมนเธรด Main thread, Game thread. เธรดหลักของเกมที่ไล่ทำการคำนวณกติกาเกมและการเตรียมภาพตามลำดับ ถ้ามีงานใดใช้เวลานานแม้แค่งานเดียว ภาพจะหยุดไปตลอดช่วงนั้น
ความละเอียดของตัวจับเวลา Timer resolution. ช่วงเวลาสั้นที่สุดที่ระบบปฏิบัติการปลุกโปรแกรมที่หลับอยู่ได้ ค่าเริ่มต้นของ Windows คือ 15.6 ms ถ้าโปรแกรมไม่เปลี่ยนค่านี้เอง ต่อให้สั่ง “ปลุกในอีก 1 ms” ก็จะตื่นช้ากว่านั้น
การลดความเร็วเพราะความร้อน Thermal throttling. ฟีเจอร์ป้องกันที่ลดความเร็ว CPU/GPU ลงเองเมื่อเครื่องร้อน บนมือถือเกิดบ่อยหลังเล่นเกมไปหลายนาทีถึงหลายสิบนาที
VRAM Video memory. หน่วยความจำเฉพาะบนการ์ดจอ เท็กซ์เจอร์และโมเดลจะถูกโหลดขึ้นไปไว้ที่นี่ก่อนวาด ถ้าไม่พอ จะต้องรับส่งกับหน่วยความจำของ PC ผ่านเส้นทางที่ช้า ภาพจึงกระตุก
เน็ตกราฟ Net graph. หน้าจอสำหรับพัฒนาและดีบั๊กที่แสดงปิง แพ็กเก็ตหาย FPS และทิกเป็นกราฟแบบเรียลไทม์บนหน้าจอเกม ถ้าติดมาในคลิปแจ้งแลคด้วย จะหาสาเหตุได้ง่ายขึ้นมาก
อัตราการส่งซ้ำ Retransmission rate. สัดส่วนแพ็กเก็ต TCP ที่ต้องส่งซ้ำจากที่ส่งไปทั้งหมด ไม่มีเกณฑ์ที่เป็นทางการ แต่ถ้าค่าเฉลี่ยของทั้งเซิร์ฟเวอร์ต่ำกว่า 0.1% ถือว่าอยู่ในเกณฑ์ดี และถ้าเกิน 1% ผู้เล่นจำนวนมากจะเริ่มรู้สึกแลค ควรดูด้วยว่าเพิ่มขึ้นจากค่าปกติกี่เท่า
SACK Selective ACK. ฟีเจอร์ของ TCP ที่ฝั่งรับแจ้งอย่างละเอียดว่า “ได้ช่วงนี้แล้ว ขาดแค่ส่วนนี้” ต่อให้หายหลายตัวก็กู้คืนได้ในรอบเดียว
RACK-TLP Recent ACK, Tail Loss Probe. ฟีเจอร์ของ TCP ที่ใช้เวลาเป็นเกณฑ์ตัดสินว่าแพ็กเก็ตหาย และถ้าไม่มี ACK อยู่ช่วงหนึ่ง จะส่งแพ็กเก็ตสุดท้ายซ้ำอีกครั้งเพื่อเร่งการกู้คืน เป็นค่าเริ่มต้นใน Linux และ Android รุ่นใหม่ ฝั่ง Windows เปิด TLP และ RACK เป็นค่าเริ่มต้นตั้งแต่ Windows 10 (1607) และ Server 2016 ส่วน RACK รุ่นใหม่ที่กู้คืนได้แม้แต่การส่งซ้ำที่หายไป มีตั้งแต่ Server 2022 ทำงานเฉพาะการเชื่อมต่อที่เปิด SACK
การส่งซ้ำโดยไม่จำเป็น Spurious retransmission. การส่งซ้ำแพ็กเก็ตที่ไม่ได้หาย แค่มาช้าหรือมาสลับลำดับจนถูกเข้าใจว่าหาย ทำให้เปลืองแบนด์วิดท์และลดอัตราการส่งลงโดยไม่จำเป็น
ซีโรวินโดว์ Zero window. สถานะที่บัฟเฟอร์ฝั่งรับเต็มจนแจ้งว่า “หยุดส่งก่อน” ดูเหมือนการส่งซ้ำ แต่เน็ตไม่ได้มีปัญหา โปรแกรมฝั่งรับแค่อ่านข้อมูลไม่ทัน
thin stream Thin stream. การเชื่อมต่อที่ส่งแพ็กเก็ตเล็ก ๆ ห่าง ๆ แบบเกม สัญญาณสำหรับ fast retransmit สะสมได้ยาก เมื่อแพ็กเก็ตหายจึงหยุดนาน
โพลิเซอร์ Policer. วิธีจำกัดความเร็วที่ทิ้งแพ็กเก็ตส่วนที่เกินความเร็วที่กำหนดทันทีโดยไม่พักไว้ในคิว ส่วนวิธีที่พักไว้ในคิวแล้วค่อย ๆ ปล่อยออกเรียกว่า shaper
เพซซิง Pacing. การกระจายแพ็กเก็ตที่จะส่งให้ออกไปอย่างสม่ำเสมอตามเวลา แทนการส่งออกไปทีเดียวทั้งหมด ช่วยกันไม่ให้บัฟเฟอร์ขนาดเล็กล้น
ECN Explicit Congestion Notification. ฟีเจอร์ที่เมื่อเครือข่ายแออัด จะติดเครื่องหมาย “แออัด” ให้แพ็กเก็ตแทนการทิ้ง เพื่อให้ฝั่งส่งลดความเร็วลง บอกความแออัดได้โดยไม่ต้องมีแพ็กเก็ตหาย ต้องรองรับทั้งปลายทั้งสองฝั่งและอุปกรณ์ในช่วงที่แออัดจึงจะได้ผล
MSS Maximum Segment Size. ขนาดข้อมูลสูงสุดที่ TCP ใส่ในแพ็กเก็ตหนึ่ง ปกติ 1,460 ไบต์ ถ้าลดลงให้เข้ากับช่วงที่ผ่านอุโมงค์ (tunnel) จะป้องกัน MTU black hole ได้
แฮนด์โอเวอร์ Handover. การที่มือถือซึ่งกำลังเคลื่อนที่เปลี่ยนสถานีฐานที่เชื่อมต่ออยู่
เปอร์เซ็นไทล์ Percentile (p50, p95, p99). ค่าที่อยู่ในตำแหน่งกี่เปอร์เซ็นต์เมื่อเรียงค่าจากน้อยไปมาก p50 คือค่ามัธยฐาน p99 คือค่าที่อยู่แถว ๆ ครั้งที่ช้าที่สุด 1 ครั้งใน 100 ครั้ง ช่วยเผยค่าที่พุ่งซึ่งค่าเฉลี่ยซ่อนไว้
ความหน่วงส่วนหาง Tail latency. ความหน่วงนาน ๆ ที่เกิดเป็นบางครั้ง ทั้งที่ส่วนใหญ่เร็ว แทบไม่ปรากฏในค่าเฉลี่ย แต่เป็นส่วนที่ผู้เล่นจำได้ว่าแลค
การวัดแบบสังเคราะห์ Synthetic monitoring. การใช้อุปกรณ์หรือเซิร์ฟเวอร์สำหรับวัดส่ง ping, traceroute ฯลฯ จากจุดที่กำหนดเป็นระยะแทนผู้เล่นจริง เพื่อวัดคุณภาพเส้นทาง RIPE Atlas เป็นเครื่องมือสาธารณะที่เป็นที่รู้จัก
ช่วงเวลารวมค่า Aggregation interval. จุดหนึ่งบนกราฟรวมค่าของกี่วินาทีหรือกี่นาที ยิ่งช่วงยาว ค่าที่พุ่งสั้น ๆ จะถูกเฉลี่ยจนจางลง
การวิเคราะห์หลังเกิดเหตุ Postmortem. เอกสารที่สรุปหลังเหตุขัดข้องจบลงว่าเกิดอะไรขึ้น ทำไมจึงเกิด และจะเปลี่ยนอะไร เขียนขึ้นเพื่อป้องกันไม่ให้เกิดซ้ำมากกว่าเพื่อหาคนผิด
C-state CPU idle state. สถานะประหยัดพลังงานที่ CPU เข้าไปเมื่อว่าง ยิ่งลึกยิ่งประหยัดไฟ แต่ต้องใช้เวลาตื่นกลับมานานขึ้น
ไลฟ์ไมเกรชัน Live migration. การที่คลาวด์ย้าย VM ที่กำลังทำงานอยู่ไปยังโฮสต์อื่น เช่น เพื่อซ่อมบำรุงโฮสต์ ขณะย้ายอาจหยุดไปชั่วครู่
SNAT Source NAT. NAT ที่เปลี่ยน IP ต้นทางของแพ็กเก็ตขาออกเป็น public IP จำนวนพอร์ตที่ public IP หนึ่งตัวใช้ได้มีขีดจำกัด ถ้าใช้หมด การเชื่อมต่อใหม่จะล้มเหลว
NAT เกตเวย์ NAT gateway. อุปกรณ์บนคลาวด์ที่ให้เซิร์ฟเวอร์ในเครือข่ายส่วนตัวใช้ public IP ร่วมกันหนึ่งตัวเวลาออกอินเทอร์เน็ต จำนวนการเชื่อมต่อพร้อมกันต่อปลายทางมีขีดจำกัด
อินเทอร์เน็ตดาวเทียมวงโคจรต่ำ LEO satellite internet. อินเทอร์เน็ตที่เชื่อมต่อผ่านดาวเทียมจำนวนมากที่ความสูงหลักร้อยถึงหลักพันกิโลเมตร ความหน่วงสั้นกว่าดาวเทียมวงโคจรค้างฟ้ามาก แต่เมื่อเปลี่ยนดาวเทียมที่เชื่อมต่อ ความหน่วงอาจพุ่งขึ้นได้
GeoIP IP geolocation. ฐานข้อมูลที่ใช้ IP address ประมาณประเทศ เมือง และ ISP บางรายการผิดหรือล้าสมัย จึงอาจเป็นสาเหตุให้ถูกส่งไปเซิร์ฟเวอร์ในภูมิภาคที่อยู่ไกล
ใบรับรอง TLS TLS certificate. เอกสารอิเล็กทรอนิกส์ที่ยืนยันว่าเซิร์ฟเวอร์เป็นตัวจริง มีวันหมดอายุ ถ้าหมดอายุ การเชื่อมต่อแบบเข้ารหัสจะล้มเหลวจนเข้าใช้งานไม่ได้
การสร้างเฟรม Frame generation. เทคโนโลยีที่การ์ดจอแทรกเฟรมที่คาดการณ์ขึ้นระหว่างเฟรมที่วาดจริง เพื่อเพิ่ม FPS ภาพลื่นขึ้น แต่ความหน่วงตั้งแต่อินพุตจนถึงภาพบนจออาจเพิ่มขึ้น
เอกสารอ้างอิง
เอกสาร 616 รายการ จากผู้เผยแพร่ 83 ราย ได้แก่ เอกสารมาตรฐาน, เอกสารทางการของเคอร์เนล OS คลาวด์ เอนจิน และ DB, งานวิจัย และบทความเทคนิคจากผู้พัฒนาต้นทาง
Microsoft 85 _WDF_TIMER_CONFIG (wdftimer.h) Microsoft ความแม่นยำของตัวจับเวลาทั่วไปคือช่วงห่างของ system clock tick ค่าเริ่มต้น 15.6 ms ส่วน high-resolution timer คือ 1 ms /fp (Specify floating-point behavior) Microsoft /fp:fast อาจสลับหรือรวมลำดับการคำนวณ floating point จนผลต่างจากการตั้งค่า /fp แบบอื่น และการคำนวณที่รวมด้วย FMA ก็อาจต่างจากการคูณแล้วบวกแยกกัน 5157(F): The Windows Filtering Platform has blocked a connection. Microsoft Event 5157: Windows Filtering Platform บล็อกการเชื่อมต่อ (Audit Filtering Platform Connection) About regular quick and full scans with Microsoft Defender Antivirus Microsoft การป้องกันแบบเรียลไทม์จะสแกนทุกครั้งที่เปิดและปิดไฟล์ About Windows Filtering Platform Microsoft โครงสร้างที่อนุญาตหรือบล็อกแพ็กเก็ตด้วย hook และ filter engine ใน network stack ของ Windows ผู้ผลิตซอฟต์แวร์ความปลอดภัยภายนอกเสียบโมดูลกรองของตัวเอง (callout) เข้าไปได้ Acquiring high-resolution time stamps Microsoft QueryPerformanceCounter (ที่ Stopwatch ใช้) เป็นนาฬิกาสำหรับวัดเวลาที่ผ่านไปซึ่งไม่ซิงก์กับเวลาภายนอก ใช้เวลาของระบบเฉพาะเมื่อต้องการเวลา UTC Address false positives/negatives in Microsoft Defender for Endpoint Microsoft ขั้นตอนตั้งข้อยกเว้นและส่งไฟล์ให้ Microsoft วิเคราะห์ เมื่อโปรแกรมปกติถูกเข้าใจผิดว่าเป็นภัย (false positive) Algorithmic improvements boost TCP performance on the Internet Microsoft TLP เป็นค่าเริ่มต้นตั้งแต่ Windows Server 2016, RACK แบบใหม่ที่กู้คืนได้ถึงการส่งซ้ำที่หาย มาพร้อม Server 2022, PRR เป็นค่าเริ่มต้นตั้งแต่ Windows 10 1903 ASP.NET Core Best Practices Microsoft เรียกการเข้าถึงข้อมูล I/O และงานที่ใช้เวลานานแบบ asynchronous, การเรียกแบบ synchronous ที่บล็อกทำให้ thread pool หมดและตอบสนองช้า Audit Filtering Platform Packet Drop Microsoft Event 5152: Windows Filtering Platform บล็อกแพ็กเก็ต bind function (winsock.h) Microsoft ถ้า bind พอร์ต 0 จะได้พอร์ตที่ไม่ซ้ำจากช่วง dynamic port (49152–65535) Chapter 12 - Detecting Memory Bottlenecks Microsoft Memory\Pages Input/sec: จำนวนเพจที่อ่านจากดิสก์เพื่อแก้ page fault (hard page fault) closesocket function (winsock.h) Microsoft ถ้าเปิด SO_LINGER และตั้งเวลาเป็น 0 การปิดจะกลายเป็นการปิดแบบบังคับที่รีเซ็ตการเชื่อมต่อทันที และข้อมูลที่ยังส่งไม่ออกจะหายไป Collecting User-Mode Dumps Microsoft ตั้งค่า Windows Error Reporting (WER) ให้เก็บ full dump หรือ mini dump ไว้ในเครื่องเมื่อโปรแกรม user mode แครช CPU Analysis Microsoft กราฟ DPC/ISR ของ WPA: เวลาของแต่ละช่วงที่ DPC/ISR ทำงานต่อเนื่อง และโมดูล (Module) ที่ฟังก์ชันนั้นอยู่ CreateMutexW function (synchapi.h) Microsoft ถ้ามี named mutex อยู่แล้วจะคืน ERROR_ALREADY_EXISTS ใช้ตรวจการเปิดซ้ำและจำกัดให้เปิดได้ครั้งเดียว CreateWaitableTimerExW function (synchapi.h) Microsoft แฟล็กของ high-resolution waitable timer: CREATE_WAITABLE_TIMER_HIGH_RESOLUTION Creating and Opening Files Microsoft ไฟล์ที่เปิดโดยไม่มี share mode โปรเซสอื่นจะเปิดไม่ได้ และเกิด ERROR_SHARING_VIOLATION Customize the Windows performance power slider Microsoft โหมดประหยัดพลังงานในการทดลอง: โหมดพลังงานของ Windows ปรับการตั้งค่าพลังงานและ CPU ไปทางยืดเวลาแบตเตอรี่ โดยแลกกับประสิทธิภาพที่ลดลง Debug ThreadPool Starvation Microsoft เมื่อ pool ไม่มีเธรดเหลือและงานใหม่ต้องรอ การตอบสนองจะช้าลง ต้นเหตุคือโค้ดแบบ blocking ที่ถือครองเธรด ใน dotnet-counters ถ้า CPU ต่ำกว่า 100% มากแต่ dotnet.thread_pool.thread.count ค่อย ๆ เพิ่มเรื่อย ๆ คือสัญญาณว่าหมด (dotnet.thread_pool.queue.length มักสูงด้วย), ดูจุดที่เธรดรอด้วย dotnet-stack Delivery Optimization reference Microsoft ค่าเริ่มต้นของการดาวน์โหลด Windows Update (Delivery Optimization) จะปรับตามแบนด์วิดท์ที่ใช้ได้แบบไดนามิก และตั้งเพดานแบนด์วิดท์การดาวน์โหลดเบื้องหลังและเบื้องหน้าได้ Design issues - Sending small data segments over TCP with Winsock Microsoft TCP ของ Windows รุ่นเก่าตั้งตัวจับเวลา delayed ACK 200 ms เมื่อได้รับข้อมูล และ Nagle เปิดเป็นค่าเริ่มต้น แพ็กเก็ตเล็กจึงต้องรอ ACK, แก้ด้วย TCP_NODELAY Direct3D 12 Return Codes Microsoft D3D12_ERROR_DRIVER_VERSION_MISMATCH: PSO cache ที่สร้างจากไดรเวอร์คนละเวอร์ชันใช้ซ้ำไม่ได้ (ต้องคอมไพล์ใหม่หลังอัปเดตไดรเวอร์) DirectStorage is coming to PC Microsoft ฮาร์ดดิสก์รุ่นเก่าอ่านได้หลายสิบ MB ต่อวินาที, NVMe SSD หลาย GB ต่อวินาที, งบการสตรีมแอสเซ็ตของเกมยุคก่อนราว 50 MB ต่อวินาที, เกมโอเพนเวิลด์อ่านและทิ้งฉากที่อยู่ไกลแบบเรียลไทม์ขณะเคลื่อนที่ dotnet-stack diagnostic tool - .NET CLI Microsoft เก็บและพิมพ์ managed stack ของทุกเธรดในโปรเซส .NET DXGI_QUERY_VIDEO_MEMORY_INFO structure (dxgi1_4.h) Microsoft Budget (งบ video memory ที่ OS กำหนด) และ CurrentUsage (ปริมาณที่แอปใช้อยู่) ถ้าใช้เกินงบอาจเกิดอาการกระตุก Find user-mode memory leaks with Performance Monitor (PerfMon) Microsoft บันทึก Process > Private Bytes (หน่วยความจำเฉพาะที่โปรเซสจัดสรร) และ Virtual Bytes เป็นเวลานาน ถ้าเพิ่มขึ้นอย่างเดียวคือหน่วยความจำรั่ว Floating-point numeric types (C# reference) Microsoft ความแม่นยำของ float ราว 6–9 หลัก, double ราว 15–17 หลัก GPUs in the task manager Microsoft Task Manager มีคอลัมน์แสดงอัตราการใช้ GPU ของแต่ละโปรเซส และบอกว่าค่านั้นเป็นของ GPU และ engine ตัวไหน Graceful Shutdown, Linger Options, and Socket Closure Microsoft ลำดับคือใช้ shutdown ปิดเฉพาะฝั่งส่งก่อน แล้วปิดซ็อกเก็ตหลังได้รับการแจ้งปิดจากอีกฝั่ง Guidelines for Writing DPC Routines Microsoft ระหว่างที่ DPC ทำงาน ทุกเธรดบนคอร์นั้นจะหยุด จึงแนะนำว่าไม่ควรเกิน 100 µs ต่อครั้ง I/O Completion Ports Microsoft ใช้ thread pool ที่สร้างไว้ล่วงหน้าร่วมกับ IOCP จัดการ async I/O จำนวนมาก และกำหนดจำนวนเธรดที่รันพร้อมกันให้เท่ากับจำนวนที่ CPU รันพร้อมกันได้ IDXGIDevice1::SetMaximumFrameLatency Microsoft ค่าเริ่มต้นของจำนวนเฟรมที่ไดรเวอร์เก็บในคิวได้คือ 3 (1–16) Introduction to NDIS Selective Suspend Microsoft Windows ส่ง network adapter ที่ว่างอยู่เข้าสู่สถานะพลังงานต่ำได้ (selective suspend) Introduction to the page file Microsoft page file คือไฟล์บนดิสก์ที่ใช้สำหรับย้ายเพจหน่วยความจำที่ถูกแก้ไขแล้วแต่ไม่ค่อยได้ใช้ออกจาก RAM ipconfig Microsoft ถ้ารันโดยไม่ใส่พารามิเตอร์ จะแสดงที่อยู่ IPv4/IPv6 และ default gateway ของแต่ละอะแดปเตอร์ listen function (winsock2.h) Microsoft บน Windows เมื่อคิวเต็ม ไคลเอนต์จะได้รับข้อผิดพลาด WSAECONNREFUSED Logging in C# Microsoft เมธอด log ของ .NET เป็นแบบ synchronous ถ้าที่เก็บช้า แนะนำให้เขียนลงที่เก็บที่เร็วก่อนแล้วค่อยย้ายทีหลัง Low Latency Workloads Management and Operations Microsoft Dropped Datagrams และ Dropped Datagrams/sec ในชุดตัวนับ Microsoft Winsock BSP: จำนวน UDP ที่ถูกทิ้งเพราะมาเร็วกว่าที่แอปประมวลผลทัน หรือ receive buffer ของซ็อกเก็ตไม่พอ Maximum Number of Sockets Supported Microsoft Winsock ของ Windows จำกัดจำนวนซ็อกเก็ตด้วยหน่วยความจำที่ใช้ได้เท่านั้น Minidump Files Microsoft minidump เก็บเฉพาะข้อมูลส่วนที่มีประโยชน์ของ crash dump จึงสร้างได้เร็วและเล็ก Multitasking Microsoft Windows ให้ time slice แก่แต่ละเธรด เมื่อใช้หมดจะสลับไปเธรดถัดไป time slice ยาวราว 20 ms (ต่างกันตาม OS และ CPU) netstat Microsoft -a แสดงพอร์ต TCP/UDP, -n แสดงที่อยู่เป็นตัวเลข, -o แสดง process ID (PID), -p udp แสดงเฉพาะ UDP Network-Related Performance Counters Microsoft ตัวนับ Processor Information: % Processor Time nslookup Microsoft คำสั่งสำหรับถามชื่อจากเซิร์ฟเวอร์ DNS โดยตรง Packet Monitor (Pktmon) Microsoft เครื่องมือในตัวที่แสดงตำแหน่งและเหตุผลที่แพ็กเก็ตถูกทิ้ง ณ หลายจุดใน network stack ของ Windows pathping Microsoft ส่ง ping ไปแต่ละ hop เป็นช่วงเวลาหนึ่งเพื่อคำนวณอัตราแพ็กเก็ตหายของแต่ละเราเตอร์และลิงก์ แล้วแสดงว่าแพ็กเก็ตหายเกิดที่ช่วงไหน Performance analyzer for Microsoft Defender Antivirus Microsoft อัดด้วย New-MpPerformanceRecording แล้วใช้ Get-MpPerformanceReport ดูไฟล์, path และโปรเซสอันดับต้น ๆ ที่มีผลต่อเวลาสแกน ping Microsoft /t: ส่ง echo request ต่อไปเรื่อย ๆ จนกว่าจะสั่งหยุด Pktmon command formatting Microsoft มีมาในตัวเป็น pktmon.exe ใน Windows 10 และ Windows Server 2019 (1809 ขึ้นไป) Powercfg command-line options Microsoft powercfg /energy: วิเคราะห์ระบบแล้วสร้างรายงานพลังงาน (HTML) Priority Boosts Microsoft โปรเซสของหน้าต่างที่อยู่ด้านหน้า (foreground) จะได้รับการยก priority ให้ไม่ต่ำกว่าโปรเซสเบื้องหลัง Process Monitor Microsoft บันทึกกิจกรรมของ file system, registry และโปรเซสแบบเรียลไทม์ และกรองได้ด้วยทุกฟิลด์ รวมถึง path Pushing the Limits of Windows: Virtual Memory Microsoft บน Windows เมื่อถึง commit limit การจัดสรรที่ต้อง commit หน่วยความจำจะล้มเหลว และอาจนำไปสู่ข้อผิดพลาดของแอปหรือระบบขัดข้อง Quality of Service Microsoft โปรแกรมของหน้าต่างที่มองไม่เห็นและไม่มีเสียงจะได้ Low QoS เมื่อใช้แบตเตอรี่จะถูกจัดให้รันที่ความเร็ว CPU ที่ประหยัดที่สุดและบน efficiency core recvfrom function (winsock.h) Microsoft WSAECONNRESET บนซ็อกเก็ต UDP หมายความว่าการส่งครั้งก่อนได้รับ ICMP Port Unreachable กลับมา Reduce latency with DXGI 1.3 swap chains Microsoft Present ถูกบล็อกจนกว่าคิวจะว่าง ทำให้ต้องรอเกือบอีกหนึ่งเฟรมตั้งแต่วาดเสร็จจนแสดงผล ลดได้ด้วย waitable swap chain Request scheduling Microsoft grain (actor) ของ Orleans ใช้โมเดลรันแบบเธรดเดียวที่ประมวลผลคำขอทีละรายการจนจบ จึงไม่มีการแก้สถานะพร้อมกัน, ถ้า grain รอการตอบกลับของกันและกันอาจเกิดเดดล็อก Residency Microsoft แต่ละโปรเซสมีงบหน่วยความจำกราฟิกที่ใช้ได้ ถ้าเกิน เคอร์เนลจะย้าย heap บางส่วนของ GPU แยกไปไว้ในหน่วยความจำของ PC (เป็นทางเลือกสุดท้าย จึงแนะนำให้จัดการงบเอง) Resolve-DnsName Microsoft ใช้ -Server กำหนดเซิร์ฟเวอร์ DNS ที่จะถาม แล้วค้นหาชื่อ Results for the Idle Energy Efficiency Assessment Microsoft ความละเอียดของ system timer ค่าเริ่มต้น 15.6 ms หาโปรเซสที่เปลี่ยนความละเอียดของตัวจับเวลาได้จากหัวข้อ “Platform Timer Resolution” ในรายงานพลังงาน Scheduling Priorities Microsoft ในบรรดาเธรดที่พร้อมทำงาน เธรดที่มีลำดับความสำคัญสูงสุดจะได้ time slice ผลัดกันไป (round robin) send function (winsock2.h) Microsoft Winsock ก็เช่นกัน ถ้าพื้นที่บัฟเฟอร์ไม่พอ send จะถูกบล็อก เว้นแต่อยู่ในโหมด non-blocking SO_KEEPALIVE socket option Microsoft ไทม์เอาต์เริ่มต้นของ TCP keepalive บน Windows คือ 2 ชั่วโมง Socket.ReceiveBufferSize Property Microsoft ขนาดเริ่มต้นของ receive buffer ของซ็อกเก็ตต่างกันตาม OS SOL_SOCKET Socket Options (Winsock2.h) Microsoft SO_RCVBUF ของ Windows: พื้นที่บัฟเฟอร์ที่จองไว้สำหรับรับข้อมูลในแต่ละซ็อกเก็ต TCP improvements in the Windows network stack (IETF 98 TCPM) Microsoft เปลี่ยนไทม์เอาต์ delayed ACK เริ่มต้นของ Windows เป็น 40 ms (ประกาศปี 2017) TCP Templates for Windows Server 2019 – How to tune your Windows Server Transports (Advanced users only 😉) Microsoft เทมเพลต Server 2019: DelayedAckTimeout 40 ms, MaxSynRetransmissions 2, InitialRto 3000 ms TCP/IP connectivity issues troubleshooting Microsoft จำนวนครั้งที่ส่ง SYN ซ้ำต่างกันไปตาม OS ตรวจได้จาก Max SYN Retransmissions ใน netsh int tcp show global TCP/IP port exhaustion troubleshooting Microsoft ช่วง dynamic port เริ่มต้นของ Windows คือ 49152–65535 และการเชื่อมต่อที่ปิดแล้วจะถือพอร์ตไว้ในสถานะ TIME_WAIT 4 นาทีโดยค่าเริ่มต้น TcpMaxConnectRetransmissions Microsoft ค่าเริ่มต้นของ Windows รุ่นเก่า: ส่ง SYN ซ้ำ 2 ครั้ง รอครั้งแรก 3 วินาทีแล้วเพิ่มเป็นสองเท่า หลังครั้งสุดท้ายรออีกสองเท่าแล้วเลิก (3+6+12=21 วินาที) The application or service crashing behavior troubleshooting guidance Microsoft Event ID 1000 ใน Application log คือบันทึกการแครชจริง มีชื่อแอปที่ผิดพลาดและชื่อโมดูลที่ผิดพลาด (Faulting module name) timeBeginPeriod function (timeapi.h) Microsoft ก่อน Windows 10 เวอร์ชัน 2004 เป็นการตั้งค่าทั้งระบบ หลังจากนั้นมีผลเฉพาะโปรเซสที่ร้องขอ Windows 11 ไม่รับประกันความละเอียดสูงให้โปรเซสของหน้าต่างที่ถูกบังหรือถูกย่อ Using SO_REUSEADDR and SO_EXCLUSIVEADDRUSE Microsoft ถ้า bind พอร์ตเดียวกันเป็นตัวที่สองด้วย SO_REUSEADDR จะแย่งพอร์ตไป และไม่รู้ว่าซ็อกเก็ตไหนจะได้รับแพ็กเก็ต WDDM Support for Timeout Detection and Recovery (TDR) Microsoft ถ้า GPU ทำงานไม่เสร็จภายในค่าเริ่มต้น 2 วินาที Windows จะรีเซ็ตไดรเวอร์กราฟิกและ GPU WDI low latency connection quality Microsoft การค้นหาและ roaming ย้ายชิปไร้สายออกนอกช่องสัญญาณที่เชื่อมต่ออยู่ โหมด low latency จึงจำกัดเวลาที่ออกนอกช่องสัญญาณและการค้นหา Well-known EventCounters in .NET Microsoft Monitor Lock Contention Count (monitor-lock-contention-count): จำนวนครั้งที่เกิดการแย่งกันตอนพยายามถือ monitor lock Windows Firewall Rules Microsoft ค่าเริ่มต้นคือบล็อกการเชื่อมต่อขาเข้า แอปจึงต้องมีกฎยกเว้น และปกติโปรแกรมติดตั้งของแอปเป็นตัวสร้างกฎนี้ Windows Performance Monitor Disk Counters Explained Microsoft Avg. Disk sec/Read คือเวลาเฉลี่ยที่การอ่านหนึ่งครั้งใช้จนเสร็จ (ดีเลย์ของ I/O), Current Disk Queue Length คือความยาวคิวดิสก์ ณ ขณะที่วัด Windows Sockets Error Codes Microsoft หมายเลขข้อผิดพลาดของ WSAECONNRESET คือ 10054 Winsock IOCTLs Microsoft SIO_UDP_CONNRESET ใช้เปิดหรือปิดการรายงานข้อความแจ้ง “ไม่พบพอร์ต” (PORT_UNREACHABLE) ของ UDP Wireless network connectivity issues troubleshooting Microsoft netsh wlan show networks mode=bssid: แสดง BSSID, ความแรงสัญญาณ, ช่องสัญญาณ และมาตรฐานไร้สายของ Wi-Fi แต่ละตัวที่มองเห็น WlanSetInterface function (wlanapi.h) Microsoft API สำหรับเปิดปิดการค้นหาเบื้องหลัง (wlan_intf_opcode_background_scan_enabled) และโหมด media streaming บน Windows Working Set Microsoft การเข้าถึงเพจที่ไม่อยู่ใน RAM คือ page fault ส่วน hard fault ต้องอ่านจากดิสก์ เช่น page file จึงจะแก้ได้ Xbox Series X: What’s the Deal with Latency? Microsoft อินพุตดีเลย์คือผลรวมของเส้นทางคอนโทรลเลอร์→คอนโซล→HDMI→ทีวี, คอนโทรลเลอร์รุ่นเก่าอ่านและส่งอินพุตทุก 8 ms, เวลาส่งหนึ่งเฟรมผ่าน HDMI คือ 60 Hz 16.6 ms และ 120 Hz 8.3 ms, ALLM สลับทีวีเป็น Game Mode อัตโนมัติ
Linux kernel 62 ABI stable symbols Linux kernel /sys/block/(ดิสก์)/queue/rotational: บอกว่าอุปกรณ์เป็นแบบหมุนหรือไม่หมุน CFS Bandwidth Control Linux kernel ถ้าใช้โควตาของรอบหมด เธรดจะหยุดจนถึงรอบถัดไป (throttling), รอบเริ่มต้น 100 ms, สถิติ nr_throttled Concepts overview Linux kernel เก็บคืน page cache ที่มีต้นฉบับอยู่บนดิสก์และ page ที่สวอปได้ ถ้ายังไม่พอ OOM killer จะฆ่าโปรเซส Control Group v2 Linux kernel cpu.max ใช้รูปแบบ “$MAX $PERIOD” (โควตา, รอบ) และค่าเริ่มต้นคือ “max 100000” (รอบ 100 ms) CPU Idle Time Management Linux kernel โหมดประหยัดพลังงานแต่ละระดับมีเวลาตื่น (exit latency) และเวลาอยู่ขั้นต่ำ (target residency) และจะเลือกสถานะลึกตามเวลาว่างที่คาดไว้, latency, usage และ time ของแต่ละ state ใน sysfs, จำกัดสถานะลึกด้วย PM QoS (/dev/cpu_dma_latency) และ intel_idle.max_cstate CPU Performance Scaling Linux kernel ตรวจและเปลี่ยน governor ด้วย scaling_governor, performance จะขอความถี่สูงสุดในช่วงที่อนุญาต, powersave ขอความถี่ต่ำสุด Documentation for /proc/sys/net/ Linux kernel netdev_max_backlog: ขีดจำกัดของคิวรับที่ใช้พักแพ็กเก็ตเมื่อแพ็กเก็ตเข้ามาเร็วกว่าที่เคอร์เนลประมวลผลทัน Documentation for /proc/sys/vm/ Linux kernel min_free_kbytes: เกณฑ์หน่วยความจำว่างขั้นต่ำ (watermark) ที่เคอร์เนลกันไว้ drivers/idle/intel_idle.c (Linux v6.12) Linux kernel เวลาตื่นของแต่ละ C-state บน CPU เซิร์ฟเวอร์ของ Intel: Skylake-SP (C1 2 µs, C1E 10 µs, C6 133 µs), Ice Lake (C6 170 µs), Sapphire Rapids (C1 1 µs, C6 290 µs) drivers/net/ethernet/intel/ice/ice.h (Linux v6.12) Linux kernel receive descriptor ของไดรเวอร์ ice ค่าเริ่มต้น 2,048 สูงสุด 8,160 drivers/net/ethernet/intel/igb/igb_ethtool.c Linux kernel ไดรเวอร์เป็นผู้กำหนดชื่อตัวนับใน ethtool -S (เช่น rx_missed_errors และ rx_no_buffer_count ของ igb) drivers/net/ethernet/intel/ixgbe/ixgbe_main.c (Linux v6.12) Linux kernel ไดรเวอร์ ixgbe รีเซ็ตอะแดปเตอร์เมื่อการส่งหยุด และบันทึก “NIC Link is Down” เมื่อลิงก์ขาด EEVDF Scheduler Linux kernel Linux เริ่มย้ายจาก CFS ไปใช้ scheduler EEVDF ตั้งแต่ 6.6 Ethtool counters Linux kernel rx_out_of_buffer (ไม่มีบัฟเฟอร์ในคิวรับ) และ rx_discards_phy (ทิ้งเพราะบัฟเฟอร์ของพอร์ตไม่พอ) ของไดรเวอร์ mlx5 include/net/sock.h (Linux v6.18) Linux kernel กำหนดบัฟเฟอร์ซ็อกเก็ตเริ่มต้นเท่ากับแพ็กเก็ตขนาด 256 ไบต์จำนวน 256 แพ็กเก็ตรวม overhead ของ sk_buff (SKB_TRUESIZE(256)×256), เฟรมเล็ก ๆ ก็คิดเป็น sk_buff+MTU (ประมาณ 208 KB คือค่าที่คำนวณบน x86-64) include/net/tcp.h (Linux v6.12) Linux kernel TCP_TIMEWAIT_LEN (60*HZ): TIME_WAIT ประมาณ 60 วินาทีเป็นค่าคงที่ของเคอร์เนล include/uapi/linux/tcp.h Linux kernel tcpi_reord_seen ใน tcp_info: จำนวนครั้งที่การเชื่อมต่อเจอการสลับลำดับ intel_pstate CPU Performance Scaling Driver Linux kernel อัลกอริทึม powersave ของ intel_pstate ต่างจาก powersave governor ทั่วไป คือปรับตามโหลด (คล้าย schedutil และ ondemand) Interface statistics Linux kernel rx_crc_errors: จำนวนแพ็กเก็ตที่รับมาพร้อม CRC error, ดูแยกตามชนิด error ได้ด้วย ip -s -s link IP Sysctl Linux kernel tcp_mtu_probing=1 ปกติปิดอยู่ และจะเปิดการค้นหา path MTU ของ TCP เมื่อตรวจพบ ICMP black hole Linux Base Driver for Intel(R) Ethernet Network Connection (e1000) Linux kernel receive descriptor ของ e1000 (สล็อตของ ring) ค่าเริ่มต้น 256 เพิ่มได้ถึง 4,096 Linux Base Driver for the Intel(R) Ethernet 10 Gigabit PCI Express Adapters (ixgbe) Linux kernel GRO คือฟีเจอร์ที่รวมทราฟฟิกขาเข้าเป็นก้อนใหญ่เพื่อประหยัด CPU และพัฒนาต่อมาจาก LRO Linux Driver for Intel(R) Ethernet Network Connection (e1000e) Linux kernel ค่าเริ่มต้นคือ adaptive interrupt moderation ที่ 4,000–20,000 ครั้งต่อวินาที (ห่างกัน 50–250 µs), ลดอินเทอร์รัปต์แล้วประหยัด CPU แต่ความหน่วงเพิ่มขึ้น MDS - Microarchitectural Data Sampling Linux kernel mitigation จะล้างบัฟเฟอร์ CPU ตอนกลับจากเคอร์เนลไปยัง user space และตอนเข้า VM, ตรวจสถานะช่องโหว่และ mitigation ได้จากไฟล์ใต้ /sys/devices/system/cpu/vulnerabilities/, CPU จำนวนมากต้องปิด SMT จึงจะป้องกันได้สมบูรณ์ และการปิด SMT อาจกระทบประสิทธิภาพมากแล้วแต่งาน mm/oom_kill.c (Linux v6.12) Linux kernel คำนวณให้โปรเซสที่ใช้หน่วยความจำมากที่สุดได้คะแนนสูงสุด (รวม oom_score_adj), เมื่อปิดจะบันทึก “Out of memory: Killed process …” NAPI Linux kernel ถ้าตั้ง gro_flush_timeout ไว้สูง จะได้การประมวลผลแบบรวมก้อน แต่เกิดความหน่วงเมื่อโหลดต่ำ net/core/net-procfs.c Linux kernel /proc/net/softnet_stat มีหนึ่งบรรทัดต่อ CPU เป็นเลขฐาน 16 คอลัมน์ที่ 2 คือ dropped และคอลัมน์ที่ 3 คือ time_squeeze net/core/sock_reuseport.c (Linux v6.12) Linux kernel ถ้าไม่มีโปรแกรม BPF จะนำค่า hash ของแพ็กเก็ตมาแบ่งตามจำนวนซ็อกเก็ตในกลุ่มเพื่อเลือกซ็อกเก็ตที่รับ net/ipv4/proc.c (Linux v6.12) Linux kernel ชื่อตัวนับที่ nstat แสดง: RcvbufErrors และ SndbufErrors ในกลุ่ม Udp net/ipv4/tcp_bbr.c Linux kernel BBR กำหนด pacing_rate จากแบนด์วิดท์คอขวดที่ประเมินได้แล้วส่งตามนั้น net/ipv4/tcp_diag.c (Linux v6.12) Linux kernel ค่า Recv-Q และ Send-Q ของ ss: ซ็อกเก็ตที่ listen อยู่คือจำนวนการเชื่อมต่อที่รอ accept และขีดจำกัด backlog, ซ็อกเก็ตที่เชื่อมต่อแล้วคือไบต์ที่แอปยังไม่ได้อ่าน และไบต์ที่ส่งไปแล้วแต่ยังไม่ได้รับ ACK net/ipv4/tcp_input.c (Linux v6.12) Linux kernel RTO ของ Linux = smoothed RTT + ค่าความแปรปรวนของ RTT และค่าความแปรปรวนมีขั้นต่ำเป็น tcp_rto_min (200 ms) RTO จึงไม่ต่ำกว่า RTT + 200 ms net/ipv4/tcp_ipv4.c Linux kernel การกำหนดค่าเริ่มต้น: tcp_early_retrans 3, tcp_recovery RACK, tcp_syn_linear_timeouts 4, tcp_base_mss 1,024 (tcp_mtu_probing ไม่ได้กำหนดแยก จึงเป็น 0) net/ipv4/tcp_output.c Linux kernel TLP ของ Linux ถูกตั้งเวลาเฉพาะในการเชื่อมต่อที่ใช้ SACK net/ipv4/tcp_recovery.c Linux kernel เวลาเผื่อของ RACK = min(min_RTT/4 × ขั้น, SRTT), การส่งซ้ำที่ได้รับการยืนยันเร็วกว่า RTT ต่ำสุดจะไม่ถูกนำมาใช้เป็นเกณฑ์ net/ipv4/tcp_timer.c (Linux v6.12) Linux kernel ทุกครั้งที่ตัวจับเวลาส่งซ้ำหมดเวลา จะเพิ่ม TCPTimeouts เพิ่ม backoff ทีละหนึ่ง และเพิ่ม RTO เป็นสองเท่า (จนถึงค่าสูงสุด) net/ipv4/udp.c (Linux v6.12) Linux kernel ถ้าคิวรับของ UDP เกินขนาดบัฟเฟอร์ซ็อกเก็ต จะทิ้งทันทีและเพิ่มค่า RcvbufErrors net/netfilter/nf_conntrack_core.c (Linux v6.12) Linux kernel เมื่อตาราง connection tracking เต็ม จะบันทึก “nf_conntrack: table full, dropping packet” แล้วทิ้งแพ็กเก็ตของการเชื่อมต่อใหม่ net/netfilter/nf_conntrack_standalone.c Linux kernel /proc/net/stat/nf_conntrack มีหนึ่งบรรทัดต่อคอร์ เป็นเลขฐาน 16 และมีคอลัมน์ entries, invalid, insert_failed, drop, early_drop ฯลฯ net/sched/sch_generic.c (Linux v6.12) Linux kernel เมื่อ transmit queue หยุด watchdog ของเคอร์เนลจะบันทึก “NETDEV WATCHDOG … transmit queue N timed out” และเรียกฟังก์ชันรีเซ็ตของไดรเวอร์ net/wireless/core.c Linux kernel ขีดจำกัดการลองใหม่เริ่มต้นของ wireless stack ใน Linux: เฟรมสั้น 7 ครั้ง, เฟรมยาว 4 ครั้ง (dot11ShortRetryLimit, dot11LongRetryLimit) Netfilter Conntrack Sysfs variables Linux kernel จำนวนรายการสูงสุดในตาราง connection tracking ของ Linux (nf_conntrack_max) และค่าเริ่มต้นของระยะเวลาที่เก็บไว้ในแต่ละสถานะ PSI - Pressure Stall Information Linux kernel some (สัดส่วนเวลาที่งานบางส่วนหยุดรอหน่วยความจำ) และ full (สัดส่วนเวลาที่งานทั้งหมดหยุด) ใน /proc/pressure/memory Runtime locking correctness validator Linux kernel ถ้าถือล็อกสองตัวในลำดับสลับกัน จะเกิดการรอวนเป็นเดดล็อก (lock inversion deadlock), เคอร์เนล Linux ตรวจลำดับการถือล็อกและเตือนล่วงหน้า Scaling in the Linux Networking Stack Linux kernel RSS (NIC กระจายไปหลาย receive queue) และ RPS (เคอร์เนลกระจาย), การตั้งให้แต่ละคิวมีอินเทอร์รัปต์ของตัวเองแล้วแบ่งไปหลายคอร์, ถ้าการจัดการอินเทอร์รัปต์ขาเข้าเป็นคอขวด แนะนำ RSS SNMP counter Linux kernel TcpExtListenOverflows: จำนวนครั้งที่ทิ้งคำขอเชื่อมต่อ (SYN) เพราะคิว accept เต็ม ซึ่ง TcpExtListenDrops จะเพิ่มขึ้นไปพร้อมกัน Spectre Side Channels Linux kernel เพื่อป้องกันช่องโหว่ จะล้างบัฟเฟอร์ branch prediction ตอน context switch และตอนสลับ VM, mitigation แบบเข้มเพิ่ม overhead ให้ทุกโปรแกรม tcp: add sysctl_tcp_rto_min_us Linux kernel เพิ่ม tcp_rto_min_us ซึ่งเป็นค่าต่ำสุดของ RTO เริ่มต้นของทั้งเซิร์ฟเวอร์ ตั้งแต่ Linux 6.11 tcp: add the ability to control max RTO Linux kernel เพิ่ม socket option TCP_RTO_MAX_MS (1–120 วินาที) ตั้งแต่ Linux 6.15 tcp: disable RFC6675 loss detection Linux kernel เปลี่ยน RACK เป็นวิธีตรวจจับการหายหลัก (ปี 2018, Linux 4.18) tcp: limit payload size of sacked skbs Linux kernel commit แก้ช่องโหว่การจัดการ SACK ปี 2019 (CVE-2019-11477) tcp: make the first N SYN RTO backoffs linear Linux kernel commit ที่เปลี่ยนการส่ง SYN ซ้ำช่วงแรกให้เว้นช่วงคงที่ ตั้งแต่ Linux 6.5 (ค่าเริ่มต้น 4 ตามแบบของ macOS และ iOS) tcp: remove obsolete and unused RFC3517/RFC6675 loss recovery code Linux kernel ลบโค้ดการกู้คืนตาม RFC6675 (Linux 6.17) พร้อมคำอธิบายว่า RACK-TLP เป็นค่าเริ่มต้นมาตั้งแต่ปี 2018 tcp: remove thin_dupack feature Linux kernel ลบ thin_dupack ในเดือนมกราคม 2017 (Linux 4.11) พร้อมคำอธิบายว่า RACK ทำหน้าที่นั้นแทน tcp: support TCP_RTO_MIN_US for set/getsockopt use Linux kernel เพิ่ม socket option TCP_RTO_MIN_US สำหรับกำหนดค่าต่ำสุดของ RTO รายซ็อกเก็ต ตั้งแต่ Linux 6.15 tcp: use RACK to detect losses Linux kernel เริ่มใช้ RACK และ tcp_recovery (Linux 4.4) ตอนแรกทำงานเป็นตัวเสริมของวิธีเดิม The /proc Filesystem Linux kernel OOM killer เลือกโปรเซสที่จะปิดจากคะแนน (badness) ที่คิดจากสัดส่วนการใช้หน่วยความจำ และปรับได้ด้วย oom_score_adj The kernel’s command-line parameters Linux kernel mitigations=: off ปิดการป้องกันช่องโหว่ CPU ทั้งหมดเพื่อเพิ่มประสิทธิภาพแต่จะเสี่ยงต่อช่องโหว่, ค่าเริ่มต้น auto ป้องกันโดยเปิด SMT ไว้, auto,nosmt ปิด SMT เมื่อจำเป็น Thin-streams and TCP Linux kernel ใช้ TCP_THIN_LINEAR_TIMEOUTS ปิด exponential backoff เฉพาะการเชื่อมต่อแบบ thin stream ได้ tools/power/cpupower/man/cpupower-monitor.1 (Linux v6.12) Linux kernel cpupower monitor: สถิติความถี่และโหมดประหยัดพลังงานแยกตามคอร์ Transparent Hugepage Support Linux kernel ถ้า defrag=always เมื่อจัดสรร THP ไม่สำเร็จจะ reclaim และ compaction หน่วยความจำทันทีตรงนั้นและหยุดรอ, madvise จะทำแบบนั้นเฉพาะส่วนที่ร้องขอ What is NUMA? Linux kernel หน่วยความจำใน cell เดียวกันเร็วกว่าและมีแบนด์วิดท์สูงกว่า ส่วนหน่วยความจำใน cell อื่น (remote) เข้าถึงช้ากว่า
IETF 59 RFC 1191: Path MTU discovery IETF path MTU discovery: แพ็กเก็ตที่ใหญ่เกินจะได้รับแจ้งด้วย ICMP “fragmentation needed and DF set” (type 3 code 4) RFC 1812: Requirements for IP Version 4 Routers IETF เราเตอร์ต้องจำกัดความถี่ในการส่งข้อความ ICMP error เช่น Time Exceeded ได้ และจำกัด Echo Reply ได้ด้วย (ระวังเวลาตีความผล mtr และ ping) RFC 2018: TCP Selective Acknowledgment Options IETF ถ้าไม่มี SACK และมีแค่ cumulative ACK จะรู้ได้แค่แพ็กเก็ตที่หายหนึ่งตัวต่อรอบไปกลับ RFC 2475: An Architecture for Differentiated Services IETF นิยามว่า shaping หน่วงแพ็กเก็ตให้เข้ากับ traffic profile ส่วน policing ทิ้งแพ็กเก็ตที่เกิน profile RFC 2544: Benchmarking Methodology for Network Interconnect Devices IETF ต้องทดสอบประสิทธิภาพของอุปกรณ์ด้วยเฟรมหลายขนาด รวมทั้งขนาดเล็กสุดและใหญ่สุด (ประสิทธิภาพการประมวลผลเปลี่ยนไปตามขนาดแพ็กเก็ต) RFC 2697: A Single Rate Three Color Marker IETF token bucket: ตัดสินด้วยอัตราเฉลี่ย (CIR) และขนาด burst ที่ยอมให้ในครั้งเดียว (CBS) RFC 2863: The Interfaces Group MIB IETF ifOutDiscards: จำนวนแพ็กเก็ตที่ส่งออกไม่ได้และถูกทิ้งแม้ไม่มี error ด้วยเหตุผล เช่น ต้องเคลียร์พื้นที่บัฟเฟอร์ RFC 2883: An Extension to the Selective Acknowledgement (SACK) Option for TCP IETF DSACK: ฝั่งรับแจ้งว่าได้รับซ้ำ ฝั่งส่งจึงรู้ว่ามีการส่งซ้ำโดยไม่จำเป็น RFC 2923: TCP Problems with Path MTU Discovery IETF ถ้าไฟร์วอลล์บล็อก ICMP (Fragmentation Needed) การค้นหา path MTU จะล้มเหลว และแพ็กเก็ตใหญ่จะหายไปเรื่อย ๆ (black hole), ping และการสื่อสารขนาดเล็กยังใช้ได้ จึงวินิจฉัยยาก RFC 2991: Multipath Issues in Unicast and Multicast Next-Hop Selection IETF เกณฑ์แยก flow ต่างกันตามการ implement (แค่ IP ปลายทาง, คู่ IP หรือรวมถึงพอร์ต), ในเครือข่ายหลายเส้นทาง ผล ping และ traceroute เชื่อถือได้ยาก RFC 2992: Analysis of an Equal-Cost Multi-Path Algorithm IETF ECMP เลือกเส้นทางถัดไปจาก hash ของฟิลด์ใน header ที่ใช้แยก flow (flow เดียวกันไปเส้นทางเดียวกัน) RFC 3168: The Addition of Explicit Congestion Notification (ECN) to IP IETF ECN: แจ้งความแออัดด้วยการทำเครื่องหมายใน IP header แทนการทิ้งแพ็กเก็ต RFC 3449: TCP Performance Implications of Network Path Asymmetry IETF บนเน็ตแบบอสมมาตรที่อัปโหลดแคบ ถ้า ACK ช้าหรือหาย ประสิทธิภาพ TCP จะลดลง, ACK เป็นการยืนยันแบบสะสม ถ้าบางตัวหาย ACK ตัวหลังก็ยืนยันแทนได้, มาตรการอย่างการจัดลำดับให้ ACK ไปก่อน RFC 3481: TCP over Second (2.5G) and Third (3G) Generation Wireless Networks IETF เครือข่ายมือถือมีการส่งซ้ำที่ชั้น link จึงมีแพ็กเก็ตหายระดับ IP น้อย แต่การกู้คืนนั้นแสดงออกมาเป็นจิตเตอร์และความหน่วงพุ่ง RFC 3522: The Eifel Detection Algorithm for TCP IETF ใช้ timestamps แยกแยะย้อนหลังว่าการกู้คืนไม่จำเป็นหรือไม่ (การย้อนคืน congestion window ในการจำลอง) RFC 3550: RTP, A Transport Protocol for Real-Time Applications IETF นิยามและวิธีคำนวณจิตเตอร์ของช่วงเวลาที่แพ็กเก็ตมาถึง (interarrival jitter) RFC 3635: Definitions of Managed Objects for the Ethernet-like Interface Types IETF เฟรมที่ไม่ผ่านการตรวจเฟรม (FCS) จะนับเป็น FCS error (dot3StatsFCSErrors) และรวมไว้ใน input error (ifInErrors) RFC 4271: A Border Gateway Protocol 4 (BGP-4) IETF ค่าเริ่มต้นที่แนะนำของ BGP hold time คือ 90 วินาที (ถ้าไม่ได้รับข้อความจากอีกฝั่งในช่วงนี้ จะตัดเซสชัน) RFC 4459: MTU and Fragmentation Issues with In-the-Network Tunneling IETF fragmentation และปัญหา path MTU ที่เกิดจากขนาดที่ส่งได้ลดลงเพราะเฮดเดอร์ encapsulation ของ tunnel กลางทาง RFC 4594: Configuration Guidelines for DiffServ Service Classes IETF แยกทราฟฟิกแบบโต้ตอบเรียลไทม์อย่างเกม กับการส่งข้อมูลขนาดใหญ่อย่างการสำรองข้อมูล ไว้คนละ service class RFC 4787: Network Address Translation (NAT) Behavioral Requirements for Unicast UDP IETF ตัวจับเวลาของ UDP mapping ต้องไม่หมดก่อน 2 นาที และแนะนำค่าเริ่มต้นตั้งแต่ 5 นาทีขึ้นไป การต่ออายุด้วยแพ็กเก็ตขาออกจากข้างในเป็นข้อบังคับ ส่วนการต่ออายุด้วยแพ็กเก็ตขาเข้าจากข้างนอกเป็นทางเลือก RFC 4821: Packetization Layer Path MTU Discovery IETF วิธีที่ชั้น transport ค้นหาขนาดแพ็กเก็ตเองโดยไม่ใช้ ICMP (พื้นฐานของ tcp_mtu_probing ใน Linux) RFC 5280: Internet X.509 Public Key Infrastructure Certificate and Certificate Revocation List (CRL) Profile IETF อายุของใบรับรองคือตั้งแต่ notBefore ถึง notAfter, การตรวจ path จะตรวจว่าเวลาปัจจุบันอยู่ในช่วงอายุของใบรับรองทุกใบใน chain หรือไม่ (ถ้านาฬิกาฝั่งที่ตรวจผิดก็จะล้มเหลว) RFC 5382: NAT Behavioral Requirements for TCP IETF คำแนะนำว่า idle timeout ของการเชื่อมต่อใน TCP NAT ต้องไม่น้อยกว่า 2 ชั่วโมง 4 นาที (ตั้งอยู่บนสมมติฐานว่าอุปกรณ์อาจลบเซสชันที่ idle ไปก่อน) RFC 5482: TCP User Timeout Option IETF TCP user timeout: ข้อมูลที่ส่งไปยังไม่ได้รับการยืนยันนานเท่าไรจึงจะปิดการเชื่อมต่อ RFC 5681: TCP Congestion Control IETF ตรวจพบแพ็กเก็ตหายจาก duplicate ACK 3 ตัวแล้วทำ fast retransmit ถ้าไม่ใช่ก็รอตัวจับเวลาส่งซ้ำ RFC 5682: Forward RTO-Recovery (F-RTO): An Algorithm for Detecting Spurious Retransmission Timeouts with TCP IETF F-RTO: ใช้ ACK ที่มาหลัง RTO แยกแยะว่าเป็น RTO ที่ไม่จำเป็นหรือไม่ RFC 5798: Virtual Router Redundancy Protocol (VRRP) Version 3 for IPv4 and IPv6 IETF VRRP ส่ง advertisement ทุก 1 วินาทีเป็นค่าเริ่มต้น ถ้า advertisement ขาดไปนานกว่าราว 3 เท่าของช่วงนั้น อุปกรณ์สำรองจะรับบทบาทแทน (ถ้าใช้ค่าเริ่มต้นจะเป็นราว 3 วินาทีเศษ) RFC 5880: Bidirectional Forwarding Detection (BFD) IETF วิธี Hello ของโปรโตคอล routing ใช้เวลาตรวจพบความเสียหายเกิน 1 วินาที จึงมี BFD ที่สร้างขึ้นเพื่อตรวจพบได้เร็วกว่านั้น RFC 5905: Network Time Protocol Version 4: Protocol and Algorithms Specification IETF วิธีคำนวณดีเลย์ไปกลับและค่าคลาดเคลื่อนของนาฬิกาจากเวลาสี่จุดของคำขอและการตอบกลับ RFC 6269: Issues with IP Address Sharing IETF เมื่อหลายคนใช้ IP ร่วมกัน การบล็อกตาม IP (penalty box) จะบล็อกผู้ใช้บริการคนอื่นที่ใช้ IP เดียวกันไปด้วย RFC 6298: Computing TCP's Retransmission Timer IETF backoff ที่เพิ่มเวลารอเป็นสองเท่าทุกครั้งที่ตัวจับเวลาส่งซ้ำหมดเวลา RFC 6598: IANA-Reserved IPv4 Prefix for Shared Address Space IETF 100.64.0.0/10 คือช่วง IP ร่วมที่ใช้ระหว่างอุปกรณ์ NAT ของ ISP (CGN) กับเราเตอร์ของผู้ใช้บริการ RFC 6675: A Conservative Loss Recovery Algorithm Based on Selective Acknowledgment (SACK) for TCP IETF การกู้คืนที่ใช้ข้อมูล SACK ตัดสินแพ็กเก็ตที่ขาดหาย (สัญญาณ duplicate ACK และ SACK สำหรับ fast retransmit) RFC 6888: Common Requirements for Carrier-Grade NATs (CGNs) IETF CGN ต้องรองรับการจำกัดจำนวนพอร์ตภายนอกต่อผู้ใช้บริการ และการจำกัดอัตราการสร้าง mapping ใหม่ RFC 6928: Increasing TCP's Initial Window IETF initial window 10 segment, สูงสุด 14,600 ไบต์ RFC 6937: Proportional Rate Reduction for TCP IETF PRR: ลดปริมาณที่ส่งระหว่างกู้คืนให้สอดคล้องกับปริมาณที่ส่งถึงใหม่ (เพดานการส่งระหว่างกู้คืนในการจำลอง) RFC 7323: TCP Extensions for High Performance IETF ถ้าไม่มี option window scaling window จะใหญ่สุด 2^16 = 64 KiB RFC 7424: Mechanisms for Optimizing Link Aggregation Group (LAG) and Equal-Cost Multipath (ECMP) Component Link Utilization in Networks IETF LAG และ ECMP เลือกลิงก์หนึ่งเส้นให้แต่ละ flow ด้วย hash ของฟิลด์ในเฮดเดอร์เพื่อรักษาลำดับแพ็กเก็ต (flow→ลิงก์ แบบหลายต่อหนึ่ง) RFC 7567: IETF Recommendations Regarding Active Queue Management IETF ถ้าข้อมูลที่เข้ามาในอุปกรณ์มากกว่าความเร็วที่ส่งออกได้ คิวจะสะสม และคิวที่มากเกินไปเป็นสาเหตุหลักของความหน่วง RFC 768: User Datagram Protocol IETF UDP ไม่รับประกันการส่งถึงและการป้องกันข้อมูลซ้ำ RFC 7871: Client Subnet in DNS Queries IETF DNS ที่ตอบต่างกันตามตำแหน่งจะเดาตำแหน่งจากที่อยู่ของ resolver ที่ส่งคำถามมา และถ้าใช้ resolver ส่วนกลางที่อยู่ไกลจากผู้เล่น จะได้คำตอบที่ไม่เหมาะสม ส่งที่อยู่บางส่วนของผู้เล่นต่อไปด้วย EDNS Client Subnet (ฟีเจอร์ทางเลือก) RFC 7938: Use of BGP for Routing in Large-Scale Data Centers IETF ถ้าพึ่งแค่ BGP keepalive การ converge จะช้า ถ้ารับสัญญาณลิงก์ล่มทันทีแล้วตัดเซสชัน จะตรวจพบได้ในระดับ ms และ converge ใหม่ RFC 7999: BLACKHOLE Community IETF BLACKHOLE community ที่ใช้ BGP แจ้ง ISP ข้างเคียงให้ทิ้งทราฟฟิกที่ไปยัง IP หนึ่ง ๆ RFC 8085: UDP Usage Guidelines IETF ถ้า fragment หายหนึ่งชิ้น จะประกอบกลับไม่ได้และเสียทั้งแพ็กเก็ต, แอป UDP ควรเลี่ยง IP fragmentation RFC 8289: Controlled Delay Active Queue Management IETF เป้าหมายเวลารอของ CoDel 5 ms และช่วงสังเกต 100 ms (คิว SQM ราว 5 ms ในการทดลอง) RFC 8290: The Flow Queue CoDel Packet Scheduler and Active Queue Management Algorithm IETF fq_codel: ใช้คิวแยกตาม flow และ AQM รักษาคิวให้สั้นเพื่อลด bufferbloat RFC 8305: Happy Eyeballs Version 2: Better Connectivity Using Concurrency IETF IP หรือเวอร์ชันของ IP (IPv4/IPv6) อาจถูกบล็อก เสีย หรือช้า ขึ้นอยู่กับเครือข่าย, ลอง IPv6 ก่อน แล้วรอค่าแนะนำ 250 ms ก่อนเริ่มเชื่อมต่อครั้งถัดไป RFC 8325: Mapping Diffserv to IEEE 802.11 IETF CSMA/CA ของ 802.11: ส่งเฉพาะตอนช่องสัญญาณว่าง ถ้าไม่ว่างจะเลื่อนไปจนว่าง แล้วรอเพิ่มอีกตามช่วง backoff แบบสุ่ม RFC 8767: Serving Stale Data to Improve DNS Resiliency IETF วิธีใช้ระเบียนในแคชที่หมดอายุแล้วต่อไปเมื่อติดต่อเซิร์ฟเวอร์ authoritative ไม่ได้ เพื่อให้ผ่านช่วงขัดข้องไปได้ (serve-stale) RFC 8899: Packetization Layer Path MTU Discovery for Datagram Transports IETF แนะนำ 1,200 ไบต์เป็นขนาดปลอดภัยพื้นฐาน (BASE_PLPMTU) สำหรับการส่งแบบ datagram เช่น UDP RFC 8900: IP Fragmentation Considered Fragile IETF กรณีที่ไฟร์วอลล์และเครือข่ายบางแห่งทิ้ง IP fragment RFC 8952: Captive Portal Architecture IETF captive portal: เครือข่ายที่จำกัดการเชื่อมต่อจนกว่าจะทำตามเงื่อนไข เช่น ยอมรับข้อตกลงหรือยืนยันตัวตน RFC 896: Congestion Control in IP/TCP Internetworks IETF จุดประสงค์เดิมของกฎ Nagle: ปัญหา remote terminal ที่กดแป้นแต่ละครั้ง (1 ไบต์) ต้องส่งแพ็กเก็ต 41 ไบต์ออกไป RFC 8985: The RACK-TLP Loss Detection Algorithm for TCP IETF นิยามของ RACK (ตัดสินการหายตามเวลา) และ TLP (ส่งแพ็กเก็ตท้ายสุดซ้ำ) RFC 9000: QUIC: A UDP-Based Multiplexed and Secure Transport IETF connection ID ทำให้การเชื่อมต่อคงอยู่แม้ IP address และพอร์ตเปลี่ยน (บทที่ 9) โหลดบาลานเซอร์ที่กระจายโหลดด้วยที่อยู่และพอร์ตอย่างเดียว อาจส่งแพ็กเก็ตที่มาจากที่อยู่ใหม่ไปยังเซิร์ฟเวอร์อื่น (หัวข้อ 5.2.3) RFC 9293: Transmission Control Protocol (TCP) IETF การเชื่อมต่อ TCP ระบุด้วยคู่ซ็อกเก็ต (ที่อยู่และพอร์ต) ของปลายทั้งสองฝั่ง RFC 9308: Applicability of the QUIC Transport Protocol IETF บนอินเทอร์เน็ตที่มี NAT อยู่ในเส้นทาง keep-alive ทุกราว 30 วินาทีกำลังพอดี ถี่กว่านั้นจะเปลืองทราฟฟิกและพลังงาน RFC 9438: CUBIC for Fast and Long-Distance Networks IETF เมื่อแพ็กเก็ตหาย CUBIC ลด window เหลือ 0.7 เท่า (ลด 30%) ส่วน Reno เหลือ 0.5 เท่า, CUBIC เป็นค่าเริ่มต้นของ Linux, Windows และ Apple
AWS 51 Amazon CloudWatch metrics for Amazon EBS AWS VolumeQueueLength (จำนวนคำขอที่รอให้เสร็จ), VolumeAvgWriteLatency (ดีเลย์การเขียนเฉลี่ยราย 1 นาที, อินสแตนซ์ Nitro) Amazon CloudWatch metrics for Amazon EC2 Auto Scaling AWS group metrics ต้องเปิดก่อนจึงเผยแพร่ทุก 1 นาที, GroupDesiredCapacity (จำนวนที่ต้องการรักษาไว้), GroupPendingInstances (จำนวนอินสแตนซ์ที่ยังไม่เริ่มให้บริการ), GroupInServiceInstances (จำนวนอินสแตนซ์ที่กำลังให้บริการ) Amazon CloudWatch metrics for Amazon RDS AWS FreeStorageSpace: พื้นที่จัดเก็บที่เหลือของอินสแตนซ์ DB Amazon EBS fast snapshot restore AWS fast snapshot restore ให้ volume ที่ initialize แล้วตั้งแต่ตอนสร้าง จึงไม่มีดีเลย์ตอนเข้าถึงครั้งแรก Amazon EBS General Purpose SSD volumes AWS ความหน่วงของดิสก์คลาวด์พื้นฐาน (gp3) อยู่ในระดับหลักหน่วย ms Amazon EBS-optimized instance types AWS บางอินสแตนซ์คงประสิทธิภาพ EBS สูงสุดได้เพียง 30 นาทีครั้งเดียวใน 24 ชั่วโมง จากนั้นกลับไปที่ประสิทธิภาพพื้นฐาน Amazon EC2 Auto Scaling lifecycle hooks AWS ตอนขยายหรือลดขนาด จะพักอินสแตนซ์ไว้ในสถานะรอเพื่อทำงานเตรียมและเก็บกวาดให้เสร็จ (ค่าเริ่มต้นนานสุด 1 ชั่วโมง) Amazon EC2 instance network bandwidth AWS “สูงสุด N Gbps” ของอินสแตนซ์ที่มีไม่เกิน 16 vCPU คือ burst ที่ใช้เครดิต network I/O (ปกติ 5–60 นาที) เมื่อเครดิตหมดจะกลับไปที่แบนด์วิดท์พื้นฐาน Amazon EC2 security group connection tracking AWS ถ้าเกินจำนวนการเชื่อมต่อที่ติดตามได้ต่ออินสแตนซ์ แพ็กเก็ตของการเชื่อมต่อใหม่จะถูกทิ้ง, การเชื่อมต่อที่ idle อาจทำให้ตารางติดตามเต็ม Amazon GameLift Servers UDP ping beacons AWS ไคลเอนต์เกมวัดความหน่วงด้วย UDP endpoint ที่มีในแต่ละตำแหน่งโฮสต์ แล้วใช้ในการวางเซิร์ฟเวอร์และจับคู่, ใกล้เคียงทราฟฟิกเกมจริงมากกว่า ICMP ping Amazon RDS event categories and event messages AWS RDS-EVENT-0013: เริ่ม Multi-AZ failover, RDS-EVENT-0049: Multi-AZ failover เสร็จ Avoiding insurmountable queue backlogs AWS Amazon Builders' Library มอนิเตอร์ backlog ด้วยอายุของข้อความที่รออยู่, ระบบเรียลไทม์ประมวลผลข้อมูลใหม่ก่อน (ใกล้เคียง LIFO), บางครั้งทิ้งข้อความเก่า CloudWatch metrics for your Application Load Balancer AWS TargetResponseTime (เวลาตั้งแต่คำขอออกจากโหลดบาลานเซอร์จนถึง target เริ่มตอบ), HTTPCode_Target_5XX_Count (จำนวน 5xx ที่ target ส่งกลับ), UnHealthyHostCount (จำนวน target ที่ผิดปกติ) CloudWatch metrics for your Network Load Balancer AWS TCP_ELB_Reset_Count: จำนวนแพ็กเก็ต RST ที่โหลดบาลานเซอร์สร้างและส่งออกไป CloudWatch metrics that are available for your instances AWS NetworkPacketsOut (จำนวนแพ็กเก็ตที่อินสแตนซ์ส่งออกทาง network interface ทั้งหมด) และ NetworkOut (จำนวนไบต์ที่ส่ง) Control subnet traffic with network access control lists AWS network ACL ไม่เก็บสถานะ (ไม่มี connection tracking) จึงต้องเขียนกฎอนุญาตทราฟฟิกขากลับแยกไว้ด้วย Create a player latency policy AWS วางไว้ในตำแหน่งที่ความหน่วงเฉลี่ยของผู้เล่นทุกคนต่ำที่สุด แต่ผู้เล่นที่ความหน่วงสูงแบบสุดโต่งก็ถูกวางด้วย, ตัวอย่างนโยบายที่ขยายเพดานปิงจาก 50 ms เป็น 100 ms และ 200 ms Decrease latency for applications with long boot times using warm pools AWS แอปที่บูตนานใช้ pool ของอินสแตนซ์ที่ initialize ไว้ล่วงหน้า (warm pool) เพื่อลดเวลาที่ใช้ขยาย Edit attributes for your Application Load Balancer AWS idle timeout ของ ALB ค่าเริ่มต้น 60 วินาที (1–4,000 วินาที) ถ้าการเชื่อมต่อฝั่งไคลเอนต์หรือฝั่ง target เงียบตลอดช่วงนี้ โหลดบาลานเซอร์จะปิดการเชื่อมต่อ Edit target group attributes for your Network Load Balancer AWS เมื่อ deregister target จะไม่ส่งการเชื่อมต่อใหม่ไปให้ และ drain การเชื่อมต่อเดิม (ค่าเริ่มต้น 300 วินาที) Exponential Backoff And Jitter AWS exponential backoff อย่างเดียวยังทำให้การลองใหม่กระจุกกัน ต้องผสมความสุ่ม (jitter) จึงจะลดการแย่งกัน (วิธีลองใหม่ในการจำลอง) Failing over a Multi-AZ DB instance for Amazon RDS AWS Multi-AZ failover ปกติใช้ 60–120 วินาที, หลัง failover ต้องเชื่อมต่อใหม่ และแนะนำให้ตั้ง TTL ของ DNS cache ใน JVM ไม่เกิน 60 วินาที FlexMatch rule types AWS กฎความหน่วง (maxLatency) ดูความหน่วงของผู้เล่นแยกตามตำแหน่ง, ปาร์ตี้ใช้ค่าเฉลี่ยของสมาชิก (partyAggregation avg) เป็นค่าเริ่มต้น, คิวอาจวางไปรีเจียนที่ไม่ตรงกฎความหน่วงก็ได้ Flow log records AWS srcaddr ใน record ของ VPC flow log: ถ้าเป็นทราฟฟิกขาเข้า คือ IP ของฝั่งผู้ส่ง Health checks for Network Load Balancer target groups AWS ค่าเริ่มต้นของ health check คือทุก 30 วินาที และถ้าล้มเหลว 2 ครั้งจะถูกถอดออก, บริการ UDP ตรวจด้วย health check แบบ TCP หรือ HTTP จึงแนะนำให้ตั้งค่าให้สะท้อนสถานะจริงของบริการ High availability for Amazon Aurora AWS ระหว่างขัดข้อง การอ่านและเขียนล้มเหลว ปกติกลับมาภายใน 60 วินาที (ส่วนใหญ่ภายใน 30 วินาที) How Amazon Route 53 uses EDNS0 to estimate the location of a user AWS ถ้า resolver ไม่รองรับ edns-client-subnet จะเดาตำแหน่งผู้เล่นจากที่อยู่ของ resolver และตอบตามตำแหน่งของ resolver (เหมือนกันทั้ง routing แบบอิงตำแหน่งและแบบอิงความหน่วง) How EC2 instance stop and start works AWS เมื่อหยุดแล้วเริ่มอินสแตนซ์ใหม่ ส่วนใหญ่จะถูกย้ายไปโฮสต์ใหม่ (ยกเว้น dedicated host) Infrastructure layer attacks AWS การโจมตีปริมาณมาก เช่น UDP reflection และ SYN flood ทำให้ความจุเครือข่ายล้น หรือจับทรัพยากรของไฟร์วอลล์และโหลดบาลานเซอร์ไว้ Initialize Amazon EBS volumes AWS volume ที่สร้างจากสแนปช็อตจะมีดีเลย์สูงขึ้นและประสิทธิภาพตกระหว่างดึงบล็อกจาก S3, ใช้ dd หรือ fio อ่านทุกบล็อกเพื่อ initialize ล่วงหน้า Managed certificate renewal in AWS Certificate Manager AWS ใบรับรองที่นำเข้า (import) และใบรับรองที่หมดอายุไปแล้ว ไม่อยู่ในขอบเขตการต่ออายุอัตโนมัติ Monitor network performance for ENA settings on your EC2 instance AWS conntrack_allowance_exceeded: จำนวนแพ็กเก็ตที่ถูกทิ้งเพราะเกินขีดจำกัด connection tracking ของอินสแตนซ์ ดูได้ด้วย ethtool -S NAT gateway basics AWS การเชื่อมต่อพร้อมกันไปยังปลายทางเดียวกัน (IP, พอร์ต, โปรโตคอลปลายทาง) 55,000 การเชื่อมต่อต่อ IPv4 หนึ่งตัว เพิ่มได้ด้วยการผูก IP สูงสุด 8 ตัว (Elastic IP ของ public NAT gateway ค่าเริ่มต้น 2 ตัว เพิ่มได้ด้วยการขอเพิ่มโควตา), แบนด์วิดท์ขยายเองจาก 5 Gbps ถึง 100 Gbps และปริมาณงานขยายเองจาก 1 ล้านถึง 10 ล้านแพ็กเก็ตต่อวินาที ถ้าเกินขีดนั้นแพ็กเก็ตจะถูกทิ้ง NAT gateway metrics and dimensions AWS ErrorPortAllocation: จำนวนครั้งที่จัดสรรพอร์ตต้นทางไม่ได้ (ถ้ามากกว่า 0 แปลว่าการเชื่อมต่อพร้อมกันมากเกินไป), ActiveConnectionCount, IdleTimeoutCount (การเชื่อมต่อที่ถูกเก็บกวาดเพราะ idle 350 วินาที), PacketsDropCount Network Load Balancers AWS idle timeout ของ TCP ใน NLB ค่าเริ่มต้น 350 วินาที (60–6,000 วินาที) เมื่อเลยไปจะหยุดติดตามเท่านั้น ถ้ามีข้อมูลมาหลังจากนั้นจะตอบด้วย RST, flow ของ UDP 120 วินาทีปรับไม่ได้ Network maximum transmission unit (MTU) for your EC2 instance AWS internet gateway และ VPN ใช้ MTU 1,500, PMTUD ต้องใช้ ICMP type 3 code 4 และถ้า security group หรือ network ACL บล็อกไว้จะรับไม่ได้ Obfuscating AWS resources (BP1, BP4, BP5) AWS วางบริการ edge อย่าง CloudFront หรือโหลดบาลานเซอร์ไว้หน้าเซิร์ฟเวอร์ต้นทาง เพื่อลดการเปิดเผยโดยตรง Processor state control for Amazon EC2 Linux instances AWS มีเพียงอินสแตนซ์บางประเภทที่ OS ควบคุม C-state และ P-state ได้ และปรับเพื่อลดความหน่วงได้, ค่าเริ่มต้นเป็นประสิทธิภาพสูงสุดซึ่งเหมาะกับงานส่วนใหญ่, Graviton ใช้ความถี่คงที่ OS จึงไม่ได้ควบคุม REL05-BP01 Implement graceful degradation to transform applicable hard dependencies into soft dependencies AWS AWS Well-Architected ออกแบบให้ฟีเจอร์หลักยังทำงานต่อได้ด้วยข้อมูลที่เก่าไปเล็กน้อยหรือข้อมูลทดแทน แม้ระบบที่พึ่งพาอยู่จะขัดข้อง Renewal for domains validated by DNS AWS 45 วันก่อนหมดอายุ จะตรวจว่าใบรับรองถูกใช้งานอยู่ในเซอร์วิสของ AWS และมี CNAME record สำหรับการยืนยันหรือไม่ แล้วต่ออายุอัตโนมัติ ถ้ายืนยันไม่ได้จะแจ้งเตือนเมื่อเหลือ 30, 15, 7, 3 และ 1 วันก่อนหมดอายุ Scheduled events for Amazon EC2 instances AWS ประเภทของ scheduled event (system-reboot คือรีบูตพร้อมย้ายไปโฮสต์ใหม่, system-maintenance คือได้รับผลกระทบชั่วครู่จากการซ่อมบำรุงเครือข่ายหรือไฟฟ้า), แจ้งทางอีเมลและ AWS Health, ดูได้ด้วย describe-instance-status, บางประเภทปรับเวลาได้ Scheduled scaling for Amazon EC2 Auto Scaling AWS เพิ่มและลด capacity ล่วงหน้าตามเวลาที่กำหนด ให้ตรงกับการเปลี่ยนแปลงของโหลดที่คาดการณ์ได้ Standard mode for burstable performance instances AWS อินสแตนซ์แบบ burstable ใช้เครดิตเพื่อทำงานเกินประสิทธิภาพพื้นฐาน และเมื่อเครดิตหมด อัตราการใช้ CPU จะลดลงเหลือระดับพื้นฐาน Supported CloudWatch metrics AWS DaysToExpiry: จำนวนวันที่เหลือก่อนใบรับรองหมดอายุ, เผยแพร่วันละสองครั้งจนกว่าจะหมดอายุ Target tracking scaling policies for Amazon EC2 Auto Scaling AWS เมตริกพื้นฐานของ EC2 มีช่วงห่าง 5 นาที (เปิด detailed monitoring จะเป็น 1 นาที) ถ้าต้องการตอบสนองเร็ว แนะนำเมตริกที่มีช่วงห่างไม่เกิน 1 นาที The Unique Architecture behind Amazon Games’ Seamless MMO New World AWS New World ให้ไคลเอนต์เชื่อมต่อเข้าเซิร์ฟเวอร์ทางเข้า (REP) ที่มี public IP ตัวใดตัวหนึ่งจาก 4 ตัว แล้วจึงสื่อสารกับเซิร์ฟเวอร์ simulation (hub) ที่อยู่ด้านหลัง Timeouts, retries, and backoff with jitter AWS Amazon Builders' Library เพิ่ม jitter ให้ตัวจับเวลา งานตามรอบ และงานที่หน่วงเวลาไว้ทุกตัว เพื่อกระจายโหลดที่จะมารวมกันในเวลาเดียวกัน, กรณีที่คำขอรอบ 1 นาทีจากเซิร์ฟเวอร์หลายเครื่องมากระจุกในไม่กี่วินาทีแรกของทุกนาที Troubleshoot NAT gateways AWS ถ้า idle 350 วินาที การเชื่อมต่อจะหมดอายุ และถ้าส่งต่อจะได้ RST กลับ, แนะนำ keepalive ที่สั้นกว่า 350 วินาที, ถ้าชนขีดจำกัดการเชื่อมต่อ ให้แยก gateway ตาม availability zone, เพิ่ม IP หรือลดจำนวนการเชื่อมต่อ Update the TCP idle timeout for your Network Load Balancer listener AWS ถ้า idle timeout ของ NLB ยาวกว่าเวลา connection tracking ของอินสแตนซ์ปลายทาง ฝั่งอินสแตนซ์จะทิ้งสถานะการเชื่อมต่อเงียบ ๆ ไปก่อน Using rate-based rule statements in AWS WAF AWS นับจำนวนคำขอตามเกณฑ์ เช่น IP และจำกัดอัตรา (rate limit) ถ้าเกินในช่วงเวลา (time window) ที่กำหนด Working with DB instance read replicas AWS การทำสำเนาข้อมูลล่าช้าในการทดลองแผนผังสถาปัตยกรรม: read replica อัปเดตแบบ asynchronous จึงอาจอ่านได้ข้อมูลเก่า
MySQL 32 Configuring Buffer Pool Flushing MySQL เมื่อ redo log เต็มจะเกิด sharp checkpoint ทำให้ throughput ตกชั่วครู่, adaptive flushing กระจายการเขียนให้สม่ำเสมอ Deadlock Detection MySQL ถ้าทำงานพร้อมกันสูงมาก การตรวจจับเองอาจช้าลง บางครั้งจึงปิดไว้แล้วอาศัยขีดจำกัดการรอล็อกแทน EXPLAIN Output Format MySQL ถ้า type เป็น ALL คือสแกนทั้งตาราง ปกติแก้ด้วยการเพิ่มอินเด็กซ์ General Thread States MySQL Waiting for table metadata lock: สถานะของเธรดที่กำลังรอ metadata lock How MySQL Uses Indexes MySQL ถ้าไม่มีอินเด็กซ์ จะอ่านทั้งตารางตั้งแต่แถวแรก และยิ่งตารางใหญ่ต้นทุนยิ่งสูง How to Minimize and Handle Deadlocks MySQL คำแนะนำให้ทำทรานแซกชันให้เล็กและสั้น และ commit ทันทีหลังแก้ข้อมูลที่เกี่ยวข้องเพื่อลดการชนกัน InnoDB INFORMATION_SCHEMA Metrics Table MySQL ตัวนับ lock_deadlocks ใน INNODB_METRICS (เปิดใช้เป็นค่าเริ่มต้น) InnoDB Locking MySQL เมื่อทรานแซกชันหนึ่งล็อกแถว (index record) ไว้ ทรานแซกชันอื่นจะแก้แถวนั้นไม่ได้และต้องรอ InnoDB Multi-Versioning MySQL ถ้ายังมีทรานแซกชันที่อาจต้องเห็นเวอร์ชันเก่า จะทิ้ง update undo log ไม่ได้ rollback segment จึงโตขึ้น, แนะนำให้ commit บ่อย ๆ แม้เป็นทรานแซกชันที่อ่านอย่างเดียว InnoDB Standard Monitor and Lock Monitor Output MySQL LATEST DETECTED DEADLOCK: สองทรานแซกชันของเดดล็อกล่าสุด, ล็อกที่ถือและที่รอ และฝั่งที่ถูกโรลแบ็ค InnoDB Startup Options and System Variables MySQL ถ้าเปิดการตรวจจับ (ค่าเริ่มต้น) InnoDB จะตรวจพบเดดล็อกทันทีแล้วโรลแบ็ค, innodb_lock_wait_timeout ค่าเริ่มต้น 50 วินาที Locks Set by Different SQL Statements in InnoDB MySQL ถ้าไม่มีอินเด็กซ์ที่เหมาะจนต้องสแกนทั้งตาราง ทุกแถวจะถูกล็อก จนผู้ใช้อื่นเพิ่มข้อมูลไม่ได้ไปด้วย MySQL 8.0 Reference Manual: SHOW REPLICA STATUS Statement MySQL ตั้งแต่ 8.0.22 ใช้ SHOW REPLICA STATUS แทน SHOW SLAVE STATUS เวอร์ชันก่อนหน้านั้นใช้ SHOW SLAVE STATUS Online DDL Performance and Concurrency MySQL แม้เป็น online DDL ตอนจบก็ต้องใช้ exclusive metadata lock ชั่วครู่ ถ้ามีทรานแซกชันยาวจะต้องรอ และคำขอล็อกที่รออยู่จะขวางทุกทรานแซกชันที่ตามมา Performance Schema Statement Digests and Sampling MySQL events_statements_summary_by_digest จัดกลุ่มคิวรีหน้าตาเดียวกันแล้วสรุปจำนวนครั้งและเวลา Purge Configuration MySQL purge ล้างรายการ undo log ของทรานแซกชันที่ commit แล้ว (history list), ปริมาณที่กองรอแสดงเป็น History list length ในส่วน TRANSACTIONS ของ SHOW ENGINE INNODB STATUS Replica Server Options and Variables MySQL replica_parallel_workers ให้หลายเธรด apply ทรานแซกชันแบบขนาน (ค่าเริ่มต้น 4, ถ้าเป็น 0 จะใช้เธรดเดียวไล่ตามลำดับ) Saving and Restoring the Buffer Pool State MySQL เพื่อลดเวลาวอร์มหลังรีสตาร์ต จะบันทึกรายการ page ที่ใช้ล่าสุด (ค่าเริ่มต้น 25%) ตอนปิดแล้วอ่านกลับตอนเปิด, ทั้งสองอย่างเปิดเป็นค่าเริ่มต้น Semisynchronous Replication MySQL asynchronous replication ถ้า DB หลักล่ม ทรานแซกชันที่ commit แล้วอาจไม่มีบน replica, semi-synchronous ลดปัญหานี้ด้วยการรอให้ replica หนึ่งตัวยืนยันว่าได้รับแล้ว แต่ดีเลย์จะเพิ่มขึ้น Server Error Message Reference MySQL 1213 ER_LOCK_DEADLOCK (เดดล็อก), 1205 ER_LOCK_WAIT_TIMEOUT (รอล็อกเกินขีดจำกัด) Server Status Variables MySQL ดูจำนวนครั้งและเวลาที่รอ row lock จาก Innodb_row_lock_waits และ Innodb_row_lock_time และจำนวนที่กำลังรออยู่จาก Innodb_row_lock_current_waits Server System Variables MySQL lock_wait_timeout: ขีดจำกัดการรอ metadata lock, ค่าเริ่มต้น 31,536,000 วินาที (1 ปี) SHOW BINARY LOGS Statement MySQL รายการไฟล์ binary log ของเซิร์ฟเวอร์และขนาดไฟล์ (File_size) SHOW PROCESSLIST Statement MySQL Host (ที่อยู่ไคลเอนต์), Command (เซสชันที่ว่างคือ Sleep), Time, State SHOW REPLICA STATUS Statement MySQL Seconds_Behind_Source: ส่วนต่างเทียบกับเวลาที่ DB หลักบันทึกอีเวนต์ซึ่ง replica กำลัง apply อยู่ (replication lag) Statement Summary Tables MySQL events_statements_summary_by_digest: SUM_NO_INDEX_USED (จำนวนครั้งที่รันโดยไม่ใช้อินเด็กซ์) และ SUM_ROWS_EXAMINED แยกตามรูปแบบคิวรี The INFORMATION_SCHEMA INNODB_TRX Table MySQL TRX_STARTED: เวลาที่ทรานแซกชันเริ่ม The innodb_lock_waits and x$innodb_lock_waits Views MySQL คิวรีที่รออยู่ (waiting_query), เซสชันที่ขวางอยู่ (blocking_pid) และเวลาที่รอ (wait_age) The schema_table_lock_waits and x$schema_table_lock_waits Views MySQL เซสชันที่รอ metadata lock (waiting_query) และเซสชันที่ขวางอยู่ (blocking_pid) The Slow Query Log MySQL บันทึกคิวรีที่เกิน long_query_time (ค่าเริ่มต้น 10 วินาที), เลือกบันทึกคิวรีที่ไม่ใช้อินเด็กซ์แยกได้ Too many connections MySQL เมื่อใช้ max_connections ครบแล้ว การเชื่อมต่อใหม่จะถูกปฏิเสธด้วยข้อผิดพลาด Too many connections Using Replication for Backups MySQL หยุด replica แล้วสำรองข้อมูลก็ไม่กระทบการทำงานของ DB หลัก
Unity 26
PostgreSQL 25
ACM 20 A Multi-perspective Analysis of Carrier-Grade NAT Deployment (IMC 2016) ACM ระยะเวลาคง mapping ของ UDP ใน NAT ที่วัดได้อยู่ที่ 10–200 วินาที, 74% ไม่เกิน 1 นาที, ค่ามัธยฐานของ CGN คือเครือข่ายมือถือ 65 วินาที และเครือข่ายแบบมีสาย 35 วินาที A Multifaceted Look at Starlink Performance (WWW 2024) ACM Starlink จัดเส้นทางใหม่พร้อมกันทั่วโลกทุก 15 วินาที ช่วงรอยต่อนั้นความหน่วงและ throughput แกว่ง และมีช่วงขาดสั้น ๆ ไม่ถึง 1 วินาที (ไม่ได้เกิดจากการสลับดาวเทียม), ความหน่วงช่วงอุปกรณ์ผู้ใช้↔ดาวเทียม↔สถานีภาคพื้นดิน ประมาณ 40 ms A Survey and Taxonomy of Latency Compensation Techniques for Network Computer Games (ACM Computing Surveys, 2022) ACM ปรากฏการณ์ “โดนยิงทั้งที่หลบเข้ามุมแล้ว (shot around the corner)”, เพดานการย้อนเวลาของเกม FPS เชิงพาณิชย์, ข้อเสนอเทคนิคที่ไม่ย้อนเวลาถ้าฝ่ายที่ถูกยิงอยู่ในที่ปลอดภัยแล้ว An Experimental Study of Home Gateway Characteristics (IMC 2010) ACM ผลวัดเราเตอร์บ้าน 34 รุ่น: UDP mapping อยู่ได้ 30–691 วินาที ค่ามัธยฐาน 90 วินาที เกินครึ่งต่ำกว่า 2 นาที ส่วน TCP ค่ามัธยฐานราว 60 นาที An In-depth Study of LTE: Effect of Network Protocol and Application Behavior on Performance (SIGCOMM 2013) ACM ตัวจับเวลาเปลี่ยนเข้าสถานะประหยัดพลังงาน (tail) ของเครือข่าย LTE ที่วัดคือ 10 วินาที ดีเลย์ในการยกกลับจากสถานะประหยัดพลังงานมีค่ามัธยฐาน 435 ms (25–75%: 319–558 ms) ส่วน 3G ราว 1.5–2 วินาที Capacity of Ad Hoc Wireless Networks (MobiCom 2001) ACM การส่งต่อหลายทอดผ่านไร้สาย 802.11 ทำให้ node ส่งไม่ได้ระหว่างรับ และช่วงก่อนหน้ากับถัดไปรบกวนกันเอง throughput ของเส้นทางที่ส่งต่อเป็นแถวเดียวจึงลดลงได้ถึง 1/3 ตามทฤษฎี (ในการจำลองราว 1/7) Comparing Interest Management Algorithms for Massively Multiplayer Games ACM เปเปอร์ NetGames 2006 (ฉบับที่ผู้เขียนเผยแพร่เอง) วิธีวัดระยะทุกคู่รับไม่ไหวเมื่อจำนวนคนเพิ่มขึ้น และถ้าแบ่งเป็นตารางสี่เหลี่ยมจัตุรัส จะตรวจเฉพาะ 9 เซลล์โดยรอบ Data Center TCP (DCTCP) (SIGCOMM 2010) ACM สวิตช์ทั่วไปมีบัฟเฟอร์ตื้น (48 พอร์ตใช้ร่วมกัน 4 MB, พอร์ตเดียวใช้ได้ถึงราว 700 KB), ถ้าหลาย flow ไหลเข้าพอร์ตเดียวในชั่วขณะสั้น ๆ จะเกิดแพ็กเก็ตหาย Delayed Internet Routing Convergence (SIGCOMM 2000) ACM หลังเส้นทางขัดข้อง การ converge ใช้เวลาได้ถึงหลายนาที และระหว่างนั้นแพ็กเก็ตหายและความหน่วงเพิ่มขึ้น (การวัดในปี 2000) Electri-Fi Your Data: Measuring and Combining Power-Line Communications with WiFi (IMC 2015) ACM อุปกรณ์สื่อสารผ่านสายไฟ (IEEE 1901, HomePlug AV) ที่ขายในท้องตลาดส่งด้วย CSMA/CA คล้าย Wi-Fi ความไม่เป็นธรรมในช่วงเวลาสั้น ๆ อาจทำให้จิตเตอร์สูงขึ้น และคุณภาพช่องสัญญาณเปลี่ยนไปตามสัญญาณรบกวนจากเครื่องใช้ไฟฟ้าและการเปิดปิดเครื่องใช้ไฟฟ้า (ระดับไม่กี่นาทีถึงหลายชั่วโมง) High-Resolution Measurement of Data Center Microbursts (IMC 2017) ACM burst ในดาต้าเซ็นเตอร์มากกว่า 70% จบภายในหลายสิบ µs, แม้พอร์ตที่อัตราการใช้งานเฉลี่ยราว 9% ก็ยังทิ้งแพ็กเก็ตเพราะ burst Inferring Persistent Interdomain Congestion (SIGCOMM 2018) ACM ความแออัดที่เกิดซ้ำทุกวัน โดยความหน่วงสูงขึ้นทุกช่วงพีคในบางจุดเชื่อมต่อระหว่าง ISP และอัตราแพ็กเก็ตหายก็สูงขึ้นในช่วงแออัด Latency and Player Actions in Online Games (Communications of the ACM, 2006) ACM ใน EverQuest 2 ยิ่งดีเลย์มาก ดาเมจที่ตัวละครทำได้ยิ่งลดลงและการต่อสู้ยิ่งยาวขึ้น (จาก 0 เป็น 500 ms การต่อสู้ที่ใช้เวลาประมาณ 2 นาทีนานขึ้น 5 วินาที) Mile High WiFi: A First Look at In-Flight Internet Connectivity (WWW 2018) ACM วัดอินเทอร์เน็ตบนเครื่องบิน 45 ชั่วโมง: เวลาไปกลับเฉลี่ยแบบสถานีฐานภาคพื้นดิน 200 ms แบบดาวเทียม 750 ms, ค่ามัธยฐานอัตราแพ็กเก็ตหายของแบบดาวเทียม 7% Quantifying the Causes of Path Inflation (SIGCOMM 2003) ACM วิเคราะห์ ISP 65 ราย: นโยบาย peering ระหว่าง ISP และ routing ระหว่างโดเมน (inter-domain) ทำให้เส้นทางยาวขึ้นมาก Quantifying The Cost of Context Switch (ExpCS 2007) ACM ต้นทุนทางตรงของ context switch ประมาณ 3.8 µs, ต้นทุนทางอ้อมรวมผลต่อแคชตั้งแต่ไม่กี่ µs ถึงมากกว่า 1,000 µs (ตามสภาพแวดล้อมที่วัด) The Internet at the Speed of Light (HotNets 2014) ACM เส้นทางจริงที่ผ่านเราเตอร์ยาวกว่าไฟเบอร์ที่ลากเป็นเส้นตรงประมาณ 1.5 เท่า (ค่ามัธยฐาน) และมีกรณีที่แพ็กเก็ตระหว่างสองจุดที่อยู่ใกล้กันวิ่งอ้อมไปอีกฟากโลก (hairpinning) The QUIC Transport Protocol: Design and Internet-Scale Deployment (SIGCOMM 2017) ACM ปี 2016: ไคลเอนต์ 4.4% ใช้ QUIC (UDP) ไม่ได้ (UDP หรือ QUIC ถูกบล็อก หรือ path MTU เล็ก ส่วนใหญ่อยู่หลังไฟร์วอลล์ขององค์กร และไม่พบ ISP ที่บล็อกทั้งเครือข่าย), 0.3% อยู่ในเครือข่ายที่ดูเหมือนจำกัดความเร็ว UDP (แพ็กเก็ตหายเพิ่มในช่วงพีค หลังขอให้ ISP แก้ไขก็ลดลงจาก 1% ในปี 2015), กรณีไฟร์วอลล์ที่หลัง 1 บิตในเฮดเดอร์เปลี่ยน ก็ปล่อยผ่านแค่ไม่กี่แพ็กเก็ตแรกแล้วบล็อกที่เหลือ ทำให้ลอจิกสำรองไปใช้ TCP ใช้การไม่ได้ Understanding and Mitigating Packet Corruption in Data Center Networks (SIGCOMM 2017) ACM สาเหตุหลักของแพ็กเก็ตเสียหายคือโมดูลออปติกเสีย, ไฟเบอร์เสียหาย, ขั้วต่อสกปรก และการติดตั้งผิด อัตราแพ็กเก็ตหายจากความเสียหายคงที่ไม่ว่าปริมาณการใช้งานจะเป็นเท่าไร Understanding Operational 5G: A First Measurement Study on Its Coverage, Performance and Energy Consumption (SIGCOMM 2020) ACM ดีเลย์ handover ที่วัดจริงบนเครือข่ายเชิงพาณิชย์: 4G↔4G เฉลี่ย 30 ms, ระหว่างเซลล์ 5G (NSA) เฉลี่ย 108 ms
Epic Games 19
Android (Google) 17 Android common kernels Android (Google) รองรับ common kernel 5.10–6.18 ไปพร้อมกัน และใช้เคอร์เนลของแพลตฟอร์มก่อนหน้า (เช่น android14-6.1) กับการวางจำหน่ายหรืออัปเกรดเครื่อง Android รุ่นใหม่ได้ ApplicationExitInfo Android (Google) REASON_LOW_MEMORY: low memory killer ของระบบปิดโปรเซสของแอป (เครื่องที่ไม่รองรับจะรายงานเป็น REASON_SIGNALED/SIGKILL) Cached apps freezer Android (Google) Android 14 ขึ้นไปจะแช่แข็งโปรเซสของแอปที่เข้าสู่สถานะ cached หลังผ่านไป 10 วินาที เมื่อถูกแช่แข็ง ทุกเธรดจะหยุด Crashes Android (Google) แครชคือการที่แอปปิดตัวโดยไม่คาดคิดเพราะ exception หรือ signal ที่ไม่ได้จัดการ (เช่น SIGSEGV) รวบรวมได้จาก Android vitals ใน Play Console Frame Pacing library Android (Google) บนจอ 60 Hz ถ้าไม่มีเฟรมใหม่จะแสดงเฟรมก่อนหน้าซ้ำ ตัวอย่างเกม 30 FPS ที่เฟรมไทม์แกว่งไม่สม่ำเสมอ เช่น 49, 16, 33 ms Memory allocation among processes Android (Google) Android ประคองไว้ด้วยการบีบอัดหน่วยความจำลง zRAM ถ้าไม่พอ low memory killer จะปิดโปรเซส ถ้าแอปที่เปิดอยู่บนหน้าจอถูกปิดจะดูเหมือนแครช Network security configuration Android (Google) ถ้าใช้ certificate pinning ต้องใส่คีย์สำรองไว้ด้วยเผื่อการเปลี่ยนคีย์หรือเปลี่ยน CA ไม่อย่างนั้นการเชื่อมต่อจะถูกตัดจนกว่าจะอัปเดตแอป Optimize network access Android (Google) ดีเลย์การเปลี่ยนสถานะวิทยุและเวลา tail ต่างกันไปตามเทคโนโลยีไร้สาย (3G, LTE, 5G) และการตั้งค่าของค่ายมือถือ ตัวอย่าง 3G: จากพลังงานต่ำไปพลังงานสูงสุดราว 1.5 วินาที จาก idle ไปพลังงานสูงสุดเกิน 2 วินาที Read network state Android (Google) เมื่อ default network เปลี่ยน การเชื่อมต่อใหม่จะไปทางเครือข่ายใหม่ และการเชื่อมต่อบนเครือข่ายเดิมสุดท้ายจะถูกตัด ตรวจจับการสลับได้ด้วย registerDefaultNetworkCallback Security with network protocols Android (Google) ถ้าเซิร์ฟเวอร์ส่งมาโดยไม่มีใบรับรองกลาง แอป Android จะล้มเหลวด้วย SSLHandshakeException แต่เบราว์เซอร์บน PC อาจไม่ error เพราะเติมด้วยใบรับรองกลางที่เคยได้รับไว้, ตรวจ chain ที่เซิร์ฟเวอร์ส่งด้วย openssl s_client Slow rendering Android (Google) ต้องวาดหนึ่งเฟรมให้เสร็จภายใน 16 ms จึงจะได้ 60 FPS ถ้าช้ากว่านั้นเฟรมจะถูกข้ามและเห็นเป็นอาการกระตุก (jank) Slow Sessions (games only) Android (Google) Android vitals ถือว่าเฟรมของเกมที่เกิน 50 ms (20 FPS) หรือ 34 ms (30 FPS) เป็นเฟรมช้า TelephonyDisplayInfo Android (Google) OVERRIDE_NETWORK_TYPE_NR_NSA: สัญลักษณ์เครือข่ายเมื่อเชื่อมต่อ LTE อยู่และสามารถเชื่อมต่อคู่ (EN-DC) กับ 5G (NR) ได้หรือเชื่อมต่ออยู่ Thermal API Android (Google) อุปกรณ์รักษาประสิทธิภาพสูงไว้ได้แค่ช่วงเวลาจำกัด แล้วจะถูก throttle เพราะความร้อน แนะนำให้ดูสถานะความร้อนแล้วลดโหลดล่วงหน้า Wi-Fi low-latency mode Android (Google) โหมด low latency จะปิดการประหยัดพลังงานของ Wi-Fi ส่วนการปรับแต่งการค้นหาและ roaming ขึ้นกับการ implement ของผู้ผลิตเครื่อง WifiManager Android (Google) WIFI_MODE_FULL_LOW_LATENCY (API 29, Android 10): Wi-Fi lock แบบความหน่วงต่ำที่มีผลเฉพาะเมื่อเชื่อมต่อ AP อยู่ จอเปิดอยู่ และแอปอยู่เบื้องหน้า Window.setPreferMinimalPostProcessing Android (Google) หน้าต่างที่ดีเลย์สำคัญอย่างเกมจะขอให้จอประมวลผลภาพน้อยที่สุด ถ้าเชื่อมต่อผ่าน HDMI จะส่งสัญญาณ ALLM และ Game Content Type เพื่อสลับทีวีเป็นโหมด low latency
Linux man-pages 15 accept(2) — Linux manual page Linux man-pages เมื่อโปรเซสแตะขีดจำกัด fd แล้ว accept จะล้มเหลวด้วย EMFILE clock_gettime(2) — Linux manual page Linux man-pages CLOCK_MONOTONIC ไม่ได้รับผลจากการกระโดดแบบไม่ต่อเนื่องของนาฬิการะบบและไม่ถอยหลัง connect(2) — Linux manual page Linux man-pages EADDRNOTAVAIL: เปิดการเชื่อมต่อไม่ได้เพราะพอร์ตทั้งหมดในช่วง ephemeral port ถูกใช้อยู่ core(5) — Linux manual page Linux man-pages RLIMIT_CORE กำหนดเพดานขนาดไฟล์ core, coredump_filter เลือกส่วนของหน่วยความจำที่จะเก็บ, ส่ง core dump ผ่าน pipe ไปให้โปรแกรมจัดการแยก epoll(7) — Linux manual page Linux man-pages การแจ้งเหตุการณ์ I/O ที่ขยายให้เฝ้าดู fd จำนวนมากพร้อมกันได้ fsync(2) — Linux manual page Linux man-pages fsync ส่งข้อมูลที่เปลี่ยนแปลงลงไปถึงดิสก์ (รวมแคชของดิสก์) และบล็อกจนกว่าอุปกรณ์จะแจ้งว่าเสร็จ getrlimit(2) — Linux manual page Linux man-pages RLIMIT_NOFILE: ขีดจำกัดจำนวน fd ที่โปรเซสเปิดได้ ถ้าเกินจะได้ EMFILE listen(2) — Linux manual page Linux man-pages ถ้า backlog ของ listen เกิน somaxconn จะถูกตัดเงียบ ๆ, somaxconn ค่าเริ่มต้น 4,096 (ตั้งแต่ 5.4 ก่อนหน้านั้น 128), เมื่อคิวเต็มอาจเพิกเฉยต่อคำขอแล้วปล่อยให้ไคลเอนต์ลองใหม่เอง mallopt(3) — Linux manual page Linux man-pages glibc malloc สร้าง arena ได้ถึงจำนวนที่เป็นพหุคูณของจำนวน CPU เพื่อลดการแย่งกันระหว่างเธรด และยิ่งมี arena มาก หน่วยความจำยิ่งถูกใช้มาก (จำกัดด้วย M_ARENA_MAX หรือตั้งผ่านตัวแปรสภาพแวดล้อม MALLOC_ARENA_MAX ก็ได้) proc_pid_limits(5) — Linux manual page Linux man-pages /proc/PID/limits แสดงค่า soft และ hard ของขีดจำกัดทรัพยากรแต่ละรายการของโปรเซส proc_stat(5) — Linux manual page Linux man-pages steal: เวลาที่ถูกแย่งไปเพราะระบบปฏิบัติการอื่นกำลังรันอยู่ในสภาพแวดล้อมเสมือน send(2) — Linux manual page Linux man-pages ถ้า send buffer ไม่มีที่ว่าง send() จะถูกบล็อก ส่วนโหมด non-blocking จะคืนค่า EAGAIN ทันที socket(7) — Linux manual page Linux man-pages SO_RCVBUF คือขนาดสูงสุดของ receive buffer ของซ็อกเก็ต ค่าเริ่มต้นกำหนดโดย rmem_default และค่าสูงสุดโดย rmem_max (Android ก็ใช้เคอร์เนล Linux) tcp(7) — Linux manual page Linux man-pages หลัง idle 7,200 วินาที ส่ง probe 9 ครั้งห่างกัน 75 วินาที (เพิ่มอีกประมาณ 11 นาที), มีผลเฉพาะซ็อกเก็ตที่เปิด SO_KEEPALIVE, TCP_KEEPIDLE และ TCP_USER_TIMEOUT write(2) — Linux manual page Linux man-pages ถ้าอุปกรณ์ไม่มีพื้นที่เหลือ การเขียนจะล้มเหลวด้วยข้อผิดพลาด ENOSPC
Microsoft Azure 12 Azure network round-trip latency statistics Microsoft Azure ค่ามัธยฐานเวลาไปกลับที่วัดจริงจากโซล (Korea Central): โตเกียว 30 ms, สิงคโปร์ 68 ms, สหรัฐฯ ฝั่งตะวันตก 124–136 ms, ยุโรป 234–244 ms Bulkhead Pattern Microsoft Azure ถ้าแยก connection pool และ thread pool ไว้ต่อปลายทางที่เรียก ความขัดข้องของปลายทางหนึ่งจะบล็อกแค่ pool ของมันเอง Chatty I/O antipattern Microsoft Azure ถ้ามีคำขอ I/O เล็ก ๆ จำนวนมาก ดีเลย์สะสมจะทำให้การตอบสนองแย่ลงมาก แนะนำให้รวมคำขอให้ใหญ่ขึ้นและน้อยครั้งลง Circuit Breaker Pattern Microsoft Azure คำขอที่ถูกบล็อกจนถึงไทม์เอาต์ถือครองเธรดและการเชื่อมต่อ DB ทำให้ฟีเจอร์ที่ไม่เกี่ยวข้องล้มเหลวไปด้วย, ถ้าความล้มเหลวสะสมถึงเกณฑ์ภายในเวลาที่กำหนด ให้ปฏิเสธการเรียกทันที Configure load balancer TCP reset and idle timeout Microsoft Azure idle timeout ของ Azure Load Balancer ค่าเริ่มต้น 4 นาที (4–100 นาที) ถ้าเกินจะไม่รับประกันว่าเซสชันยังอยู่, TCP reset เป็นตัวเลือกที่เปิดเพิ่มได้ Disk metrics Microsoft Azure อัตราการใช้ burst credit ของดิสก์และ VM เช่น Data Disk Used Burst IO Credits Percentage (ทุก 5 นาที) Extraneous Fetching antipattern Microsoft Azure ถ้าดึงข้อมูลมากเกินจำเป็น ภาระ I/O จะเพิ่มขึ้นและตอบสนองช้าลง Maintenance and updates Microsoft Azure การซ่อมบำรุงที่ไม่ต้องรีบูตแทบทุกครั้งหยุดไม่ถึง 10 วินาที, นาน ๆ ครั้ง (ขนาดทั่วไปไม่เกินหนึ่งครั้งใน 18 เดือน) ราว 30 วินาที, live migration ปกติไม่เกิน 5 วินาที, หลังหยุดนาฬิกาซิงก์อัตโนมัติ, การเชื่อมต่อ TCP ที่เปิดไว้นานอาจขาด หรืออีกฝั่งส่งซ้ำข้อมูลที่ส่งไปยัง VM ที่หยุดอยู่แบบ exponential backoff ทำให้กู้คืนช้าลงอีก, health check ของโหลดบาลานเซอร์ตัดสินว่าผิดปกติภายในราว 10 วินาที, ตรวจได้จาก Microsoft.Compute/virtualMachines/liveMigration/action ใน Activity Log และ VmAvailabilityMetric ที่เป็น 0 ระหว่างหยุด, เลือกเวลาที่จะใช้การซ่อมบำรุงได้ด้วย Maintenance Configuration Managed disk bursting Microsoft Azure Premium SSD ตั้งแต่ P20 ลงไป burst ด้วยระบบเครดิต, ถ้าเครดิตเต็มจะ burst ที่ความเร็วสูงสุดได้ 30 นาที Metrics and alerts for Azure NAT Gateway Microsoft Azure ถ้า SNAT Connection Count ที่กรองสถานะ Failed มากกว่า 0 อาจเป็นไปได้ว่า SNAT port หมด, Dropped Packets Scheduled Events for Linux VMs in Azure Microsoft Azure Freeze (หยุดไม่กี่วินาที CPU และเครือข่ายอาจหยุด) แจ้งล่วงหน้าอย่างน้อย 15 นาที, กรณีฮาร์ดแวร์ของโฮสต์เสีย จะเริ่มกู้คืนทันทีโดยไม่มีช่วงแจ้งล่วงหน้า Source Network Address Translation (SNAT) with Azure NAT Gateway Microsoft Azure SNAT port 64,512 พอร์ตต่อ public IP หนึ่งตัว (IP สูงสุด 16 ตัว), การเชื่อมต่อแต่ละรายการไปยังปลายทางเดียวกันต้องใช้พอร์ตต่างกัน, พอร์ตที่ปิดแล้วมี cooldown ก่อนนำกลับมาใช้กับปลายทางเดียวกัน
Oracle 9 Available Collectors Oracle ZGC ยอมเสีย throughput เล็กน้อยเพื่อให้การหยุดสูงสุดต่ำกว่า 1 ms และการหยุดไม่ขึ้นกับขนาด heap Diagnostic Tools (Java SE 21 Troubleshooting Guide) Oracle jstack พิมพ์ stack ของทุกเธรดใน JVM ที่กำลังรัน และหาเดดล็อกแล้วแสดงด้วย (Found one Java-level deadlock) Garbage Collector Implementation Oracle เมื่อ Young generation เต็มจะเกิด minor GC, ออบเจ็กต์ที่รอดบางส่วนย้ายไป Old generation และเมื่อ Old เต็มจะเก็บคืนทั้ง heap (นานกว่า minor มาก), -Xlog:gc เขียนหนึ่งบรรทัดต่อ GC หนึ่งครั้ง Garbage-First (G1) Garbage Collector Oracle ค่าเริ่มต้นของเป้าหมายเวลาหยุดของ G1 คือ 200 ms (MaxGCPauseMillis), ถ้าหน่วยความจำหมดระหว่างเก็บคืนจะเปลี่ยนไปทำ Full GC ที่หยุดทั้ง heap แล้วบีบอัด Garbage-First Garbage Collector Tuning Oracle ค่าเริ่มต้นของ G1 (GCTimeRatio=12) จะกำหนดขนาด heap ให้เวลา GC อยู่ที่ประมาณไม่เกิน 8% ของเวลาทั้งหมด, Full GC ที่เกิดจาก heap ถูกใช้สูงเกินไปหาได้จาก Pause Full (G1 Compaction Pause) ใน log The java Command Oracle ตารางเทียบออปชัน GC log แบบเดิมกับ -Xlog: -XX:+PrintGCDetails คือ -Xlog:gc* The Parallel Collector Oracle parallel GC จะแจ้ง OutOfMemoryError ถ้าใช้เวลาเกิน 98% ของเวลาทั้งหมดไปกับ GC แล้วเก็บคืน heap ได้น้อยกว่า 2% The Z Garbage Collector Oracle ZGC ทำงานที่หนักไปพร้อมกับแอป จึงไม่หยุดเกิน 1 ms แต่ถ้าเก็บคืนไม่ทัน แอปอาจต้องหยุดรอ GC (โหมด concurrent ในการทดลอง GC) Troubleshoot Memory Leaks Oracle ถ้าโปรแกรมช้าลงเรื่อย ๆ ให้สงสัยหน่วยความจำรั่ว สุดท้ายหน่วยความจำจะหมดและโปรแกรมปิดตัวผิดปกติ, ข้อมูลหลักในการวิเคราะห์การรั่วคือ heap dump
Redis 9 Diagnosing latency issues Redis เธรดเดียวประมวลผลคำขอตามลำดับ คำสั่งที่ช้าจึงขวางทุกคำขอที่ตามมา, ใช้ SCAN แทน KEYS, fork วัดจริงบนเครื่อง physical และ VM รุ่นใหม่ได้ราว 9–13 ms ต่อ 1 GB, THP ทำให้ดีเลย์และหน่วยความจำพุ่งจากการคัดลอกหลัง fork, คีย์จำนวนมากหมดอายุในวินาทีเดียวกันทำให้หยุด High availability with Redis Sentinel Redis failover อัตโนมัติที่ promote replica เมื่อเซิร์ฟเวอร์หลักล่ม INFO Redis keyspace_hits และ keyspace_misses (จำนวนครั้งที่ค้นคีย์เจอและไม่เจอ), expired_keys (จำนวนคีย์ที่หมดอายุ), uptime_in_seconds (เวลาตั้งแต่เริ่มทำงาน) KEYS Redis ใช้บน production ด้วยความระมัดระวังอย่างยิ่ง อาจทำลายประสิทธิภาพบน DB ขนาดใหญ่ได้ (บนโน้ตบุ๊กระดับทั่วไป คีย์ 1,000,000 ตัวใช้ 40 ms) Redis CLI Redis --bigkeys: ไล่ดู keyspace เพื่อหาคีย์ใหญ่ Redis latency monitoring Redis latency-monitor-threshold ค่าเริ่มต้น 0 (ปิด), LATENCY LATEST และ LATENCY DOCTOR, บันทึกดีเลย์แยกตามอีเวนต์ เช่น fork และ expire-cycle Redis persistence Redis ถ้าสร้าง RDB snapshot ทุกไม่กี่นาที ต้องยอมรับว่าข้อมูลช่วงไม่กี่นาทีสุดท้ายอาจหายเมื่อปิดตัวผิดปกติ SLOWLOG Redis log คำสั่งช้าที่บันทึกคำสั่งที่เกิน slowlog-log-slower-than, เวลารันไม่รวม I/O รับส่งกับไคลเอนต์ UNLINK Redis การลบแบบ asynchronous ที่ถอดคีย์ออกทันทีแล้วไปคืนหน่วยความจำในเธรดอื่น
Cloudflare 8 AAE-1 & SMW5 cable cuts impact millions of users across multiple countries Cloudflare ทราฟฟิกระหว่างยุโรปกับเอเชียส่วนใหญ่วิ่งผ่านเคเบิลใต้น้ำที่ผ่านอียิปต์ (สุเอซ) Cloudflare 1.1.1.1 Incident on July 14, 2025 Cloudflare เมื่อ DNS resolver สาธารณะหยุดทำงาน 62 นาที ผู้ใช้ที่แปลงชื่อเป็น IP ไม่ได้ก็แทบใช้บริการอินเทอร์เน็ตอะไรไม่ได้เลย How "expensive" is crypto anyway? Cloudflare ผลวัดของ BoringSSL: AES-128-GCM ประมาณ 3.7 GB ต่อวินาที (ต่างกันมากตามขนาด record), คอร์เดียวต่อวินาทีทำ RSA 2048 signature ได้ 1,120 ครั้ง, ECDSA P-256 signature 18,477 ครั้ง และ P-256 ECDHE 9,394 ครั้ง, บนเอดจ์เซิร์ฟเวอร์ของ Cloudflare ไลบรารี TLS ใช้ CPU ประมาณ 1.8% How to receive a million packets per second Cloudflare ผลการวัดที่ receive queue เดียวไปที่คอร์เดียว ทำให้คอร์นั้นตันที่ราว 350,000–430,000 แพ็กเก็ตต่อวินาที, กรณีที่ NIC hash UDP ด้วย IP อย่างเดียวจนไปกองที่คิวเดียว Maximum transmission unit and maximum segment size Cloudflare ทราฟฟิกขาเข้าถูกกรองแล้วส่งต่อผ่าน GRE tunnel (MTU 1,476), การตอบกลับขาออกส่งออกอินเทอร์เน็ตตรง (DSR), แนะนำให้จำกัด TCP MSS ไว้ไม่เกิน 1,436 ถ้าไม่ปรับ แพ็กเก็ตใหญ่จะถูกทิ้งหรือถูก fragment Q1 2024 Internet disruption summary Cloudflare เคเบิลแอฟริกาตะวันตกขาด (14 มีนาคม) กลับมาใช้ได้หลังผ่านไป 3–6 สัปดาห์ ระหว่างนั้นย้ายทราฟฟิกไปเคเบิลอื่น Q2 2024 Internet disruption summary Cloudflare เคเบิลในทะเลแดงที่เสียหายเมื่อกุมภาพันธ์ 2024 ยังซ่อมอยู่ในเดือนกรกฎาคม (พื้นที่ขัดแย้ง), เคเบิล EASSy และ Seacom ที่ขาดในเดือนพฤษภาคมกลับมาใช้ได้ใน 19 วัน Why does one NGINX worker take all the load? Cloudflare SO_REUSEPORT แบ่งคิวให้ worker แต่ละตัวด้วย hash แบบง่าย ถ้า worker ตัวหนึ่งติดขัด การเชื่อมต่อทั้งหมดที่กองอยู่ในคิวนั้นจะหยุดหมด
Gaffer On Games 7 Deterministic Lockstep Gaffer On Games ต้องได้อินพุตของเฟรม n ครบจึงจะคำนวณได้ ถ้าช้าก็ต้องรอ ถ้าบัฟเฟอร์ playout delay ที่ดูดซับจิตเตอร์เล็กไป จะหยุดแวบ Floating Point Determinism Gaffer On Games โค้ด floating point เดียวกันอาจให้ผลต่างกันตามคอมไพเลอร์, สถาปัตยกรรม CPU และ debug/release build, มีกรณีที่ CPU ของ AMD และ Intel ให้ค่าฟังก์ชัน transcendental ต่างกันเล็กน้อย Snapshot Compression Gaffer On Games ส่วนเปลี่ยนแปลงต้องสร้างเทียบกับ baseline ที่อีกฝ่ายยืนยัน (ack) ว่าได้รับแล้วเท่านั้น และสถานะเริ่มต้นส่งแยกต่างหาก Snapshot Interpolation Gaffer On Games ถ้าวาดสแนปช็อตที่ได้รับทันที จะกระตุกเพราะจิตเตอร์ ถ้าเก็บไว้ใน interpolation buffer สักครู่แล้วค่อยวาด จะลื่น State Synchronization Gaffer On Games ถ้าส่งสถานะไปพร้อมอินพุต ก็ปรับทั้งสองฝั่งให้ตรงกันได้โดยไม่ต้อง deterministic สมบูรณ์ UDP vs. TCP Gaffer On Games UDP ไม่รับประกันการส่งถึงและลำดับ แพ็กเก็ตที่หายต้องตรวจจับเองแล้วส่งซ้ำ What Every Programmer Needs To Know About Game Networking Gaffer On Games พัฒนาการของ netcode จาก P2P lockstep สู่ client/server และ client-side prediction
Google Cloud 7 IP addresses and ports Google Cloud TCP และ UDP อย่างละ 64,512 พอร์ตต่อ NAT IP หนึ่งตัว, ค่าเริ่มต้นของพอร์ตขั้นต่ำต่อ VM คือ 64 (static allocation) และ 32 (dynamic allocation), จำนวนพอร์ตที่จองให้ VM จำกัดจำนวนการเชื่อมต่อพร้อมกันไปยังปลายทางเดียวกัน, การเชื่อมต่อที่ปิดแล้วใช้ไม่ได้ระหว่าง TIME_WAIT Live migration process during maintenance events Google Cloud การหยุดระหว่าง live migration ปกติสั้นกว่า 1 วินาทีมาก, ระหว่างหยุดนาฬิการะบบกระโดดไปข้างหน้าได้สูงสุด 5 วินาที, ระหว่างย้าย ประสิทธิภาพดิสก์ CPU หน่วยความจำ และเครือข่ายลดลงชั่วครู่, VM ที่ไม่ใช้ live migration จะถูกปิดเมื่อซ่อมบำรุง (bare metal instance ไม่รองรับ) Logs and metrics Google Cloud reason OUT_OF_RESOURCES ของ dropped_sent_packets_count: แพ็กเก็ตที่ถูกทิ้งเพราะ NAT IP หรือพอร์ตไม่พอ Monitor and plan for a host maintenance event Google Cloud เมื่อซ่อมบำรุงจะมี system event compute.instances.migrateOnHostMaintenance ใน audit log MTU considerations | Cloud VPN Google Cloud MTU ของ Cloud VPN gateway คือ 1,460 ไบต์, payload MTU ของอุโมงค์ IPv4 คือ 1,406 ไบต์ (ผ่านอุโมงค์แล้วเหลือราว 1,400) Query metadata server for maintenance event notices Google Cloud ค่า metadata ของ maintenance-event เปลี่ยน 60 วินาทีก่อน live migration (กรณีตั้งค่าเป็น live migration และเคยอ่านค่านี้อย่างน้อยหนึ่งครั้งหลังการซ่อมบำรุงครั้งก่อน) TCP BBR congestion control comes to GCP – your Internet just got faster Google Cloud congestion control ที่อิงการหายของแพ็กเก็ตจะลดอัตราการส่งลงมาก แม้แพ็กเก็ตจะหายด้วยเหตุอื่นนอกจากความแออัด, BBR ตัดสินจากอัตราการส่งถึงปลายทาง (delivery rate) และ RTT
iproute2 7
Apple 6
Bufferbloat.net 6 Cake Bufferbloat.net CAKE: SQM สำหรับเราเตอร์ที่รวม shaper กับการจัดการคิวตระกูล fq_codel ไว้ด้วยกัน Introduction Bufferbloat.net ถ้าอุปกรณ์เครือข่ายอย่างเราเตอร์เก็บข้อมูลไว้มากเกินไป ดีเลย์จะพุ่งสูงมาก (bufferbloat) Setting up SQM for CeroWrt 3.10 Bufferbloat.net ต้องลดความเร็ว SQM ลงเป็น 95% ของความเร็วที่วัดได้จริง (ถ้าอิงความเร็วที่โฆษณาคือ 85%) เพื่อย้ายคอขวดจากอุปกรณ์ของ ISP มาไว้ในเราเตอร์ จึงจะได้ผล Smart Queue Management Bufferbloat.net SQM: วิธีที่ใช้ scheduling แยกตาม flow, การจัดการความยาวคิว (AQM) และ shaping ร่วมกัน Tests for Bufferbloat Bufferbloat.net ถ้าเปิดปิงทิ้งไว้แล้วใช้การทดสอบความเร็วทำให้เน็ตเต็ม แล้วปิงขึ้น คือ bufferbloat What Can I Do About Bufferbloat? Bufferbloat.net ใช้เราเตอร์ที่รองรับ SQM อย่าง cake และ fq_codel และปรับความเร็ว SQM โดยวัดความหน่วงขณะมีโหลดไปด้วย
Google 6
Microsoft SQL Server 6 Deadlocks guide Microsoft SQL Server ตรวจเดดล็อกทุก 5 วินาทีตามค่าเริ่มต้น ถ้าเกิดเดดล็อกบ่อยจะลดลงได้ถึง 100 ms, เซสชัน system_health ที่เปิดไว้เป็นค่าเริ่มต้นเก็บ xml_deadlock_report, ฝั่งที่ถูกเลือกให้ยกเลิกจะได้ข้อผิดพลาด 1205 Monitor performance by using the Query Store Microsoft SQL Server plan เปลี่ยนเพราะสถิติ สคีมา หรืออินเด็กซ์เปลี่ยน และ plan cache เก็บแค่ plan ล่าสุด, ใช้ plan forcing ของ Query Store ตรึง plan ที่ดี, ใช้หน้า Regressed Queries เทียบคิวรีที่ช้าลงกับ plan Parameter Sensitive Plan Optimization Microsoft SQL Server ถ้าข้อมูลกระจายไม่สม่ำเสมอ plan ที่แคชไว้ตัวเดียวจะไม่เหมาะกับทุกค่าพารามิเตอร์ Query Processing Architecture Guide Microsoft SQL Server parameter sniffing: วาง query plan ตามค่าพารามิเตอร์ที่เข้ามาตอน compile หรือ recompile Transaction Locking and Row Versioning Guide Microsoft SQL Server ถ้าคำสั่งเดียวถือล็อกบนตาราง (หรืออินเด็กซ์) เดียวตั้งแต่ 5,000 ตัวขึ้นไปจะเกิด lock escalation, บันทึกได้ด้วย extended event lock_escalation Troubleshoot a full transaction log (SQL Server Error 9002) Microsoft SQL Server ถ้า log เต็ม DB จะอ่านได้อย่างเดียวและแก้ไขไม่ได้, สาเหตุที่พบบ่อยที่ขวางการล้าง log คือขาดการสำรอง log, replication lag และทรานแซกชันที่ยาว, ดูว่าอะไรขวางอยู่ได้จาก log_reuse_wait_desc ใน sys.databases
Wireshark 6
.NET 5 .NET runtime metrics .NET dotnet.monitor.lock_contentions ตั้งแต่ .NET 9: จำนวนครั้งที่เกิดการแย่งกันตอนพยายามถือ monitor lock นับตั้งแต่โปรเซสเริ่ม Background garbage collection .NET background GC ใช้กับการเก็บคืน generation 2 เท่านั้น ส่วนการเก็บคืน generation 0 และ 1 (foreground GC) หยุด managed thread ทั้งหมด Debug a memory leak in .NET .NET แม้มี GC แต่ถ้ายังอ้างอิงออบเจ็กต์ที่ไม่ต้องใช้แล้วไว้ก็คือหน่วยความจำรั่ว ทำให้ประสิทธิภาพตกและเกิด OutOfMemoryException, ตรวจแนวโน้มหน่วยความจำและวิเคราะห์ dump dotnet-counters diagnostic tool .NET ตั้งแต่ .NET 9 แสดงเป็น meter ของ System.Runtime (dotnet.gc.pause.time ฯลฯ) ส่วน .NET 8 ลงไปแสดงเป็น EventCounter แบบเดิม (% Time in GC since last GC ฯลฯ) Efficient Querying .NET lazy loading ของ ORM ทำให้เกิดปัญหา N+1 ที่ส่งคิวรีเพิ่มอีกหนึ่งครั้งต่อทุกรายการ ทำให้ประสิทธิภาพตกมาก, แนะนำให้โหลดรวมทีเดียว (eager loading)
OpenJDK 5
systemd 5
ITU 4
sysstat 4
Valve 4
AMD 3
CCP Games 3
chrony 3 chrony – Frequently Asked Questions chrony แนะนำให้อนุญาต step เพียงไม่กี่ครั้งหลังเริ่มทำงาน เช่น makestep 1 3, VM ที่หยุดแล้วกลับมาทำงานอาจตื่นมาพร้อมเวลาที่คลาดเคลื่อน chrony.conf(5) chrony logchange: ถ้าปรับนาฬิกามากกว่าค่านี้ (ค่าเริ่มต้น 1 วินาที) จะบันทึกลง syslog chronyc(1) chrony System time (ส่วนต่างระหว่างนาฬิกา NTP กับนาฬิการะบบ), Last offset (offset ที่ประมาณไว้ตอนปรับครั้งล่าสุด), Ref time (เวลาที่นำค่าวัดล่าสุดจากแหล่งเวลามาใช้) ของ chronyc tracking
Go 3 A Guide to the Go Garbage Collector Go GC ของ Go ส่วนใหญ่ทำงานพร้อมกับโปรแกรม (concurrent) และมีแค่ช่วง stop-the-world สั้น ๆ, ถ้าจัดสรรมาก goroutine ต้องรับงาน GC ไปช่วยทำ (assist) จนเกิดดีเลย์ Go 1.8 Release Notes Go การหยุดของ GC ใน Go ปกติน้อยกว่า 100 µs runtime package Go GODEBUG=gctrace=1: หนึ่งบรรทัดต่อ GC หนึ่งครั้ง, wall clock time ของแต่ละเฟส, ขนาด heap ตอนเริ่มและจบ GC และ heap เป้าหมาย
IEEE 3
Intel 3
IO Visor 3
Kubernetes 3
NVIDIA 3
perf 3
Riot Games 3 Peeking into VALORANT's Netcode Riot Games ถ้าเดาเพื่อเติมข้อมูลที่มาช้าหรือหายไปแล้วผิด จะคลาดจากเซิร์ฟเวอร์ ตัวละครจึงกระโดดหรือถูกแก้ตำแหน่งแบบลื่นไถล Peeking into VALORANT's Netcode Riot Games เซิร์ฟเวอร์ย้อนกลับไปยังสถานะเกมที่ผู้เล่นเห็นตอนยิงแล้วตัดสินการโดน, ไคลเอนต์ส่งเวลาของ simulation ที่ตัวเองเห็นไปด้วย VALORANT's 128-Tick Servers Riot Games เซิร์ฟเวอร์ 128 ทิกต้องจบหนึ่งเฟรมภายใน 7.8125 ms, วัดเวลาเฟรมของเซิร์ฟเวอร์แยกตามระบบย่อย และแบ่งงบเวลาให้แต่ละระบบย่อยดูแล
RIPE NCC 3
APNIC 2 BGP updates in 2024 APNIC เส้นทางที่ไม่เสถียรใช้เวลากว่าจะกลับมาเสถียรโดยเฉลี่ยรายวัน 25–35 วินาที (IPv4) และ 40–50 วินาที (IPv6) IPv6 Performance – Revisited APNIC เทียบเวลาไปกลับของ IPv6 กับ IPv4 จากผู้ใช้ dual-stack คนเดียวกัน: บางเครือข่ายปลายทาง (access network) จัดการแพ็กเก็ต IPv6 ต่างไปโดยสิ้นเชิง จึงพบกลุ่มที่ IPv6 ช้ากว่า 15 ms, 25 ms และ 75 ms ภายใน ISP เดียวกัน
Istio 2 Istio Standard Metrics Istio istio_request_duration_milliseconds (การกระจายของเวลาประมวลผลคำขอ HTTP/gRPC), ใช้ label reporter แยกพร็อกซีฝั่งผู้ส่ง (source) กับฝั่งผู้รับ (destination) Performance and Scalability Istio ในโหมด sidecar คำขอผ่าน sidecar proxy ฝั่งผู้ส่งแล้วจึงผ่านฝั่งผู้รับ, ยิ่งเพิ่มฟีเจอร์ เส้นทางประมวลผลในพร็อกซียิ่งยาว และการเก็บ telemetry ทำให้คำขอถัดไปต้องรอนานขึ้น
Let's Encrypt 2 Decreasing Certificate Lifetimes to 45 Days Let's Encrypt ลดอายุเริ่มต้นเหลือ 64 วันตั้งแต่เดือนกุมภาพันธ์ 2027 และ 45 วันตั้งแต่เดือนกุมภาพันธ์ 2028, การต่ออายุแบบช่วงห่างตายตัว 60 วันจะไม่พอ จึงแนะนำให้ต่ออายุเมื่อผ่านไปประมาณ 2 ใน 3 ของอายุใบรับรอง FAQ Let's Encrypt อายุใบรับรองเริ่มต้น 90 วัน, แนะนำให้ต่ออายุทุก 60 วัน
MaxMind 2 GeoLite2 Free Geolocation Data MaxMind ฐานข้อมูลสาธารณะที่ระบุประเทศและ ASN ให้ IP address Geolocation accuracy MaxMind ระดับประเทศประมาณ 99.8%, ระดับเมืองในสหรัฐฯ (ในรัศมี 50 กิโลเมตร) ประมาณ 66%, ถ้าใช้ VPN จะได้ตำแหน่งเซิร์ฟเวอร์ VPN แทนผู้ใช้ปลายทาง, IP ของเครือข่ายมือถือใช้กันในพื้นที่กว้างจึงระบุตำแหน่งละเอียดไม่ได้, ฐานข้อมูลต้องอัปเดตอย่างต่อเนื่อง, ขอแก้ไขข้อมูลได้
numactl 2 numactl(8) — Linux manual page numactl ใช้ --cpunodebind และ --membind ผูก CPU และหน่วยความจำของโปรเซสไว้กับ NUMA โหนดที่กำหนด numastat(8) — Linux manual page numactl ตัวนับ numa_miss (จัดสรรบนโหนดที่ไม่ใช่โหนดที่ต้องการ) และ other_node (โปรเซสที่รันบนโหนดอื่นมาจัดสรรบนโหนดนี้), -p แสดงหน่วยความจำแยกตามโหนดของโปรเซส
OpenSSL 2 openssl-s_client OpenSSL -showcerts: แสดงรายการใบรับรองที่เซิร์ฟเวอร์ส่งมาตามลำดับที่ส่ง (ยังไม่ได้ตรวจ chain) openssl-x509 OpenSSL -enddate: แสดงวันหมดอายุของใบรับรอง (notAfter), -checkend: ตรวจว่าจะหมดอายุภายในจำนวนวินาทีที่กำหนดหรือไม่
SK텔레콤 2 SKT, 고객 선택권과 혜택 강화한 신규 5G 요금제 출시 SK텔레콤 ตัวอย่างการควบคุมความเร็วหลังดาต้าพื้นฐานของแพ็กเกจ 5G หมด: สูงสุด 400 kbps, 1 Mbps, 3 Mbps SKT, 요금제 개편 SK텔레콤 ใช้งานต่อได้ที่ความเร็วสูงสุด 400 kbps แม้ใช้ดาต้าพื้นฐานหมดแล้ว (โครงการดาต้าอุ่นใจสำหรับคนทั้งประเทศ)
Solidigm 2
Square Enix 2
USENIX 2
util-linux 2
Amazon Builders' Library 1
Apache Software Foundation 1 Asynchronous loggers Apache Software Foundation async logging ดูดซับ log ที่พุ่งช่วงสั้น ๆ ด้วยคิว แต่ถ้าปลายทาง (output) ช้าต่อเนื่อง คิวจะเต็มแล้วความเร็วลดลงเหลือเท่าปลายทางที่ช้าที่สุด หรือทิ้ง log ตามนโยบาย (Discard)
coreutils 1
Envoy 1 What is Envoy Envoy Envoy เป็นโปรเซสแยกที่รันข้างแอปพลิเคชันเซิร์ฟเวอร์ทุกตัว และแอปรับส่งข้อมูลผ่าน Envoy บน localhost
ethtool 1
Frontiers 1
Game Developer 1
gdb 1
GDC 1
GGPO 1
GNU Project 1
HDMI Licensing Administrator 1 Auto Low Latency Mode (ALLM) HDMI Licensing Administrator ALLM ทำให้อุปกรณ์สลับจอเป็นโหมด low latency (ที่มักเรียกว่า Game Mode) โดยอัตโนมัติ ในโหมดนี้ทีวีจะหยุดการประมวลผลภาพบางอย่างเพื่อลดดีเลย์
id Software 1
iputils 1 ping(8) — Linux manual page iputils -M do เปิดแฟล็ก DF และปฏิเสธแพ็กเก็ตที่ใหญ่กว่า path MTU, -s กำหนดขนาดข้อมูล (ค่าเริ่มต้น 56 ไบต์ บวกเฮดเดอร์ ICMP 8 ไบต์)
IRTF 1 RFC 9505: A Survey of Worldwide Censorship Techniques IRTF อุปกรณ์ตรวจในเครือข่ายอาจเลือกบล็อก flow ของ TCP หรือ UDP ตาม IP, พอร์ต และโปรโตคอล (พบการบล็อก endpoint UDP ของ QUIC), วิธีบล็อกทุกอย่างที่ไม่ใช่โปรโตคอลที่อนุญาตทำให้บล็อกเกินจำเป็น และยังมีวิธีจำกัดความเร็วของทราฟฟิกบางประเภทด้วย
jemalloc 1
Juniper Networks 1 Flow-Based Sessions Juniper Networks ไฟร์วอลล์บริษัทในการทดลอง: session timeout เริ่มต้นของไฟร์วอลล์ SRX คือ TCP 1,800 วินาที (30 นาที), UDP 60 วินาที
Lua.org 1 Lua 5.4 Reference Manual Lua.org โหมด incremental แบ่งการเก็บคืนเป็นขั้นเล็ก ๆ แทรกระหว่างการรันโปรแกรม (ถ้าตั้งขั้นใหญ่จะกลายเป็น stop-the-world), major collection ในโหมด generational เป็น stop-the-world ที่ไล่ทุกออบเจ็กต์, collectgarbage("count") คือปริมาณหน่วยความจำทั้งหมดที่ Lua ใช้ (KB)
Meta 1
mtr 1
net-tools 1
netfilter 1
Netflix 1
Network Time Foundation 1 ntpd - Network Time Protocol (NTP) daemon Network Time Foundation ถ้าต่างเกินเกณฑ์ step 128 ms จะปรับทีเดียว ถ้าน้อยกว่าจะค่อย ๆ ปรับ ด้วยอัตรา 0.5 ms ต่อวินาที การปรับ 1 วินาทีจึงใช้ 2,000 วินาที (ประมาณ 33 นาที)
OpenWrt 1 SQM (Smart Queue Management) OpenWrt ใส่ความเร็วดาวน์โหลดและอัปโหลดเป็น 90% ของค่าที่วัดได้จริง แนะนำ queue discipline แบบ cake (ถ้า CPU อ่อนให้ใช้ fq_codel)
procps-ng 1
Red Hat 1 Chapter 2. Getting started with TuneD Red Hat โปรไฟล์ latency-performance ปิดฟีเจอร์ประหยัดพลังงาน ตั้ง governor เป็น performance และใช้ PM QoS ให้ใช้เฉพาะ C-state ระดับตื้น, ตรวจโปรไฟล์ปัจจุบันด้วย tuned-adm active
Seagate 1
Starlink 1 Improving Starlink’s Latency Starlink ค่ามัธยฐานช่วงพีคในสหรัฐฯ 48.5 ms→33 ms, 1% ที่ช้าที่สุด (p99) จากเกิน 150 ms→ต่ำกว่า 65 ms (ปี 2024), สัญญาณเดินทางช่วงดาวเทียมหนึ่งช่วง 1.8–3.6 ms, ถ้าอ้อมผ่านลิงก์เลเซอร์ความหน่วงจะเพิ่ม และระยะจากสถานีภาคพื้นดินถึงจุดเชื่อมต่ออินเทอร์เน็ต (PoP) ก็เป็นปัจจัยของความหน่วงด้วย
VLDB Endowment 1
과학기술정보통신부 1 5G 통신서비스 품질평가 결과 발표 과학기술정보통신부 ตามประกาศปี 2020 5G ในเกาหลีให้บริการแบบ NSA และอยู่ในขั้นวางแผนเปลี่ยนเป็น SA