Нещодавно я витратив досить багато часу на пошук проблеми у виробництві, коли зникнення сервера баз даних призвело б до двох годин (довго чекати 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
Чотири наведені вище значення - від машини Ubuntu 12.04, і схоже, що ці параметри за замовчуванням не змінюються від поточних стандартних ядер Linux .
Ці налаштування здаються сильно упередженими щодо збереження існуючого з’єднання відкритим і надзвичайно скупими з чутливими зондами. AIUI, за замовчуванням tcp_keepalive_time
2 години означає, що коли ми будемо чекати відповіді на віддалений хост, ми будемо терпляче чекати 2 години, перш ніж ініціювати зонд для збереження, щоб переконатися, що наше з'єднання все-таки дійсне. І тоді, якщо віддалений хост не реагує на зонд кепаліву, ми повторюємо ці зонди киепалів 9 разів ( tcp_keepalive_probes
), відстань між ними 75 секунд ( tcp_keepalive_intvl
), тож це зайві 11 хвилин, перш ніж ми вирішимо, що з'єднання справді мертве.
Це відповідає тому, що я бачив у цьому полі: наприклад, якщо я запускаю psql
сеанс, підключений до віддаленого екземпляра PostgreSQL, із запитом, що чекає відповіді, наприклад
SELECT pg_sleep(30);
а потім віддалений сервер загине жахливою смертю (наприклад, скинути трафік на цю машину), я бачу, як мій сеанс psql чекав до 2 годин і 11 хвилин, перш ніж він з'ясує, що його зв'язок помер. Як ви можете собі уявити, ці налаштування за замовчуванням спричиняють серйозні проблеми для коду, про який ми говоримо з базою даних під час, скажімо, події відмови в базі даних. Відключення цих ручок допомогло дуже багато! І я бачу, що я не один в тому, щоб рекомендувати ці параметри за замовчуванням коригуватися.
Отже, мої запитання:
- Скільки часу за замовчуванням було таке?
- Яке оригінальне обґрунтування для встановлення стандартних параметрів TCP?
- Чи змінюють якісь дистрибутиви Linux ці значення за замовчуванням?
І будь-яка інша історія чи погляд на обґрунтування цих параметрів буде вдячний.
TCP_KEEPIDLE
, TCP_KEEPCNT
і TCP_KEEPINTVL
.
TCP_USER_TIMEOUT
, а не встановлювати net.ipv4.tcp_retries2
загальносистемний. Звичайно, багато програм (наприклад, PostgreSQL в моєму прикладі тут) ще не підтримують TCP_USER_TIMEOUT
.