我们有2个nginx服务器在3个php5-fpm服务器前面以1000reqs /秒的速度运行,并且有TCP连接.我们认为一个nginx服务器就足够了,并将所有流量重定向到它.但是,服务器的服务速度不能超过750reqs/sec.它有千兆以太网,总流量不超过100mbits(Debian 6.0)
我们找不到任何理由,谷歌搜索后发现它可能与TCP问题有关.但是我们似乎不太可能通过这个数量的连接和带宽(大约70mbits/sec)进行任何改变.稍后我们将一半的流量重定向回另一个nginx并再次达到1000reqs /秒.
我们一直在关注nginx错误和访问日志.是否有任何工具或文件可以帮助我们找到问题的解决方案?
大多数Linux发行版都有28232个临时端口.服务器为每个连接需要一个短暂端口,以释放新连接的主端口(即http服务器端口80).
因此,如果服务器正在处理由php5-fpm通过TCP生成的内容的1000个请求/秒,那么您将分配2000个端口/秒.实际情况并非如此,可能是5%PHP和95%静态(没有端口分配)和IIRC nginx < - > php-fpm为后续请求保持端口打开.有很多因素可以影响这些数字,但为了论证,让我们说1000端口分配/秒.
从表面上看,这似乎不是问题,但默认情况下,端口不会立即释放并可用于新连接.这种行为有多种原因,我强烈建议在任意更改此处(或其他任何地方)之前彻底了解TCP.
主要是一个称为TIME_WAIT的连接状态(套接字在关闭后等待处理仍在网络中的数据包,netstat手册页)是阻止端口被释放以供重用的原因.在最近的(所有?)linux内核上,TIME_WAIT被硬编码为60秒,根据RFC793,连接可能会在TIME_WAIT中保持最多4分钟!
这意味着至少有1000个端口将被使用至少60秒.在现实世界中,您需要考虑传输时间,保持活动请求(多个请求使用相同的连接)和服务端口(在nginx和后端服务器之间).让我们任意将其降低到750端口/秒.
在~37秒内,所有可用端口都将耗尽(28232/750 = 37).这是一个问题,因为释放端口需要60秒!
要查看正在使用的所有端口,请运行apache bench或类似的东西,以便生成您正在调整的每秒请求数.然后运行:
root:~# netstat -n -t -o | grep timewait
Run Code Online (Sandbox Code Playgroud)
你会得到像(但很多,更多行)的输出:
tcp 0 0 127.0.0.1:40649 127.1.0.2:80 TIME_WAIT timewait (57.58/0/0)
tcp 0 0 127.1.0.1:9000 127.0.0.1:50153 TIME_WAIT timewait (57.37/0/0)
tcp 0 0 127.0.0.1:40666 127.1.0.2:80 TIME_WAIT timewait (57.69/0/0)
tcp 0 0 127.0.0.1:40650 127.1.0.2:80 TIME_WAIT timewait (57.58/0/0)
tcp 0 0 127.0.0.1:40662 127.1.0.2:80 TIME_WAIT timewait (57.69/0/0)
tcp 0 0 127.0.0.1:40663 127.1.0.2:80 TIME_WAIT timewait (57.69/0/0)
tcp 0 0 127.0.0.1:40661 127.1.0.2:80 TIME_WAIT timewait (57.61/0/0)
Run Code Online (Sandbox Code Playgroud)
对于运行的已分配端口总数:
root:~# netstat -n -t -o | wc -l
Run Code Online (Sandbox Code Playgroud)
如果您收到失败的请求,则该号码将达到/接近28232.
如何解决问题?
将短暂端口数量从28232增加到63976.
sysctl -w net.ipv4.ip_local_port_range="1024 65000"
Run Code Online (Sandbox Code Playgroud)允许linux在超时到期之前重用TIME_WAIT端口.
sysctl -w net.ipv4.tcp_tw_reuse="1"
Run Code Online (Sandbox Code Playgroud)其他IP地址.