nginx连接限制

时间:2012-11-26 14:35:20

标签: nginx php

我们有2个nginx服务器在3个php5-fpm服务器前面以1000reqs /秒的速度完美运行,并且有TCP连接。我们认为一个nginx服务器就足够了,并将所有流量重定向到它。但是,服务器的服务速度不能超过750reqs / sec。它有千兆以太网,总流量不超过100mbits(Debian 6.0)

我们找不到任何理由,谷歌搜索后发现它可能与TCP问题有关。但是我们似乎不太可能通过这个数量的连接和带宽(大约70mbits / sec)进行任何改变。稍后我们将一半的流量重定向回另一个nginx并再次达到1000reqs /秒。

我们一直在关注nginx错误和访问日志。是否有任何工具或文件可以帮助我们找到问题的解决方案?

1 个答案:

答案 0 :(得分:6)

大多数Linux发行版都有28232 ephemeral ports available。服务器为每个连接需要一个短暂端口,以释放新连接的主端口(即http服务器端口80)。

因此,如果服务器通过TCP对php5-fpm生成的内容处理1000个请求/秒,那么您将分配2000个端口/秒。实际情况并非如此,可能是5%PHP和95%静态(无端口分配)和IIRC nginx< - > php-fpm为后续请求保持端口打开。有很多因素可以影响这些数字,但为了论证,让我们说1000端口分配/秒。

从表面上看,这似乎不是问题,但默认情况下,端口不会立即释放并可用于新连接。这种行为有多种原因,我强烈建议您在任意详细地(或其他任何地方)进行更改之前彻底了解TCP

主要是一个称为TIME_WAIT的连接状态(套接字在关闭后等待处理仍然在网络中的数据包,netstat man page)是阻止端口被释放以供重用的原因。在最近的(所有?)linux内核上,TIME_WAIT被硬编码为60秒,根据RFC793,连接可能会在TIME_WAIT中保持最多四分钟!

这意味着至少有1000个端口将被使用至少60秒。在现实世界中,您需要考虑传输时间,保持活动请求(多个请求使用相同的连接)和服务端口(在nginx和后端服务器之间)。让我们任意将其降低到750端口/秒。

在~37秒内,所有可用端口都将耗尽(28232/750 = 37)。这是一个问题,因为释放端口需要60秒!

要查看正在使用的所有端口,请运行apache bench或类似的东西,以便生成您正在调整的每秒请求数。然后运行:

root:~# netstat -n -t -o | grep timewait

你会得到像(但很多,更多行)的输出:

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)

对于已分配端口的运行总计:

root:~# netstat -n -t -o | wc -l

如果您收到失败的请求,则该号码将接近/接近28232。

如何解决问题?

  1. 将短暂端口数量从28232增加到63976。

    sysctl -w net.ipv4.ip_local_port_range="1024 65000"
    
  2. 允许linux在超时到期之前重用TIME_WAIT端口。

    sysctl -w net.ipv4.tcp_tw_reuse="1"
    
  3. 其他IP地址。