哪些内核参数或其他设置控制 Linux 服务器上可以打开的 TCP 套接字的最大数量?允许更多连接的权衡是什么?
我注意到在使用ab对 Apache 服务器进行负载测试时,很容易将服务器上的打开连接最大化。如果您不使用允许连接重用的 ab 的 -k 选项,并让它发送超过 10,000 个请求,那么 Apache 会处理前 11,000 个左右的请求,然后停止 60 秒。查看 netstat 输出显示 11,000 个连接处于 TIME_WAIT 状态。显然,这是正常的。出于TCP 可靠性的原因,即使在客户端完成连接后,连接仍会保持默认打开 60 秒。
看起来这将是一种对服务器进行 DoS 的简单方法,我想知道通常的调整和预防措施是什么。
这是我的测试输出:
# ab -c 5 -n 50000 http://localhost/
This is ApacheBench, Version 2.0.40-dev <$Revision: 1.146 $> apache-2.0
Copyright 1996 Adam Twiss, Zeus Technology Ltd, http://www.zeustech.net/
Copyright 2006 The Apache Software Foundation, http://www.apache.org/
Benchmarking localhost (be patient)
Completed 5000 requests
Completed 10000 requests
apr_poll: The timeout specified has expired (70007)
Total of 11655 requests completed
这是我在测试期间运行的 netstat 命令:
# netstat --inet -p | grep "localhost:www" | sed -e 's/ \+/ /g' | cut -d' ' -f 1-4,6-7 | sort | uniq -c
11651 tcp 0 0 localhost:www TIME_WAIT -
1 tcp 0 1 localhost:44423 SYN_SENT 7831/ab
1 tcp 0 1 localhost:44424 SYN_SENT 7831/ab
1 tcp 0 1 localhost:44425 SYN_SENT 7831/ab
1 tcp 0 1 localhost:44426 SYN_SENT 7831/ab
1 tcp 0 1 localhost:44428 SYN_SENT 7831/ab
我终于找到了真正限制连接数的设置:
net.ipv4.netfilter.ip_conntrack_max
. 这被设置为 11,776,无论我设置什么,都是我可以在测试中服务的请求数,然后必须等待tcp_fin_timeout
几秒钟才能获得更多连接。该conntrack
表是内核用来跟踪连接状态的表,因此一旦它已满,内核就会开始丢弃数据包并将其打印在日志中:下一步是让内核回收所有处于该
TIME_WAIT
状态的连接,而不是丢弃数据包。我可以通过打开tcp_tw_recycle
或增加到ip_conntrack_max
大于可用于连接的本地端口数来实现这一点ip_local_port_range
。我想一旦内核离开本地端口,它就会开始回收连接。这使用了更多的内存跟踪连接,但它似乎比打开更好的解决方案,tcp_tw_recycle
因为文档暗示这是危险的。使用此配置,我可以整天运行 ab 并且永远不会用完连接:
该
tcp_max_orphans
设置对我的测试没有任何影响,我不知道为什么。我认为TIME_WAIT
一旦有 8192 个连接,它就会关闭 state 中的连接,但它对我来说并没有这样做。你真的想看看 /proc 文件系统在这方面为你提供了什么。
在最后一页上,您可能会发现您感兴趣的以下内容:
我不认为有一个可调参数可以直接设置它。这属于 TCP/IP 调整的范畴。要找出可以调整的内容,请尝试“man 7 tcp”。sysctl ('man 8 sysctl') 用于设置这些。'sysctl -a | grep tcp' 将显示您可以调整的大部分内容,但我不确定它是否会显示所有内容。此外,除非这已更改,否则打开的 TCP/IP 套接字看起来像文件描述符。因此,该链接中的此部分和下一部分可能就是您要查找的内容。
尝试设置以下以及设置 tcp_fin_timeout。这应该更快地关闭 TIME_WAIT。
库存的 apache(1) 过去预定义为仅支持 250 个并发连接 - 如果您想要更多,可以修改一个头文件以允许更多并发会话。我不知道 Apache 2 是否仍然如此。
此外,您需要添加一个选项,以允许为运行 Apache 的帐户加载更多打开的文件描述符 - 之前的评论未能指出这一点。
请注意您的工作人员设置以及您在 Apache 内部有什么样的保活超时,您一次运行了多少备用服务器,以及这些额外进程被杀死的速度有多快。
您可以减少在 TIME_WAIT 状态下花费的时间(设置 net.ipv4.tcp_fin_timeout)。您可以用 YAWS 或 nginx 或类似的东西替换 Apache。
更多连接的权衡通常涉及内存使用,如果您有一个分叉进程,那么很多子进程会占用您的 CPU。
可以在单个 IP 地址上打开的套接字的绝对数量是 2^16,并且由 TCP/UDP 定义,而不是内核定义。
Apache HTTP 服务器基准测试工具ab在 2.4 版本中具有-s 超时选项。另请参见ab (Apache Bench) 错误:apr_poll: The timeout specified has expired (70007) on Windows。
此选项可以解决您的问题。