การตั้งค่าเริ่มต้น Linux TCP เหล่านี้มีวิธีตัดสินใจอย่างไร


13

ฉันใช้เวลาค่อนข้างนานในการติดตามปัญหาในการผลิตเมื่อไม่นานมานี้ที่เซิร์ฟเวอร์ฐานข้อมูลหายไปอาจทำให้หยุดทำงานนานถึง 2 ชั่วโมง (รอpoll()สายในไลบรารีไคลเอนต์ libpq นาน ๆ ) สำหรับไคลเอนต์ที่เชื่อมต่อ เมื่อขุดลงไปในปัญหาฉันรู้ว่าพารามิเตอร์ของเคอร์เนลเหล่านี้ควรปรับลงเพื่อให้การเชื่อมต่อ TCP ที่ขาดหายไปถูกสังเกตเห็นในเวลาที่เหมาะสม:

net.ipv4.tcp_keepalive_time = 7200 net.ipv4.tcp_keepalive_probes = 9 net.ipv4.tcp_keepalive_intvl = 75 net.ipv4.tcp_retries2 = 15

ทั้งสี่ข้างต้นเป็นค่าจากอูบุนตู 12.04 เครื่องและดูเหมือนว่าค่าเริ่มต้นเหล่านี้จะไม่เปลี่ยนแปลงจากปัจจุบันค่าเริ่มต้นของลินุกซ์

ดูเหมือนว่าการตั้งค่าเหล่านี้จะมีอคติอย่างมากต่อการเปิดการเชื่อมต่อที่มีอยู่และตระหนี่อย่างยิ่งกับโพรบ Keepalive AIUI ค่าเริ่มต้นtcp_keepalive_timeของ 2 ชั่วโมงหมายถึงเมื่อเรารอการตอบสนองสำหรับโฮสต์ระยะไกลเราจะรออย่างอดทนเป็นเวลา 2 ชั่วโมงก่อนที่จะเริ่มใช้โพรบ Keepalive เพื่อตรวจสอบว่าการเชื่อมต่อของเรายังคงใช้ได้ และถ้าหากรีโมตโฮสต์ไม่ตอบสนองต่อโพรบ Keepalive เราจะลองโพรบ Keepalive 9 ครั้ง ( tcp_keepalive_probes) เว้นระยะห่าง 75 วินาที ( tcp_keepalive_intvl) ดังนั้นนั่นคืออีก 11 นาทีก่อนที่เราจะตัดสินใจว่าการเชื่อมต่อนั้นตายแล้วจริง ๆ

สิ่งนี้ตรงกับสิ่งที่ฉันเห็นในฟิลด์: ตัวอย่างเช่นถ้าฉันเริ่มpsqlเซสชันที่เชื่อมต่อกับอินสแตนซ์ PostgreSQL ระยะไกลโดยมีแบบสอบถามบางคำรอการตอบกลับเช่น

SELECT pg_sleep(30);

และจากนั้นให้เซิร์ฟเวอร์ระยะไกลตายอย่างน่ากลัว (เช่นลดทราฟฟิกไปยังเครื่องนั้น) ฉันเห็นเซสชั่น psql ของฉันรอนานถึง 2 ชั่วโมง 11 นาทีก่อนที่มันจะคิดว่าการเชื่อมต่อนั้นตายแล้ว ดังที่คุณอาจจินตนาการว่าการตั้งค่าเริ่มต้นเหล่านี้ทำให้เกิดปัญหาร้ายแรงสำหรับรหัสที่เราได้พูดคุยกับฐานข้อมูลในระหว่างนั้นกล่าวว่าเป็นเหตุการณ์ความล้มเหลวของฐานข้อมูล การลดลูกบิดเหล่านี้ช่วยได้มาก! และฉันเห็นว่าฉันไม่ได้อยู่คนเดียวในการแนะนำการปรับค่าเริ่มต้นเหล่านี้

ดังนั้นคำถามของฉันคือ:

  • ค่าเริ่มต้นเป็นเช่นนี้มานานแค่ไหนแล้ว?
  • เหตุผลดั้งเดิมที่ทำให้การตั้งค่า TCP เหล่านี้เป็นค่าเริ่มต้นคืออะไร
  • Linux distros ใด ๆ เปลี่ยนค่าเริ่มต้นเหล่านี้หรือไม่

และประวัติอื่น ๆ หรือมุมมองเกี่ยวกับเหตุผลสำหรับการตั้งค่าเหล่านี้จะได้รับการชื่นชม


ข้อมูลบางอย่างที่เกี่ยวข้องที่นี่ ... tldp.org/HOWTO/TCP-Keepalive-HOWTO/usingkeepalive.html
Drav Sloan

โปรดทราบว่าคุณสามารถเปลี่ยนต่อการเชื่อมต่อครั้งแรกที่สามในรหัสลูกค้ากับซ็อกเก็ตตัวเลือกTCP_KEEPIDLE, และTCP_KEEPCNT TCP_KEEPINTVL
wnoise

1
@wnoise จริง ๆ แล้วตั้งแต่ Linux 2.6.37คุณควรระบุตัวเลือก socket TCP_USER_TIMEOUTด้วยเช่นกันแทนที่จะตั้งค่าทั้งnet.ipv4.tcp_retries2ระบบ ของการใช้งานจำนวนมากแน่นอน (เช่น PostgreSQL ในตัวอย่างของฉันที่นี่) ไม่สนับสนุนTCP_USER_TIMEOUTเลย
Josh Kupershmidt

คำตอบ:


6

RFC 1122ระบุไว้ในส่วน 4.2.3.6 ว่าระยะเวลาเก็บไว้ต้องไม่เริ่มต้นเป็นเวลาน้อยกว่าสองชั่วโมง


1
เยี่ยมมากขอบคุณที่ขุดมันขึ้นมา ฉันคิดว่าส่วนใหญ่ตอบคำถามว่าทำไมtcp_keepalive_timeค่าเริ่มต้นถึง 7200 แม้ว่าฉันจะยังคงสนใจในแบบอย่าง / คำอธิบายสำหรับอีกสามการตั้งค่าที่เกี่ยวข้อง
Josh Kupershmidt

การถอดคำตอบของฉันเช่นนี้สามารถตอบคำถามได้ (อย่างน้อยหนึ่งของค่า)
coteyr

1
@ Coteyr ขอบคุณต่อไปฉันขอขอบคุณความพยายาม IIRC มีความคิดเห็นที่น่าสนใจเกี่ยวกับคำตอบของคุณซึ่งบอกว่าในเมล็ด Linux รุ่นก่อนหน้าค่าเริ่มต้นคือ 15 นาที ฉันสนใจวิธี / เหตุผลที่เปลี่ยนเป็น 2 ชั่วโมงหรือตั้งค่าเป็น 15 นาทีในตอนแรก
Josh Kupershmidt
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.