如何减少 TIME_WAIT 中的套接字数量?

Ale*_*ysh 41 ubuntu nginx linux-networking high-load

Ubuntu 服务器 10.04.1 x86

我有一台在 nginx 后面带有 FCGI HTTP 服务的机器,它为许多不同的客户端提供许多小的 HTTP 请求。(高峰时段每秒大约 230 个请求,平均响应大小为 650 字节,每天有数百万个不同的客户端。)

结果,我有很多套接字,挂在 TIME_WAIT 中(使用下面的 TCP 设置捕获图表):

时间的等待

我想减少套接字的数量。

除了这个我还能做什么?

$ cat /proc/sys/net/ipv4/tcp_fin_timeout
1
$ cat /proc/sys/net/ipv4/tcp_tw_recycle
1
$ cat /proc/sys/net/ipv4/tcp_tw_reuse
1

更新:有关机器上实际服务布局的一些详细信息:

客户端-----TCP-socket--> nginx(负载均衡器反向代理) 
       -----TCP-socket--> nginx (worker) 
       --domain-socket--> fcgi-software
                          --single-persistent-TCP-socket--> Redis
                          --single-persistent-TCP-socket--> MySQL (其他机器)

我可能应该切换负载平衡器 --> 工作线程连接到域套接字,但关于 TIME_WAIT 套接字的问题仍然存在——我计划很快在单独的机器上添加第二个工作线程。在这种情况下将无法使用域套接字。

Kyl*_*ndt 32

您应该做的一件事是修复net.ipv4.tcp_fin_timeout=1. 那太低了,你可能不应该比 30 低得多。

因为这是在 nginx 后面。这是否意味着 nginx 充当反向代理?如果是这种情况,那么您的连接是 2x(一个到客户端,一个到您的 Web 服务器)。你知道这些插座属于哪一端吗?

更新:
fin_timeout 是它们在 FIN-WAIT-2 中停留的时间(来自networking/ip-sysctl.txt内核文档):

tcp_fin_timeout - INTEGER
        Time to hold socket in state FIN-WAIT-2, if it was closed
        by our side. Peer can be broken and never close its side,
        or even died unexpectedly. Default value is 60sec.
        Usual value used in 2.2 was 180 seconds, you may restore
        it, but remember that if your machine is even underloaded WEB server,
        you risk to overflow memory with kilotons of dead sockets,
        FIN-WAIT-2 sockets are less dangerous than FIN-WAIT-1,
        because they eat maximum 1.5K of memory, but they tend
        to live longer. Cf. tcp_max_orphans.
Run Code Online (Sandbox Code Playgroud)

我认为您可能只需要让 Linux 将 TIME_WAIT 套接字编号保持在它们上看起来可能是 32k 的上限,这就是 Linux 回收它们的地方。这个 32k 在这个链接中被提及:

另外,我发现 /proc/sys/net/ipv4/tcp_max_tw_buckets 令人困惑。尽管默认设置为 180000,但当我的系统上有 32K TIME_WAIT 套接字时,我看到 TCP 中断,而不管最大 tw 存储桶。

此链接还表明 TIME_WAIT 状态为 60 秒,并且无法通过 proc 进行调整。

随机有趣的事实:
您可以使用 netstat 为每个套接字查看 timewait 上的计时器netstat -on | grep TIME_WAIT | less

Reuse Vs Recycle:
这些有点有趣,它读起来就像重用启用 time_Wait 套接字的重用,而 recycle 将其置于 TURBO 模式:

tcp_tw_recycle - BOOLEAN
        Enable fast recycling TIME-WAIT sockets. Default value is 0.
        It should not be changed without advice/request of technical
        experts.

tcp_tw_reuse - BOOLEAN
        Allow to reuse TIME-WAIT sockets for new connections when it is
        safe from protocol viewpoint. Default value is 0.
        It should not be changed without advice/request of technical
        experts.
Run Code Online (Sandbox Code Playgroud)

我不建议使用 net.ipv4.tcp_tw_recycle 因为它会导致 NAT 客户端出现问题

也许你可以尝试不打开这两个,看看它有什么效果(一次尝试一个,看看它们是如何独立工作的)?我会用netstat -n | grep TIME_WAIT | wc -l比穆宁更快的反馈。

  • 哦,这是一个不错的单行:`netstat -an|awk '/tcp/ {print $6}'|sort|uniq -c`。所以@Alex,如果 Munin 不喜欢,也许可以深入了解它如何监控这些统计数据。也许唯一的问题是穆宁给了你错误的数据:-) (4认同)
  • 我会说“30”或“20”。试试看。你有很多负载,所以很多 TIME_WAIT 是有道理的。 (2认同)