วิธีลดจำนวนซ็อกเก็ตใน TIME_WAIT


36

เซิร์ฟเวอร์ Ubuntu 10.04.1 x86

ฉันมีเครื่องที่มีบริการ FCGI HTTP ซึ่งอยู่หลัง nginx ซึ่งให้บริการคำขอ HTTP ขนาดเล็กจำนวนมากแก่ลูกค้าที่แตกต่างกันจำนวนมาก (ประมาณ 230 คำขอต่อวินาทีในชั่วโมงเร่งด่วนขนาดตอบสนองโดยเฉลี่ยที่มีส่วนหัวคือ 650 ไบต์ลูกค้าหลายล้านรายต่อวัน)

เป็นผลให้ฉันมีซ็อกเก็ตจำนวนมากแขวนอยู่ใน TIME_WAIT (กราฟถูกจับด้วยการตั้งค่า TCP ด้านล่าง):

TIME_WAIT

ฉันต้องการลดจำนวนซ็อกเก็ต

ฉันจะทำอะไรนอกจากนี้

$ cat / proc / sys / net / ipv4 / tcp_fin_timeout
1
$ cat / proc / sys / net / ipv4 / tcp_tw_recycle
1
$ cat / proc / sys / net / ipv4 / tcp_tw_reuse
1

อัปเดต: รายละเอียดบางอย่างเกี่ยวกับเค้าโครงบริการจริงบนเครื่อง:

ไคลเอนต์ ----- TCP-socket -> nginx (reverse proxy balancer โหลด) 
       ----- TCP-socket -> nginx (ผู้ปฏิบัติงาน) 
       - โดเมนซ็อกเก็ต -> fcgi-software
                          --single-persistent-TCP-socket -> Redis
                          --single-persistent-TCP-socket -> MySQL (เครื่องอื่น ๆ )

ฉันควรเปลี่ยน load-balancer -> การเชื่อมต่อของผู้ปฏิบัติงานไปยังซ็อกเก็ตโดเมนด้วยเช่นกัน แต่ปัญหาเกี่ยวกับซ็อกเก็ต TIME_WAIT จะยังคงอยู่ - ฉันวางแผนที่จะเพิ่มคนทำงานที่สองในเครื่องแยกต่างหากในไม่ช้า จะไม่สามารถใช้ซ็อกเก็ตโดเมนในกรณีนั้นได้


ดูเหมือนว่ามูนินกำลังโกหกอย่างไร้ยางอาย ดูความเห็นต่อคำตอบของ Kyle มองเข้าไปที่ตอนนี้
Alexander Gladysh

1
สร้างคำถามเกี่ยวกับ Munin: serverfault.com/questions/212200/ …
Alexander Gladysh

ตอนนี้ดูเหมือนว่า Munin จะไม่โกหก แต่ฉันกำลังดูโครงเรื่องที่ผิด ...
Alexander Gladysh

คำตอบ:


28

net.ipv4.tcp_fin_timeout=1สิ่งหนึ่งที่คุณควรจะทำอย่างไรที่จะเริ่มต้นในการแก้ไขปัญหา นั่นคือวิธีการลดคุณไม่ควรต่ำกว่า 30

เนื่องจากสิ่งนี้อยู่หลัง nginx นั่นหมายความว่า nginx ทำหน้าที่เป็น reverse proxy หรือไม่? หากเป็นกรณีนี้การเชื่อมต่อของคุณคือ 2x (หนึ่งต่อไคลเอ็นต์หนึ่งต่อหนึ่งกับเว็บเซิร์ฟเวอร์ของคุณ) คุณรู้หรือไม่ว่าซ็อคเก็ตเหล่านี้จบลงที่ใด

อัพเดต:
fin_timeout คือระยะเวลาที่จะอยู่ใน FIN-WAIT-2 (จากnetworking/ip-sysctl.txtในเอกสารประกอบเคอร์เนล):

tcp_fin_timeout - INTEGER
        Time to hold socket in state FIN-WAIT-2, if it was closed
        by our side. Peer can be broken and never close its side,
        or even died unexpectedly. Default value is 60sec.
        Usual value used in 2.2 was 180 seconds, you may restore
        it, but remember that if your machine is even underloaded WEB server,
        you risk to overflow memory with kilotons of dead sockets,
        FIN-WAIT-2 sockets are less dangerous than FIN-WAIT-1,
        because they eat maximum 1.5K of memory, but they tend
        to live longer. Cf. tcp_max_orphans.

ฉันคิดว่าคุณอาจต้องให้ Linux เก็บหมายเลขซ็อกเก็ต TIME_WAIT ไว้กับสิ่งที่ดูเหมือนว่ามีขนาด 32k cap อยู่และนี่เป็นที่ที่ Linux ใช้รีไซเคิล 32k นี้ถูกพาดพิงถึงในลิงค์นี้:

นอกจากนี้ฉันพบว่า / proc / sys / net / ipv4 / tcp_max_tw_buckets เกิดความสับสน แม้ว่าค่าเริ่มต้นจะถูกตั้งไว้ที่ 180000 แต่ฉันเห็นการหยุดชะงักของ TCP เมื่อฉันมีซ็อกเก็ต 32K TIME_WAIT บนระบบของฉันโดยไม่คำนึงถึงที่เก็บข้อมูลสูงสุด tw

ลิงก์นี้ยังแนะนำว่าสถานะ TIME_WAIT คือ 60 วินาทีและไม่สามารถปรับได้ด้วย proc

ความจริงสนุกแบบสุ่ม:
คุณสามารถดูตัวจับเวลาบน timewait ด้วย netstat สำหรับแต่ละซ็อกเก็ตด้วยnetstat -on | grep TIME_WAIT | less

Reuse Vs Recycle: สิ่ง
เหล่านี้เป็นสิ่งที่น่าสนใจเหมือนการอ่านซ้ำทำให้สามารถใช้งานซ็อกเก็ต time_Wait ได้อีกครั้งและการรีไซเคิลทำให้มันอยู่ในโหมด TURBO:

tcp_tw_recycle - BOOLEAN
        Enable fast recycling TIME-WAIT sockets. Default value is 0.
        It should not be changed without advice/request of technical
        experts.

tcp_tw_reuse - BOOLEAN
        Allow to reuse TIME-WAIT sockets for new connections when it is
        safe from protocol viewpoint. Default value is 0.
        It should not be changed without advice/request of technical
        experts.

ฉันจะไม่แนะนำให้ใช้ net.ipv4.tcp_tw_recycle ขณะที่มันทำให้เกิดปัญหากับลูกค้า

บางทีคุณอาจลองไม่เปิดสวิตช์ทั้งคู่และดูว่ามีผลกระทบอะไรบ้าง (ลองทีละครั้งแล้วดูว่ามันทำงานอย่างไร) ฉันจะใช้netstat -n | grep TIME_WAIT | wc -lสำหรับข้อเสนอแนะที่เร็วกว่า Munin


1
@ Kyle: สิ่งที่คุ้มค่าสำหรับnet.ipv4.tcp_fin_timeoutคุณแนะนำ?
Alexander Gladysh

1
@Kyle: ไคลเอนต์ --TCP- ซ็อกเก็ต -> nginx (โหลดพร็อกซี balancer ย้อนกลับ) --TCP- ซ็อกเก็ต -> nginx (ผู้ปฏิบัติงาน) - โดเมนซ็อกเก็ต -> fcgi ซอฟต์แวร์
Alexander Gladysh

2
ผมจะบอกว่าหรืออาจจะ30 20ลองและดู คุณมีโหลดจำนวนมากดังนั้น TIME_WAIT จึงเหมาะสมเป็นอย่างยิ่ง
Kyle Brandt

1
@ Kyle: ขอโทษสำหรับคำถามโง่ (ฉันอยู่ในระดับสินค้าลัทธิที่นี่จนถึงน่าเสียดาย) แต่สิ่งที่ฉันควรคาดหวังที่จะเห็นเมื่อฉันเปลี่ยนnet.ipv4.tcp_fin_timeoutจาก1เป็น20?
Alexander Gladysh

4
netstat -an|awk '/tcp/ {print $6}'|sort|uniq -cโอ้นี่เป็นดีหนึ่งซับ: ดังนั้น @Alex ถ้า Munin ไม่ชอบอาจจะลองดูว่ามันติดตามสถิติเหล่านี้อย่างไร บางทีปัญหาเดียวคือ Munin กำลังให้ข้อมูลที่ไม่ดีแก่คุณ :-)
Kyle Brandt

1

tcp_tw_reuse ค่อนข้างปลอดภัยเนื่องจากอนุญาตให้ใช้การเชื่อมต่อ TIME_WAIT ซ้ำ

นอกจากนี้คุณสามารถเรียกใช้บริการเพิ่มเติมที่ฟังบนพอร์ตต่าง ๆ ที่อยู่เบื้องหลังตัวโหลดบาลานซ์ของคุณหากการเรียกใช้พอร์ตไม่เพียงพอเป็นปัญหา

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.