TIME_WAIT-Verbindungen werden nach Ablauf der Zeitüberschreitung nicht bereinigt

7

Ich teste einen meiner Server mit einem konstanten Strom neuer Netzwerkverbindungen, der tcp_fin_timeoutauf 60 eingestellt ist. Wenn ich also einen konstanten Strom von etwa 100 Anfragen pro Sekunde sende, würde ich einen gleitenden Durchschnitt von erwarten 6000 (60 * 100) Verbindungen in einem TIME_WAITZustand, dies geschieht, aber wenn netstatich (mit -o) nachschaue, um die Timer zu sehen, sehe ich Verbindungen wie:

TIME_WAIT   timewait (0.00/0/0)

Wo ihre Zeitüberschreitung abgelaufen ist, aber die Verbindung immer noch besteht, gehen mir schließlich die Verbindungen aus. Weiß jemand, warum diese Verbindungen nicht bereinigt werden? Wenn ich aufhöre, neue Verbindungen herzustellen, verschwinden sie schließlich, aber während ich ständig neue Verbindungen herstelle, scheint es, als ob der Kernel keine Chance bekommt, sie zu bereinigen? Gibt es noch andere Konfigurationsoptionen, die ich einstellen muss, um die Verbindungen zu entfernen, sobald sie abgelaufen sind?

Auf dem Server läuft Ubuntu und mein Webserver ist Nginx. Es gibt auch iptables mit Verbindungsverfolgung, nicht sicher, ob dies dazu führen würde, dass diese TIME_WAITVerbindungen weiterleben.

Danke Mark.

Mark D.
quelle
Haben Sie tcp_tw_recycleund aktiviert tcp_tw_reuse?
Quanten
Nachdem ich diese Werte gelesen hatte, wollte ich keinen von beiden aktivieren, da sie als problematisch gemeldet wurden und wie eine Optimierung wirkten. Ich bin damit einverstanden, dass das Zeitlimit 60 Sekunden beträgt, solange die Ports nach dieser Zeit verschwinden
Mark D

Antworten:

3

Dieses Problem war interessant, wie ich mich oft gefragt habe. Ich habe ein paar Tests gemacht und einige interessante Ergebnisse gefunden. Wenn ich eine Verbindung zu einem Server öffne und 60 Sekunden warte, wurde sie ausnahmslos bereinigt (nie auf 0,00 / 0/0 gebracht). Wenn ich 100 Verbindungen geöffnet habe, wurden auch diese nach 60 Sekunden bereinigt. Wenn ich 101 Verbindungen öffnen würde, würde ich Verbindungen in dem Zustand sehen, den Sie menitonisiert haben (den ich auch zuvor gesehen habe). Und sie scheinen ungefähr 120s oder 2xMSL (was 60 ist) zu dauern, unabhängig davon, auf was fin_timeout eingestellt ist. Ich habe ein bisschen im Kernel-Quellcode gegraben und herausgefunden, was meiner Meinung nach der "Grund" ist. Es scheint Code zu geben, der versucht, die Anzahl der Sockets zu begrenzen, die pro 'Zyklus' auftreten. Die Zyklusfrequenz selbst wird auf einer Skala basierend auf HZ eingestellt:

linux-source-2.6.38/include/net/inet_timewait_sock.h:
     35 #define INET_TWDR_RECYCLE_SLOTS_LOG     5
     36 #define INET_TWDR_RECYCLE_SLOTS         (1 << INET_TWDR_RECYCLE_SLOTS_LOG)
     37 
     38 /*
     39  * If time > 4sec, it is "slow" path, no recycling is required,
     40  * so that we select tick to get range about 4 seconds.
     41  */
     42 #if HZ <= 16 || HZ > 4096
     43 # error Unsupported: HZ <= 16 or HZ > 4096
     44 #elif HZ <= 32
     45 # define INET_TWDR_RECYCLE_TICK (5 + 2 - INET_TWDR_RECYCLE_SLOTS_LOG)
     46 #elif HZ <= 64
     47 # define INET_TWDR_RECYCLE_TICK (6 + 2 - INET_TWDR_RECYCLE_SLOTS_LOG)
     48 #elif HZ <= 128
     49 # define INET_TWDR_RECYCLE_TICK (7 + 2 - INET_TWDR_RECYCLE_SLOTS_LOG)
     50 #elif HZ <= 256
     51 # define INET_TWDR_RECYCLE_TICK (8 + 2 - INET_TWDR_RECYCLE_SLOTS_LOG)
     52 #elif HZ <= 512
     53 # define INET_TWDR_RECYCLE_TICK (9 + 2 - INET_TWDR_RECYCLE_SLOTS_LOG)
     54 #elif HZ <= 1024
     55 # define INET_TWDR_RECYCLE_TICK (10 + 2 - INET_TWDR_RECYCLE_SLOTS_LOG)
     56 #elif HZ <= 2048
     57 # define INET_TWDR_RECYCLE_TICK (11 + 2 - INET_TWDR_RECYCLE_SLOTS_LOG)
     58 #else
     59 # define INET_TWDR_RECYCLE_TICK (12 + 2 - INET_TWDR_RECYCLE_SLOTS_LOG)
     60 #endif
     61 
     62 /* TIME_WAIT reaping mechanism. */
     63 #define INET_TWDR_TWKILL_SLOTS  8 /* Please keep this a power of 2. */
The number of slots is also set here:
     65 #define INET_TWDR_TWKILL_QUOTA 100

Im aktuellen Timewait-Code können Sie sehen, wo das Anführungszeichen verwendet wird, um das Beenden von TIME_WAIT-Verbindungen zu beenden, wenn bereits zu viele ausgeführt wurden:

linux-source-2.6.38/net/ipv4/inet_timewait_sock.c:
    213 static int inet_twdr_do_twkill_work(struct inet_timewait_death_row *twdr,
    214                                     const int slot)
    215 {
...
    240                 if (killed > INET_TWDR_TWKILL_QUOTA) {
    241                         ret = 1;
    242                         break;
    243                 }

Weitere Informationen dazu, warum HZ auf das eingestellt ist, was es ist, finden Sie hier: http://kerneltrap.org/node/5411 Es ist jedoch nicht ungewöhnlich, es zu erhöhen. Ich denke jedoch, dass es normalerweise üblicher ist, tw_reuse / recyceln zu ermöglichen, um diesen Eimer- / Quotenmechanismus zu umgehen (was mir jetzt, da ich darüber gelesen habe, verwirrend erscheint, eine Erhöhung der HZ wäre eine viel sicherere und sauberere Lösung). Ich habe dies als Antwort gepostet, aber ich denke, es könnte hier mehr Diskussionen darüber geben, wie man es richtig beheben kann. Danke für die interessante Frage!

Polynom
quelle
Könnten Sie sich das ansehen, ich habe das gleiche Centos 5Problem , aber anscheinend hat es viel TIME_WAIT-Socket, stackoverflow.com/questions/24426014/…
secmask
2

Anstelle der Verwendung tcp_tw_recycle = 1Verwenden Sie die folgenden:

tcp_tw_reuse = 1

Recyceln Sie Berichte, die beschädigt werden sollen, und funktionieren in einigen Fällen nicht, wenn Sie NAT oder Load Balancing verwenden.

Farzan
quelle
0

net.ipv4.tcp_fin_timeout ist standardmäßig 60s. Mir war nie klar, warum Sockets dazu neigen, länger als diese Grenze in TIME_WAIT zu bleiben.

tcp_tw_recycle ist angeblich kaputt, ich weiß es nicht, da ich es nicht benutze. Sie müssen wahrscheinlich tcp_tw_reuse auf 1 setzen, aber dies wird angeblich Probleme mit NAT verursachen.

Joshua Hoblitt
quelle
tcp_fin_timeout hat keinen Einfluss auf TIME_WAIT.
Scott Carey