我一直在尝试调整我们的 Ubuntu 14.04 LTS Web 服务器实例,托管 Web 应用程序和反向代理 nginx,以便在给定硬件的情况下处理尽可能多的请求。这是一个具有 8x vCPU 的 c4.2xl EC2 实例。
我在办公室机器上运行了以下两个基准测试工具(不是同时运行):
wrk -c1000 -d2m -t8 --timeout 90 --latency http://api.mysite.com/2/ping
# or
ab -k -n 100000 -c 1000 http://api.mysite.com/2/ping
我看到的是,通过运行,ss -tan | wc -l
我总是在大约 65.5k 个连接中达到最大值TIME-WAIT
我的操作系统设置是:
net.ipv4.ip_local_port_range value="15000 65000"
/etc/security/limits.conf
其中有“www-data hard nofile 100000”/etc/pam.d/common-session*
更新为上述内容
nginx 设置如下:
worker_processes auto; # will result in 8 on this machine
events { worker_connections 8192; multi_accept on; use epoll; }
代理到 nginx 的 api 的上游如下,用于获取非常高的不同 TCP 四元组的最大值,这意味着我几乎从未用完 nginx -> app 中的临时端口:
upstream my_api { server 127.0.0.1:3004; server 127.0.0.2:3004; server 127.0.0.3:3004; [...] }
我的 m3.large 实例也遇到了类似的问题,其最大容量不是 65k,而是 32k。这两个实例的区别在于前者有 2vCPU,后者有 8 个,前者有 7.5GB 内存,后者有 15GB。
这篇文章中描述了类似的问题(扩展到超过 65k 个打开文件(TCP 连接)),但它似乎并不适用于我的情况,因为在我的较小实例中vm.max_map_count
是 65530,但它从未超过 32k 个连接TIME-WAIT
。
我起初以为限制只是#进程*#工作者,但是在较小的实例中,即使我将每个进程的工作者数量提高到 25k,我仍然限制在 32k,所以事实并非如此。
我不知道此时该调整哪个旋钮,我不清楚这些硬性限制可能来自哪里。这里需要一些帮助。
有趣的是,当 TIME-WAIT 达到这个“极限”时,我并没有看到这两台机器的连接被最终拒绝。有可能套接字队列在后台被填满,客户端只是稍后重新尝试建立连接,这就是为什么我没有看到任何永久失败的原因。
更新:
在 c4.8xlarge 实例上,我可以使用完全相同的部署配置在 TIME-WAIT 中获得最多 262k 个连接。即使将 nginx 工作程序数量限制为 1 个也不会改变它。仍然不确定这里的区别是什么。
更新 2:
我强烈怀疑这与不同的实例有关,它们都具有不同的net.ipv4.tcp_max_tw_buckets
值,据我所知,这些值与我所看到的模式完全匹配。
答案1
看看net.ipv4.netfilter.ip_conntrack_max
可调参数。有关更多信息,你可以阅读这篇 ServerFault 帖子
答案2
您的源计算机上的源端口即将用完。
为了识别连接,您需要:源 IP、源端口、目标 IP 和目标端口。由于源 IP、目标 IP 和目标端口在测试中始终相同,因此您只有一个变量:源端口。您的 TCP/IP 堆栈无法处理超过 64k 个不同的源端口(实际上要少一些)。
从单点进行压力测试从来都不是一个好主意,但您可以通过启用 net.ipv4.tcp_tw_recycle 来重用 TIME_WAIT 状态下的端口,从而进一步压缩这一点,但由于积极的端口重用,它可能会给您带来麻烦。