当前位置:  开发笔记 > 编程语言 > 正文

增加linux中tcp/ip连接的最大数量

如何解决《增加linux中tcp/ip连接的最大数量》经验,为你挑选了4个好方法。

我正在编程服务器,似乎我的连接数量有限,因为我的带宽没有饱和,即使我已经将连接数设置为"无限制".

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



1> mdk..:

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

在客户端: 增加ephermal端口范围,并减少tcp_fin_timeout

要找出默认值:

sysctl net.ipv4.ip_local_port_range
sysctl net.ipv4.tcp_fin_timeout

ephermal端口范围定义了主机可以从特定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系统中的默认SYSCTL值tcp_tw_recycletcp_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之间.现在,您可以通过将应用程序的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_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写入调用的次数.我自己的偏好是使用一个缓冲区,其中我将我希望发送的数据推送到客户端,然后在适当的点我将缓冲的数据写入实际的套接字.这种技术允许我使用大数据包,减少碎片,降低用户区域和内核级别的CPU利用率.


不要忘记我们一直在谈论IP +端口.您可以从许多不同的IP向端口XY打开"无限制"套接字.限制470适用于仅针对同一IP的并发打开套接字.另一个IP可以拥有自己的470个连接到相同的端口.
这个答案有错误.首先,net.ipv4.tcp_fin_timeout仅适用于FIN_WAIT_2状态(https://cs.uwaterloo.ca/~brecht/servers/ip-sysctl.txt).其次,正如@Eric所说,"任何时候都有470个插座"是不正确的.
@ Marki555:您的评论非常正确.为生成和维持大量出站连接而开发的应用程序必须具有用于创建出站连接的可用IP的"感知",然后必须使用某种"循环算法"适当地绑定到这些IP地址,并维护一个"记分牌".
精彩回答!我的问题有点不同,即我试图通过PHP将会话信息从应用程序级会话存储移动到redis.出于某种原因,我无法在不增加大量睡眠的情况下添加超过28230个会话,在php或redis日志中都没有看到任何错误.我们在这一天打破了我们的头一整天,直到我认为可能问题不是php/redis,而是连接两者的tcp/ip层并得出了这个答案.管理,以便在此之后立即解决问题:)非常感谢!
@mdk:我不清楚这个计算部分`(61000 - 32768)/ 60 =每秒470个套接字`.你能详细说明一下吗?

2> derobert..:

有几个变量可以设置最大连接数.最有可能的是,你首先没有文件编号.检查ulimit -n.之后,/ proc中有设置,但默认为数万.

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

检查TCP窗口设置是否足够大.除了真正快速的inet链路(数百mbps)或快速卫星链路之外,Linux默认设置适用于所有设备.你的带宽*延迟产品是多少?

使用ping大数据包检查数据包丢失(ping -s 1472...)

检查速率限制.在Linux上,配置为tc

使用例如确认您认为存在的带宽实际存在 iperf

确认您的协议是正确的.记住延迟.

如果这是一个千兆+局域网,你可以使用巨型数据包吗?你是?

可能我误解了.也许你正在做类似Bittorrent的事情,你需要很多连接.如果是这样,您需要确定实际使用的连接数(尝试netstatlsof).如果该数字很大,您可以:

有很多带宽,例如100mbps +.在这种情况下,您实际上可能需要向上ulimit -n.不过,约有1000个连接(我的系统默认)很多.

网络问题导致连接速度变慢(例如丢包)

还有其他一些因素会让你失望,例如IO带宽,特别是如果你正在寻找.你检查过iostat -x吗?

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

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



3> 小智..:

为了改进derobert给出的答案,

您可以通过捕获nf_conntrack_max来确定您的操作系统连接限制.

例如:cat/proc/sys/net/netfilter/nf_conntrack_max

您可以使用以下脚本来计算到给定范围的tcp端口的tcp连接数.默认1-65535.

这将确认您是否最大化了OS连接限制.

这是脚本.

#!/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}'


我喜欢这个脚本如何弹道来确定`awk`位置,但是假设shell总是`/ bin/bash`(专业提示:AIX5/6默认情况下甚至没有bash).
`awk`是你确定awk路径的朋友,SunOS也有链接到它:)
@PanagiotisM.`which`依赖程序在`PATH`中,在这种情况下你可以使用`awk`而不是提供完整路径.(也就是说,我不确定脚本中的解决方案是否更接近完美,但这不是脚本的内容).

4> 小智..:

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

从服务器端:

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

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

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

    尝试批量分组呼叫,减少流量和总请求数b/w客户端和服务器.

    尝试构建缓存中间层以处理不必要的重复请求.

推荐阅读
小妖694_807
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有