我正在编程一个服务器,似乎我的连接数量是有限的,因为我的带宽没有饱和,即使我已经将连接数量设置为“无限”。

如何增加或消除我的Ubuntu Linux机器一次可以打开的最大连接数?是操作系统限制了这一点,还是路由器或ISP?还是其他原因?


有几个变量可以设置最大连接数。最有可能的情况是,您首先用光了文件号。检查ulimit -n。在此之后,在/proc中有一些设置,但这些设置默认为数万。

更重要的是,听起来你好像做错了什么。单个TCP连接应该能够使用双方之间的所有带宽;如果不是:

Check if your TCP window setting is large enough. Linux defaults are good for everything except really fast inet link (hundreds of mbps) or fast satellite links. What is your bandwidth*delay product? Check for packet loss using ping with large packets (ping -s 1472 ...) Check for rate limiting. On Linux, this is configured with tc Confirm that the bandwidth you think exists actually exists using e.g., iperf Confirm that your protocol is sane. Remember latency. If this is a gigabit+ LAN, can you use jumbo packets? Are you?

可能是我误会了。也许你正在做一些像Bittorrent这样的事情,你需要很多连接。如果是这样,您需要计算出您实际使用了多少连接(尝试netstat或lsof)。如果这个数字很大,你可能会:

有很大的带宽,例如100mbps+。在这种情况下,实际上可能需要增大ulimit -n。不过,大约1000个连接(在我的系统上是默认的)是相当多的。 网络问题使你的连接变慢(例如,丢包) 使用其他减慢速度的东西,例如IO带宽,特别是如果您正在寻求。你检查过iostat -x吗?

此外,如果您使用的是消费级NAT路由器(Linksys、Netgear、DLink等),请注意数千个连接可能会超出它的能力。

我希望这能提供一些帮助。你其实是在问一个社交问题。


最大连接数受到客户端和服务器端的某些限制的影响,尽管略有不同。

在客户端: 增加临时端口范围,减少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

以上不应被解释为影响每秒建立出站连接的系统能力的因素。但是这些因素会影响系统以可持续的方式处理并发连接的能力,以应对大量的“活动”。

典型Linux机器上tcp_tw_recycle和tcp_tw_reuse的默认Sysctl值为

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 

This allows fast cycling of sockets in time_wait state and re-using them. But before you do this change make sure that this does not conflict with the protocols that you would use for the application that needs these sockets. Make sure to read post "Coping with the TCP TIME-WAIT" from Vincent Bernat to understand the implications. The net.ipv4.tcp_tw_recycle option is quite problematic for public-facing servers as it won’t handle connections from two different computers behind the same NAT device, which is a problem hard to detect and waiting to bite you. Note that net.ipv4.tcp_tw_recycle has been removed from Linux 4.12.

服务器端: net.core.somaxconn值具有重要的作用。它限制侦听套接字排队的最大请求数。如果您确信您的服务器应用程序的能力,可以将它从默认的128提高到像128到1024这样的值。现在,您可以通过将应用程序的listen调用中的listen backlog变量修改为等于或更高的整数来利用这一增加。

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极限来启动客户端和服务器端应用程序。

除了上面提到的,程序员使用的一个更流行的技术是减少tcp写调用的数量。我自己的偏好是使用缓冲区,在其中我将希望发送给客户端的数据推入,然后在适当的时候将缓冲的数据写入实际的套接字中。这种技术允许我使用大数据包,减少碎片,降低用户和内核级的CPU利用率。


为了改进@derobert给出的答案,

您可以通过计算nf_conntrack_max来确定您的操作系统连接限制。例如:

cat /proc/sys/net/netfilter/nf_conntrack_max

您可以使用下面的脚本计算到给定TCP端口范围的TCP连接数。缺省值是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快速即时响应,如果你的负载均衡器工作正常,它应该选择工作资源来服务,这比挂在那里处理意外的错误消息要好。

如果你正在使用节点服务器,你可以从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

我们也可以在客户端做一些工作:

尝试批量分组调用,减少客户端和服务器之间的流量和总请求数。 尝试构建一个缓存中间层来处理不必要的重复请求。


我试图在2022年在负载均衡器上解决这个问题,我发现的一种方法是将另一个IPv4(或最终IPv6)附加到NIC,所以限制现在翻了一番。当然,您需要为试图连接到机器的服务配置第二个IP(在我的例子中是另一个DNS条目)。