我正在编程一个服务器,似乎我的连接数量是有限的,因为我的带宽没有饱和,即使我已经将连接数量设置为“无限”。
如何增加或消除我的Ubuntu Linux机器一次可以打开的最大连接数?是操作系统限制了这一点,还是路由器或ISP?还是其他原因?
有几个变量可以设置最大连接数。最有可能的情况是,您首先用光了文件号。检查ulimit -n。在此之后,/proc中有设置,但这些设置默认为数万。
ulimit -n
/proc
更重要的是,听起来你好像做错了什么。单个TCP连接应该能够使用双方之间的所有带宽;如果不是:
ping -s 1472
tc
iperf
可能是我误会了。也许你正在做一些像Bittorrent这样的事情,你需要很多连接。如果是这样,你需要弄清楚你实际使用了多少个连接(尝试netstat或lsof)。如果这个数字很大,你可能会:
netstat
lsof
iostat -x
此外,如果您使用的是消费级NAT路由器(Linksys、Netgear、DLink等),请注意数千个连接可能会超出它的能力。
我希望这能提供一些帮助。你其实是在问一个社交问题。
最大连接数受到客户端和放大器的某些限制的影响;服务器端,尽管略有不同。
客户端: 增加临时端口范围,并减少tcp_fin_timeout
tcp_fin_timeout
查询默认值:
sysctl net.ipv4.ip_local_port_range sysctl net.ipv4.tcp_fin_timeout
临时端口范围定义了主机可以从特定ip地址创建的出站套接字的最大数量。fin_timeout定义了这些套接字将保持在TIME_WAIT状态(使用一次后不可用)的最短时间。 通常系统默认值为:
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个出站连接,这更容易。
(61000 - 32768) / 60 = 470
port_range
15000 61000
要更改值:
sysctl net.ipv4.ip_local_port_range="15000 61000" sysctl net.ipv4.tcp_fin_timeout=30
以上不应被解释为影响每秒建立出站连接的系统能力的因素。但是这些因素会影响系统以可持续的方式处理并发连接的能力,以应对大量的“活动”。
典型Linux机器上的默认Sysctl值tcp_tw_recycle &tcp_tw_reuse将是
tcp_tw_recycle
tcp_tw_reuse
net.ipv4.tcp_tw_recycle=0 net.ipv4.tcp_tw_reuse=0
它们不允许来自“已使用”套接字(处于等待状态)的连接,并强制套接字持续整个time_wait周期。我建议设置:
time_wait
sysctl net.ipv4.tcp_tw_recycle=1 sysctl net.ipv4.tcp_tw_reuse=1
这允许在time_wait状态下快速循环套接字并重用它们。但是在进行此更改之前,请确保这与需要这些套接字的应用程序将使用的协议不冲突。确保阅读后Vincent Bernat的“处理TCP TIME-WAIT”以理解其含义。net.ipv4.tcp_tw_recycle 选项对于面向公共的服务器来说是很有问题的,因为它不能处理来自同一NAT设备后面两台不同计算机的连接,这是一个很难发现的问题,等待着咬你。注意,net.ipv4.tcp_tw_recycle已经从Linux 4.12变成了删除。
net.ipv4.tcp_tw_recycle
服务器端: net.core.somaxconn值有一个重要的角色。它限制侦听套接字排队的最大请求数。如果您确信您的服务器应用程序的能力,可以将它从默认的128提高到像128到1024这样的值。现在,您可以通过修改应用程序的listen调用中的listen backlog变量来利用这一增加,使其等于或更高的整数
net.core.somaxconn
sysctl net.core.somaxconn=1024
你的以太网卡的txqueuelen参数也有一个作用。默认值是1000,所以如果您的系统可以处理,可以将其提高到5000甚至更多。
txqueuelen
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。
net.core.netdev_max_backlog
net.ipv4.tcp_max_syn_backlog
sysctl net.core.netdev_max_backlog=2000 sysctl net.ipv4.tcp_max_syn_backlog=2048
现在,请记住在shell中通过增加FD极限来启动客户端和服务器端应用程序。
除了上面提到的,程序员使用的一个更流行的技巧是减少tcp写调用的数量。我自己的偏好是使用缓冲区,在其中我将希望发送给客户端的数据推入,然后在适当的时候将缓冲的数据写入实际的套接字中。这种技术允许我使用大数据包,减少碎片,降低用户和内核级的CPU利用率。
为了改进@derobert给出的答案,
你可以通过调用nf_conntrack_max来确定你的操作系统连接限制。例如:
nf_conntrack_max
cat /proc/sys/net/netfilter/nf_conntrack_max
您可以使用下面的脚本计算到给定TCP端口范围的TCP连接数。默认为1-65535。
1-65535
这将确认您是否正在达到操作系统连接限制的最大值。
这是剧本。
#!/bin/sh 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}'
在应用程序层面,开发者可以做以下事情:
服务器端:
检查负载均衡器(如果有)是否工作正常。
把慢的TCP超时变成503快速即时响应,如果你的负载均衡器工作正常,它应该选择工作资源来服务,这比挂在那里处理意外的错误消息要好。
var toobusy = require('toobusy'); app.use(function(req, res, next) { if (toobusy()) res.send(503, "I'm busy right now, sorry."); else next(); });
我们也可以在客户端做一些工作:
尝试批量分组调用,减少客户端和服务器之间的流量和总请求数。
尝试构建一个缓存中间层来处理不必要的重复请求。
我试图在2022年在负载均衡器上解决这个问题,我发现的一种方法是将另一个IPv4(或最终IPv6)附加到NIC,所以限制现在翻了一番。当然,您需要为试图连接到机器的服务配置第二个IP(在我的例子中是另一个DNS条目)。