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

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

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

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

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

ชั้นเดียวกัน: L8 ซ็อกเก็ตและโปรโตคอล

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

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