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!
tcp_tw_recycle
und aktivierttcp_tw_reuse
?