คู่มือเกมแลค › ต้นเหตุของการส่งซ้ำใน TCP
thin stream กู้คืนช้า Thin streams fall back to 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
แหล่งอ้างอิง 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
สาเหตุที่ควรดูประกอบ
ชั้นเดียวกัน: ต้นเหตุของการส่งซ้ำใน TCP
สาเหตุจากชั้นอื่นที่ทำให้เกิดอาการเดียวกัน (ค้าง)
ดูการ์ดในฉบับหลักที่มีภาพและการทดลอง