我正在对服务器进行编程,我的连接数似乎受到了限制,因为即使我将连接数设置为“无限”,我的带宽也没有饱和。
如何增加或消除我的 Ubuntu Linux 机器一次可以打开的最大连接数?操作系统是否限制了这一点,还是路由器或 ISP?或者是别的什么?
最大连接数受到客户端和服务器端的某些限制的影响,尽管略有不同。
在客户端:增加临时端口范围,并减少 tcp_fin_timeout
要找出默认值:
sysctl net.ipv4.ip_local_port_range
sysctl net.ipv4.tcp_fin_timeout
临时端口范围定义主机可以从特定 IP 地址创建的最大出站套接字数。 fin_timeout
定义了这些套接字保持 TIME_WAIT
状态(使用一次后无法使用)的最短时间。通常的系统默认值是:
net.ipv4.ip_local_port_range = 32768 61000
net.ipv4.tcp_fin_timeout = 60
这基本上意味着您的系统不能始终保证每秒超过 (61000 - 32768) / 60 = 470
个套接字。如果您对此不满意,可以从增加 port_range
开始。如今,将范围设置为 15000 61000
很常见。您可以通过减小 fin_timeout
来进一步提高可用性。假设您两者都做,您应该更容易看到每秒超过 1500 个出站连接。
要更改值:
sysctl net.ipv4.ip_local_port_range="15000 61000"
sysctl net.ipv4.tcp_fin_timeout=30
以上不应解释为影响系统每秒建立出站连接能力的因素。但是,这些因素会影响系统在大量“活动”期间以可持续的方式处理并发连接的能力。
tcp_tw_recycle
& 的典型 Linux 机器上的默认 Sysctl 值tcp_tw_reuse
将是
net.ipv4.tcp_tw_recycle=0
net.ipv4.tcp_tw_reuse=0
这些不允许来自“已使用”套接字(处于等待状态)的连接,并强制套接字持续完整的 time_wait
周期。我建议设置:
sysctl net.ipv4.tcp_tw_recycle=1
sysctl net.ipv4.tcp_tw_reuse=1
这允许在 time_wait
状态下快速循环套接字并重新使用它们。但在您进行此更改之前,请确保这不会与您将用于需要这些套接字的应用程序的协议冲突。请务必阅读帖子 "Coping with the TCP TIME-WAIT" from Vincent Bernat 以了解其含义。 net.ipv4.tcp_tw_recycle
选项对于面向公众的服务器来说是一个很大的问题,因为它无法处理来自同一 NAT 设备后面的两台不同计算机的连接,这是一个难以检测并等待着你的问题。请注意,从 Linux 4.12 开始,net.ipv4.tcp_tw_recycle
是 removed。
在服务器端: net.core.somaxconn
值具有重要作用。它限制排队到侦听套接字的最大请求数。如果您确定服务器应用程序的能力,请将其从默认的 128 提高到 128 到 1024 之类的值。现在您可以通过将应用程序的侦听调用中的侦听积压变量修改为相等或更高的整数来利用这种增加。
sysctl net.core.somaxconn=1024
txqueuelen
您的以太网卡的参数也有一定的作用。默认值为 1000,因此如果您的系统可以处理,请将它们提高到 5000 甚至更多。
ifconfig eth0 txqueuelen 5000
echo "/sbin/ifconfig eth0 txqueuelen 5000" >> /etc/rc.local
同样提高 net.core.netdev_max_backlog
和 net.ipv4.tcp_max_syn_backlog
的值。它们的默认值分别为 1000 和 1024。
sysctl net.core.netdev_max_backlog=2000
sysctl net.ipv4.tcp_max_syn_backlog=2048
现在请记住通过在 shell 中增加 FD ulimts 来启动客户端和服务器端应用程序。
除了上述之外,程序员使用的一种更流行的技术是减少 tcp write 调用的数量。我自己的偏好是使用缓冲区,在其中我将希望发送到客户端的数据推送到客户端,然后在适当的时候将缓冲的数据写出到实际的套接字中。这种技术允许我使用大数据包,减少碎片,降低我在用户空间和内核级别的 CPU 利用率。
有几个变量可以设置最大连接数。最有可能的是,您首先用完了文件编号。检查ulimit -n
。之后,/proc
中有设置,但默认为数万。
更重要的是,听起来你做错了什么。单个 TCP 连接应该能够使用两方之间的所有带宽;如果不是:
检查您的 TCP 窗口设置是否足够大。 Linux 默认值适用于除真正快速的 inet 链接(数百 mbps)或快速卫星链接之外的所有内容。您的带宽*延迟积是多少?
使用 ping 大数据包检查数据包丢失(ping -s 1472 ...)
检查速率限制。在 Linux 上,这是用 tc 配置的
使用例如 iperf 确认您认为存在的带宽确实存在
确认您的协议是健全的。记住延迟。
如果这是一个千兆+ LAN,您可以使用巨型数据包吗?你是?
可能我理解错了。也许你正在做类似 Bittorrent 的东西,你需要大量的连接。如果是这样,您需要弄清楚您实际使用了多少个连接(尝试 netstat
或 lsof
)。如果这个数字很大,您可以:
有很多带宽,例如 100mbps+。在这种情况下,您实际上可能需要增加 ulimit -n。尽管如此,大约 1000 个连接(我的系统上的默认值)还是相当多的。
有网络问题会减慢您的连接速度(例如,数据包丢失)
有其他东西会减慢您的速度,例如 IO 带宽,特别是如果您正在寻找。你检查过iostat -x 吗?
此外,如果您使用的是消费级 NAT 路由器(Linksys、Netgear、DLink 等),请注意,您可能会因数千个连接而超出其能力。
我希望这能提供一些帮助。你真的在问一个网络问题。
为了改进@derobert 给出的答案,
您可以通过 catting nf_conntrack_max
确定您的操作系统连接限制。例如:
cat /proc/sys/net/netfilter/nf_conntrack_max
您可以使用以下脚本来计算与给定 tcp 端口范围的 TCP 连接数。默认情况下 1-65535
。
这将确认您是否正在最大化您的操作系统连接限制。
这是脚本。
#!/bin/bash
OS=$(uname)
case "$OS" in
'SunOS')
AWK=/usr/bin/nawk
;;
'Linux')
AWK=/bin/awk
;;
'AIX')
AWK=/usr/bin/awk
;;
esac
netstat -an | $AWK -v start=1 -v end=65535 ' $NF ~ /TIME_WAIT|ESTABLISHED/ && $4 !~ /127\.0\.0\.1/ {
if ($1 ~ /\./)
{sip=$1}
else {sip=$4}
if ( sip ~ /:/ )
{d=2}
else {d=5}
split( sip, a, /:|\./ )
if ( a[d] >= start && a[d] <= end ) {
++connections;
}
}
END {print connections}'
which awk
是您确定 awk 路径的朋友,SunOS 也有指向它的链接 :)
which
依赖于位于 PATH
中的程序,在这种情况下,您可以只使用 awk
而不是提供完整路径。 (也就是说,我不确定脚本中的解决方案是否更接近完美,但这不是脚本的内容)。
awk
位置,但假定 shell 始终是 /bin/bash
(专业提示:AIX5/6 默认情况下甚至没有 bash)。
awk
检测有用吗?就我个人而言,我只是假设有一个正确的 PATH
,但一个合理的替代方案可能分别是 /usr/bin/env awk
和 /usr/bin/env bash
。对于它的价值,它在我的 Linux 系统上的位置错误。它在 /usr/bin/awk
而不是 /bin/awk
在应用程序级别,开发人员可以执行以下操作:
从服务器端:
检查负载均衡器(如果有)是否正常工作。将慢速 TCP 超时转换为 503 快速即时响应,如果您的负载均衡器正常工作,它应该选择工作资源来提供服务,这比挂在那里有意外的错误消息要好。
例如:如果你使用的是节点服务器,你可以从 npm 使用 toobusy。实现类似:
var toobusy = require('toobusy');
app.use(function(req, res, next) {
if (toobusy()) res.send(503, "I'm busy right now, sorry.");
else next();
});
为什么是 503?以下是一些关于过载的好见解:http://ferd.ca/queues-don-t-fix-overload.html
我们也可以在客户端做一些工作:
尝试对呼叫进行批量分组,减少客户端和服务器的流量和总请求数。尝试构建一个缓存中间层来处理不必要的重复请求。
(61000 - 32768) / 60 = 470 sockets per second
。你能详细说明一下吗?