235

我正在对服务器进行编程,我的连接数似乎受到了限制,因为即使我将连接数设置为“无限”,我的带宽也没有饱和。

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

4

4 回答 4

456

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

在客户端: 增加临时端口范围,并减少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&的默认 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状态的套接字并重新使用它们。但在您进行此更改之前,请确保这不会与您将用于需要这些套接字的应用程序的协议冲突。请务必阅读文森特·伯纳特 (Vincent Bernat) 的文章“应对 TCP TIME-WAIT”以了解其含义。该net.ipv4.tcp_tw_recycle 选项对于面向公众的服务器来说是相当有问题的,因为它不会处理来自同一 NAT 设备后面的两台不同计算机的连接,这是一个难以检测并等待咬你的问题。请注意,net.ipv4.tcp_tw_recycle已从Linux 4.12中删除。

在服务器端: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_backlognet.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 利用率。

于 2010-10-13T12:49:44.110 回答
70

有几个变量可以设置最大连接数。最有可能的是,您首先用完了文件编号。检查ulimit -n。之后,里面有设置/proc,但默认都是几万。

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

  • 检查您的 TCP 窗口设置是否足够大。Linux 默认值适用于除真正快速的 inet 链接(数百 mbps)或快速卫星链接之外的所有内容。您的带宽*延迟积是多少?
  • 使用 ping 大数据包检查数据包丢失 ( ping -s 1472...)
  • 检查速率限制。在 Linux 上,这是配置为tc
  • 使用例如确认您认为存在的带宽确实存在,iperf
  • 确认您的协议是健全的。记住延迟。
  • 如果这是一个千兆+ LAN,您可以使用巨型数据包吗?你是?

可能我理解错了。也许你正在做类似 Bittorrent 的东西,你需要大量的连接。如果是这样,您需要弄清楚您实际使用了多少个连接(尝试netstatlsof)。如果这个数字很大,您可以:

  • 有很多带宽,例如 100mbps+。在这种情况下,您实际上可能需要升级ulimit -n. 尽管如此,大约 1000 个连接(我的系统上的默认值)还是相当多的。
  • 有网络问题会减慢您的连接速度(例如,数据包丢失)
  • 有其他东西会减慢您的速度,例如 IO 带宽,特别是如果您正在寻找。你检查过iostat -x吗?

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

我希望这能提供一些帮助。你真的在问一个网络问题。

于 2009-01-04T08:02:32.010 回答
19

为了改进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}'
于 2012-10-12T18:36:35.707 回答
10

在应用程序级别,开发人员可以执行以下操作:

从服务器端:

  1. 检查负载均衡器(如果有)是否正常工作。

  2. 将慢速 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

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

  1. 尝试对呼叫进行批量分组,减少客户端和服务器的流量和总请求数。

  2. 尝试构建一个缓存中间层来处理不必要的重复请求。

于 2014-11-19T21:26:44.953 回答