2 คะแนน โดย GN⁺ 2024-05-10 | 1 ความคิดเห็น | แชร์ทาง WhatsApp

ความสำคัญของการตั้งค่า TCP_NODELAY

  • เมื่อต้องดีบักปัญหาเรื่อง latency ในระบบแบบกระจาย สิ่งแรกที่ควรตรวจสอบคือมีการเปิดใช้ตัวเลือก TCP_NODELAY หรือไม่
  • นักพัฒนาระบบแบบกระจายจำนวนมากเคยมีประสบการณ์แก้ปัญหา latency ได้อย่างรวดเร็วเพียงแค่เปิดใช้ socket option ง่าย ๆ ตัวนี้
  • สิ่งนี้ชี้ให้เห็นว่าพฤติกรรมค่าเริ่มต้นอาจไม่เหมาะสม หรือแนวคิดโดยรวมอาจล้าสมัยแล้ว

ที่มาและปัญหาของอัลกอริทึม Nagle

  • อัลกอริทึม Nagle ซึ่งถูกเสนอครั้งแรกใน RFC896 ของ John Nagle เมื่อปี 1984 มีเป้าหมายเพื่อกระจายต้นทุนของ TCP header ให้คุ้มค่ามากขึ้น เพื่อให้ได้ throughput ที่ดีกว่าบนเครือข่าย
  • อัลกอริทึม Nagle ทำงานโดยยับยั้งการส่ง TCP segment ใหม่ หากยังไม่ได้รับ acknowledgment สำหรับข้อมูลที่ส่งไปก่อนหน้า
  • อย่างไรก็ตาม สิ่งนี้ก่อให้เกิดปัญหาเมื่อทำงานร่วมกับ delayed ACK
    • อัลกอริทึม Nagle จะบล็อกการส่งข้อมูลเพิ่มเติมจนกว่าจะได้รับ ACK ขณะที่ delayed ACK จะหน่วงการส่ง ACK ออกไปจนกว่าจะมีการเตรียมการตอบกลับ
    • สิ่งนี้ดีต่อการทำให้แพ็กเก็ตเต็ม แต่ไม่เหมาะกับแอปพลิเคชันแบบ pipeline ที่ไวต่อ latency

ความจำเป็นของอัลกอริทึม Nagle ในระบบสมัยใหม่

  • เซิร์ฟเวอร์สมัยใหม่สามารถทำงานปริมาณมหาศาลได้ภายในเวลาเพียงไม่กี่ร้อยไมโครวินาที ดังนั้นการหน่วงการส่งข้อมูลแม้เพียง RTT เดียวอาจไม่ได้ให้ประโยชน์ที่ชัดเจน
  • ฐานข้อมูลแบบกระจายและระบบส่วนใหญ่ไม่ได้ส่งแพ็กเก็ตขนาดหนึ่งไบต์
    • เพราะมีข้อมูลที่ต้องส่งมากกว่าเดิม รวมถึง overhead ของโปรโตคอลอย่าง TLS และ overhead จากการเข้ารหัสกับการทำ serialization
  • การไม่ส่งข้อความขนาดเล็กยังคงเป็นเรื่องสำคัญ แต่ปัจจุบันสิ่งนี้ถูกจัดการได้อย่างมีประสิทธิภาพในชั้นแอปพลิเคชัน

ความเห็นต่อการใช้ TCP_NODELAY

  • หากกำลังสร้างระบบแบบกระจายที่ไวต่อ latency ก็สามารถเปิดใช้ TCP_NODELAY ได้อย่างไม่ต้องกังวล (ปิดใช้อัลกอริทึม Nagle)
  • ในระบบสมัยใหม่ เมื่อพิจารณาจากทราฟฟิก ลักษณะของแอปพลิเคชัน และประสิทธิภาพฮาร์ดแวร์ อัลกอริทึม Nagle อาจไม่จำเป็นอีกต่อไป
    • กล่าวคือ TCP_NODELAY ควรเป็นค่าเริ่มต้น
    • สิ่งนี้อาจทำให้โค้ดบางประเภทที่ "เขียนทุกไบต์" ช้าลง แต่ถ้าคุณให้ความสำคัญกับประสิทธิภาพ คุณก็ควรแก้แอปพลิเคชันนั้นอยู่ดี

ความเห็นจาก GN⁺

  • ปัญหาจากปฏิสัมพันธ์ระหว่างอัลกอริทึม Nagle และ delayed ACK เป็นตัวอย่างที่ดีว่าการออกแบบโปรโตคอลนั้นยากเพียงใด สถานการณ์ที่ฟีเจอร์สมเหตุสมผลสองอย่างสร้างพฤติกรรมที่ไม่ตั้งใจขึ้นมา เป็นสิ่งที่นักออกแบบระบบคุ้นเคยกันดี

  • แนวโน้มทั่วไปคือการเพิ่มประสิทธิภาพการส่งข้อความขนาดเล็กในชั้นแอปพลิเคชัน การลด overhead ที่ไม่จำเป็นให้เหลือน้อยที่สุดผ่านการเข้ารหัสและการทำ serialization ที่มีประสิทธิภาพเป็นเรื่องสำคัญ

  • หากเป้าหมายของอัลกอริทึม Nagle คือการเพิ่มประสิทธิภาพแบนด์วิดท์เครือข่าย ปัจจุบันความต้องการที่สำคัญกว่าคือการลด latency ให้ต่ำที่สุด ในสถานการณ์ที่ความตอบสนองของแอปพลิเคชันส่งผลโดยตรงต่อประสบการณ์ผู้ใช้ ก็ควรหลีกเลี่ยงความหน่วงที่ไม่จำเป็น

  • อย่างไรก็ตาม การตั้งให้ TCP_NODELAY เป็นค่าเริ่มต้นอาจไม่ได้เหมาะสมที่สุดในทุกสถานการณ์ ในสภาพแวดล้อมที่แบนด์วิดท์จำกัด หรือในระบบที่ประสิทธิภาพการส่งข้อมูลสำคัญกว่า latency มาก อาจยังจำเป็นต้องเลือกใช้อัลกอริทึม Nagle อย่างเหมาะสม

  • ในการออกแบบโปรโตคอลเครือข่าย การสร้างสมดุลระหว่างความต้องการที่หลากหลายเป็นเรื่องสำคัญ การเปลี่ยนพฤติกรรมค่าเริ่มต้นของโปรโตคอลแบบใช้งานทั่วไปจำเป็นต้องทำอย่างรอบคอบ แต่ก็ควรมีความยืดหยุ่นในการเลือกตัวเลือกที่เหมาะกับความต้องการของแอปพลิเคชันด้วย

1 ความคิดเห็น

 
GN⁺ 2024-05-10
ความเห็นจาก Hacker News

สรุป:

  • อัลกอริทึมของ Nagle เป็นความพยายามในการเขียนข้อมูลแบบแบตช์ และมีหลายกรณีที่การเขียนแบบแบตช์ดีกว่า ไม่ว่าจะเป็นฮาร์ดแวร์ เครือข่าย แอปพลิเคชัน หรือกรณีการใช้งานใดก็ตาม
  • การประมวลผลจำนวนมากในปัจจุบันใช้การเขียนแบบแบตช์ และโปรโตคอลระดับสูงรุ่นใหม่อย่าง QUIC ก็ทำการแบตช์การเขียนเช่นกัน โดยย้ายการเชื่อมต่ออิสระและการจัดการข้อผิดพลาดของ TCP ไปไว้ใน user space
  • เมื่อเครือข่ายอิ่มตัว อัลกอริทึมของ Nagle จะย้อนกลับมาในโค้ดแอปพลิเคชันในรูปแบบของการปรับแต่ง QUIC ที่ลึกยิ่งขึ้น
  • อัลกอริทึมของ Nagle ยังมีประโยชน์ในกรณีที่แพ็กเก็ตต่อวินาที (PPS) อิ่มตัวเนื่องจากแพ็กเก็ตขนาดเล็ก
  • อัลกอริทึมของ Nagle ทำงานได้ไม่ดีกับบางเวิร์กโหลด ดังนั้นจึงควรบังคับให้วิศวกรเป็นผู้ตั้งค่าเมื่อสร้างซ็อกเก็ต
  • สามารถปิด delayed ACK ได้ด้วยซ็อกเก็ตออปชัน TCP_QUICKACK หรือใช้ /proc/sys/net/ipv4/tcp_delack_min และ /proc/sys/net/ipv4/tcp_ato_min
  • ในโลกที่แบนด์วิดท์มีจำกัด การส่งแพ็กเก็ต TCP สำหรับทุกไบต์ถือเป็นการสิ้นเปลืองแบนด์วิดท์ ดังนั้นจึงยังจำเป็นต้องมีอัลกอริทึมของ Nagle
  • หากไม่สามารถเข้าถึงซอร์สของแอปพลิเคชันได้ ก็ยังไม่มีวิธีที่ดีในการเปิดใช้ TCP_NODELAY
  • ภาษาสมัยใหม่อย่าง Go เปิดใช้ TCP_NODELAY โดยค่าเริ่มต้น จึงไม่เกิดปัญหานี้
  • หากมีวิธีให้แอปพลิเคชันบอก TCP stack ได้ว่ามันเป็น interactive shell ก็อาจปิด TCP_NODELAY ไว้เป็นค่าเริ่มต้น แล้วเปิดเฉพาะสำหรับแอปพลิเคชันนั้นเพื่อลดโอเวอร์เฮดได้