J'ai passé pas mal de temps à rechercher un problème en production récemment, où la disparition d'un serveur de base de données entraînerait un blocage pouvant aller jusqu'à 2 heures (longue attente d'un poll()
appel dans la bibliothèque client libpq) pour un client connecté. En creusant le problème, je me suis rendu compte que ces paramètres du noyau devaient être ajustés à fond pour que les connexions TCP rompues soient remarquées en temps opportun:
net.ipv4.tcp_keepalive_time = 7200
net.ipv4.tcp_keepalive_probes = 9
net.ipv4.tcp_keepalive_intvl = 75
net.ipv4.tcp_retries2 = 15
Les quatre valeurs ci-dessus proviennent d'une machine Ubuntu 12.04, et il semble que ces valeurs par défaut soient inchangées par rapport aux valeurs par défaut actuelles du noyau Linux .
Ces paramètres semblent être fortement biaisés pour garder une connexion existante ouverte et être extrêmement avares de sondes keepalive. AIUI, la valeur par défaut tcp_keepalive_time
de 2 heures signifie que lorsque nous attendons une réponse pour un hôte distant, nous attendrons patiemment 2 heures avant de lancer une sonde keepalive pour vérifier que notre connexion est toujours valide. Et puis, si l'hôte distant ne répond pas à une sonde keepalive, nous réessayons ces sondes keepalive 9 fois ( tcp_keepalive_probes
), espacées de 75 secondes ( tcp_keepalive_intvl
), donc c'est 11 minutes supplémentaires avant de décider que la connexion est vraiment morte.
Cela correspond à ce que j'ai vu sur le terrain: par exemple, si je démarre une psql
session connectée à une instance PostgreSQL distante, avec une requête en attente d'une réponse, par exemple
SELECT pg_sleep(30);
et que le serveur distant meure une mort horrible (par exemple, laisser tomber le trafic vers cette machine), je vois ma session psql attendre jusqu'à 2 heures et 11 minutes avant de comprendre que sa connexion est morte. Comme vous pouvez l'imaginer, ces paramètres par défaut provoquent de graves problèmes pour le code dont nous parlons à une base de données lors, par exemple, d'un événement de basculement de base de données. Baisser ces boutons a beaucoup aidé! Et je vois que je ne suis pas le seul à recommander que ces valeurs par défaut soient ajustées.
Mes questions sont donc:
- Depuis combien de temps les défauts sont-ils comme ça?
- Quelle était la justification d'origine pour faire de ces paramètres TCP la valeur par défaut?
- Des distributions Linux modifient-elles ces valeurs par défaut?
Et toute autre histoire ou perspective sur la justification de ces paramètres serait appréciée.
TCP_KEEPIDLE
, TCP_KEEPCNT
et TCP_KEEPINTVL
.
TCP_USER_TIMEOUT
, au lieu de la définir net.ipv4.tcp_retries2
à l'échelle du système. Bien sûr, de nombreuses applications (comme PostgreSQL dans mon exemple ici) ne sont pas TCP_USER_TIMEOUT
encore prises en charge .