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

คู่มือเกมแลค › ต้นเหตุของการส่งซ้ำใน TCP

zero window (การหยุดที่ดูเหมือนการส่งซ้ำ) Zero window, often mistaken for retransmission

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)

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

  1. RFC 9293: Transmission Control Protocol (TCP) IETF
    เมื่อ receive window เป็น 0 ฝั่งส่งจะส่ง zero window probe และเพิ่มช่วงห่างของ probe แบบ exponential
  2. 7.5. TCP Analysis Wireshark
    TCP ZeroWindow: แพ็กเก็ตที่ฝั่งรับแจ้ง window เป็น 0 เพื่อให้ฝั่งส่งหยุดส่ง
  3. Display Filter Reference: Transmission Control Protocol Wireshark
    display filter tcp.analysis.zero_window และ tcp.analysis.zero_window_probe
  4. SNMP counter Linux kernel
    TcpExtTCPToZeroWindowAdv: จำนวนครั้งที่แจ้ง receive window จากค่าที่ไม่ใช่ 0 เป็น 0
  5. net/ipv4/proc.c Linux kernel
    ชื่อตัวนับที่ nstat แสดง: TCPToZeroWindowAdv, TCPWinProbe
  6. net/ipv4/tcp_output.c Linux kernel
    TCPWinProbe: เพิ่มขึ้นทุกครั้งที่ส่ง probe (tcp_send_probe0) เมื่อ receive window ของอีกฝั่งเป็น 0
  7. net/ipv4/tcp_diag.c Linux kernel
    Recv-Q ใน ss ของการเชื่อมต่อ คือจำนวนไบต์ที่รับมาแล้วแต่โปรแกรมยังไม่ได้อ่าน

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

ชั้นเดียวกัน: ต้นเหตุของการส่งซ้ำใน TCP

สาเหตุจากชั้นอื่นที่ทำให้เกิดอาการเดียวกัน (ค้าง)

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