Ich habe in letzter Zeit einige Zeit damit verbracht, ein Problem in der Produktion aufzuspüren, bei dem das Verschwinden eines Datenbankservers poll()
für einen verbundenen Client zu einem Stillstand von bis zu 2 Stunden (lange Wartezeit auf einen Aufruf in der libpq-Clientbibliothek) führte. Als ich mich mit dem Problem befasste, wurde mir klar, dass diese Kernel-Parameter nach unten korrigiert werden müssen, damit getrennte TCP-Verbindungen rechtzeitig erkannt werden:
net.ipv4.tcp_keepalive_time = 7200
net.ipv4.tcp_keepalive_probes = 9
net.ipv4.tcp_keepalive_intvl = 75
net.ipv4.tcp_retries2 = 15
Die vier oben genannten Werte stammen von einem Ubuntu 12.04-Computer und es sieht so aus, als wären diese Standardwerte unverändert gegenüber den aktuellen Standardwerten des Linux-Kernels .
Diese Einstellungen scheinen stark darauf ausgerichtet zu sein, eine bestehende Verbindung offen zu halten, und mit Keepalive-Tests äußerst sparsam umzugehen. AIUI, die Standardeinstellung tcp_keepalive_time
von 2 Stunden, bedeutet, dass wir, wenn wir auf eine Antwort für einen Remote-Host warten, 2 Stunden geduldig warten, bevor wir eine Keepalive-Prüfung einleiten, um sicherzustellen, dass unsere Verbindung noch gültig ist. Wenn der Remote-Host nicht auf einen Keepalive-Test reagiert, wiederholen wir diesen Keepalive-Test neunmal ( tcp_keepalive_probes
) im Abstand von 75 Sekunden ( tcp_keepalive_intvl
). Das sind also zusätzliche elf Minuten, bevor wir feststellen, dass die Verbindung wirklich unterbrochen ist.
Dies entspricht dem, was ich in diesem Bereich gesehen habe: Wenn ich zum Beispiel eine psql
mit einer entfernten PostgreSQL-Instanz verbundene Sitzung starte und eine Abfrage auf eine Antwort wartet, z
SELECT pg_sleep(30);
Wenn der Remote-Server dann einen schrecklichen Tod erleidet (z. B. Datenverkehr auf diesen Computer fallen lässt), wartet meine psql-Sitzung bis zu 2 Stunden und 11 Minuten, bevor sie feststellt, dass die Verbindung unterbrochen ist. Wie Sie sich vielleicht vorstellen können, verursachen diese Standardeinstellungen schwerwiegende Probleme für Code, mit dem wir während eines Datenbank-Failover-Ereignisses mit einer Datenbank gesprochen haben. Das Drehen dieser Knöpfe hat sehr geholfen! Und ich sehe, dass ich nicht alleine bin, wenn ich empfehle, diese Standardeinstellungen anzupassen.
Meine Fragen sind also:
- Wie lange sind die Standardeinstellungen schon so?
- Was war der ursprüngliche Grund dafür, diese TCP-Einstellungen als Standard festzulegen?
- Ändern Linux-Distributionen diese Standardwerte?
Und jede andere Geschichte oder Perspektive auf die Begründung für diese Einstellungen wäre dankbar.
TCP_KEEPIDLE
, TCP_KEEPCNT
und TCP_KEEPINTVL
.
TCP_USER_TIMEOUT
, anstatt sie systemweit einzustellennet.ipv4.tcp_retries2
. Natürlich werden viele Anwendungen (wie hier PostgreSQL in meinem Beispiel) noch nicht unterstützt TCP_USER_TIMEOUT
.