한국어English日本語简体中文繁體中文DeutschไทยTiếng ViệtРусскийPortuguês (Brasil)EspañolBahasa Indonesia

คู่มือเกมแลค › L7 OS ของเซิร์ฟเวอร์ (เคอร์เนล)

คิวรอเชื่อมต่อ (backlog) ล้น Listen backlog / SYN queue overflow

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”
วิธีตรวจ
ใช้เครื่องมือฝั่งอินฟรา (ไม่ต้องใช้โค้ดเกม)

แหล่งอ้างอิง

  1. listen(2) — Linux manual page Linux man-pages
    ถ้า backlog ของ listen เกิน somaxconn จะถูกตัดเงียบ ๆ, somaxconn ค่าเริ่มต้น 4,096 (ตั้งแต่ 5.4 ก่อนหน้านั้น 128), เมื่อคิวเต็มอาจเพิกเฉยต่อคำขอแล้วปล่อยให้ไคลเอนต์ลองใหม่เอง
  2. IP Sysctl Linux kernel
    tcp_syn_retries: ส่งคำขอเชื่อมต่อ (SYN) ซ้ำหลายครั้ง โดยรอ 1 วินาทีก่อนส่งซ้ำครั้งแรก, tcp_abort_on_overflow ปิดเป็นค่าเริ่มต้น (คิวล้นก็ไม่ส่งการปฏิเสธกลับ), tcp_syncookies เปิดเป็นค่าเริ่มต้น
  3. listen function (winsock2.h) Microsoft
    บน Windows เมื่อคิวเต็ม ไคลเอนต์จะได้รับข้อผิดพลาด WSAECONNREFUSED
  4. SNMP counter Linux kernel
    TcpExtListenOverflows: จำนวนครั้งที่ทิ้งคำขอเชื่อมต่อ (SYN) เพราะคิว accept เต็ม ซึ่ง TcpExtListenDrops จะเพิ่มขึ้นไปพร้อมกัน
  5. net/ipv4/tcp_diag.c (Linux v6.12) Linux kernel
    ค่า Recv-Q และ Send-Q ของ ss: ซ็อกเก็ตที่ listen อยู่คือจำนวนการเชื่อมต่อที่รอ accept และขีดจำกัด backlog, ซ็อกเก็ตที่เชื่อมต่อแล้วคือไบต์ที่แอปยังไม่ได้อ่าน และไบต์ที่ส่งไปแล้วแต่ยังไม่ได้รับ ACK

สาเหตุที่ควรดูประกอบ

ชั้นเดียวกัน: L7 OS ของเซิร์ฟเวอร์ (เคอร์เนล)

สาเหตุจากชั้นอื่นที่ทำให้เกิดอาการเดียวกัน (เข้าเกมไม่ได้/โหลดไม่จบ)

ดูการ์ดในฉบับหลักที่มีภาพและการทดลอง