คู่มือเกมแลค › L8 ซ็อกเก็ตและโปรโตคอล
TCP RTO และ exponential backoff RTO and exponential backoff
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”
- วิธีตรวจ
- ใช้เครื่องมือฝั่งอินฟรา (ไม่ต้องใช้โค้ดเกม)
แหล่งอ้างอิง
- RFC 6298: Computing TCP's Retransmission Timer IETF
RTO แรก 1 วินาที, เพิ่ม RTO เป็นสองเท่าทุกครั้งที่ตัวจับเวลาหมดเวลา (exponential backoff) - net/ipv4/tcp_input.c (Linux v6.12) Linux kernel
RTO ของ Linux = smoothed RTT + ค่าความแปรปรวนของ RTT และค่าความแปรปรวนมีขั้นต่ำเป็น tcp_rto_min (200 ms) RTO จึงไม่ต่ำกว่า RTT + 200 ms - IP Sysctl Linux kernel
tcp_rto_min_us ค่าเริ่มต้น 200 ms, RTO แรกของคำขอเชื่อมต่อ 1 วินาที, ถ้า tcp_retries2=15 จะใช้อย่างน้อย 924.6 วินาที (ประมาณ 15 นาที) ก่อนเลิก - ss(8) — Linux manual page iproute2
rto (ตัวจับเวลาส่งซ้ำ, ms) และ backoff (จำนวนครั้งของ exponential backoff) ใน -i - net/ipv4/proc.c (Linux v6.12) Linux kernel
ชื่อตัวนับที่ nstat แสดง: TCPTimeouts ในกลุ่ม TcpExt - net/ipv4/tcp_timer.c (Linux v6.12) Linux kernel
ทุกครั้งที่ตัวจับเวลาส่งซ้ำหมดเวลา จะเพิ่ม TCPTimeouts เพิ่ม backoff ทีละหนึ่ง และเพิ่ม RTO เป็นสองเท่า (จนถึงค่าสูงสุด)
สาเหตุที่ควรดูประกอบ
ชั้นเดียวกัน: L8 ซ็อกเก็ตและโปรโตคอล
สาเหตุจากชั้นอื่นที่ทำให้เกิดอาการเดียวกัน (ค้าง)
ดูการ์ดในฉบับหลักที่มีภาพและการทดลอง