我正在用一个连续不断的新networking连接来testing我的一台服务器, tcp_fin_timeout设置为60,所以如果我发送一个类似于每秒100个请求的连续数据stream,我期望看到一个滚动平均值在TIME_WAIT状态下有6000(60 * 100)个连接,这种情况正在发生,但是在netstat (使用-o)查看计时器时,我看到如下连接:
TIME_WAIT timewait (0.00/0/0)
他们的超时时间已经过期,但是连接仍然悬而未决,于是我终于用完了连接。 任何人都知道为什么这些连接不清理? 如果我停止创build新的连接,它们最终会消失,但是当我不断创build新的连接时,他们不会这样做,好像内核没有机会清理它们。 有一些其他的configuration选项,我需要设置为删除连接,只要他们已经过期?
服务器运行的是Ubuntu,我的web服务器是nginx。 它也有连接跟踪的iptables,不知道这是否会导致这些TIME_WAIT连接生活。
谢谢马克。
这个问题很有趣,因为我经常想知道自己。 我做了一些testing,发现了一些有趣的结果。 如果我打开一个连接到服务器,并等待60秒,它总是清理(从来没有达到0.00 / 0/0)。 如果我打开100个连接,60秒后也清理干净。 如果我打开了101个连接,我会开始看到你所在的状态下的连接(我以前也见过)。 而且,无论fin_timeout设置为什么,它们似乎都会持续大约120s或2xMSL(即60)。 我在内核源代码中做了一些挖掘,发现我认为是“原因”。 似乎有一些代码试图限制每个“周期”发生的套接字数量。 循环频率本身是基于HZ的比例设置的:
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
在实际的等待代码中,你可以看到它使用引用的地方,如果它已经做了太多的事情,停止closuresTIME_WAIT连接:
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 }
这里有更多关于为什么HZ被设置为什么的信息: http : //kerneltrap.org/node/5411但增加它并不罕见。 但是我认为通常情况下,通过回收/回收来绕开这个桶/配额机制(这个问题让我感到困惑,现在我已经读了这个机制,增加HZ将是一个更安全和更干净的解决scheme)。 我发表了这个答案,但是我认为在这里可以有更多的讨论,解决这个问题的“正确方法”是什么。 感谢有趣的问题!
而不是使用tcp_tw_recycle = 1使用以下内容:
tcp_tw_reuse = 1
当您使用NAT或负载平衡时,Recyle报告被破坏,在某些情况下不起作用。
net.ipv4.tcp_fin_timeout默认为60秒。 我从来没有清楚为什么套接字在TIME_WAIT的时间比这个限制更长。
据说tcp_tw_recycle被破坏,我不知道,因为我不使用它。 您可能需要将tcp_tw_reuse设置为1,但据推测这会导致NAT问题。