我通过一个新的网络连接流来点击它来对我的一个服务器进行压力测试,tcp_fin_timeout设置为60,所以如果我发送一个每秒100个请求的常量流,我希望看到滚动平均值处于TIME_WAIT状态的6000(60 * 100)个连接,这种情况正在发生,但是查看netstat(使用-o)查看定时器,我看到如下连接:
TIME_WAIT timewait (0.00/0/0)
他们的超时已经到期,但连接仍然存在,我最终耗尽了连接.任何人都知道为什么这些连接不清理?如果我停止创建新连接,他们最终会消失,但是当我不断创建新连接时,他们却没有,似乎内核没有机会清理它们?是否有一些其他配置选项我需要设置为一旦过期就删除连接?
服务器正在运行Ubuntu,我的Web服务器是Nginx.它还具有连接跟踪的iptables,不确定是否会导致这些TIME_WAIT连接继续存在.
谢谢
标记.
解决方法
这个问题很有意思,因为我经常想知道自己.我做了几次测试,发现了一些有趣的结果.如果我打开一个连接到服务器并等待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
在实际的timewait代码中,你可以看到它使用引号停止杀掉TIME_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但增加它并不罕见.然而,我认为通常更常见的是启用tw_reuse / recycle来绕过这个桶/配额机制(现在看来我已经读过这个让我很困惑,增加HZ将是一个更安全和更清洁的解决方案).我发布了这个作为答案,但我认为可以在这里更多地讨论解决它的“正确方法”是什么.谢谢你有趣的问题!