TCP最大连接数调优

文章目录

    • 1、单机最大TCP连接数
      • 1.1、如何标识一个TCP连接
      • 1.2、client最大tcp连接数
      • 1.3、server最大tcp连接数
        • 1.3.1、理论连接数
        • 1.3.2、实际连接数
      • 1.4、单台服务器支撑的最大TCP并发连接数
        • 1.4.1、进程限制句柄限制
          • 查看进程句柄数限制
          • 临时修改
          • 重启后失效的修改(不过我在CentOS 6.5下测试,重启后未发现失效)
          • 永久修改
        • 1.4.2、全局限制
    • 2、tcp内核参数调优
      • 2.1、查看`net.ipv4`参数
      • 2.2、推荐配置
      • 2.3、参数解释
        • 2.3.1、 建立连接阶段
        • 2.3.2、 数据传输阶段
        • 2.3.3、 断开连接阶段

1、单机最大TCP连接数

1.1、如何标识一个TCP连接

在确定最大连接数之前,先来看看系统如何标识一个tcp连接。系统用一个4四元组来唯一标识一个TCP连接:

  • local ip
  • local port
  • remote ip
  • remote port

1.2、client最大tcp连接数

client每次发起tcp连接请求时,通常会让系统选取一个空闲的本地端口(local port),该端口是独占的,不能和其他tcp连接共享。在操作系统中,端口号的的数据类型是unsigned short,所以端口号的范围只有0~65535,其中0-1024是预留端口号,不可使用,其他的端口都是可以使用的。也就是说,在链接发起端,受端口号的限制理论上最多可以创建64000左右链接。

那么有没有办法超过这个限制呢,答案是肯定的!

通过TCP标识的四元组可以看到,对于链接发起端,影响链接数的是本地ip和port,端口号受限于65535,已经没办法增加了。那我们可以增加本地ip来达到这个目的。一般情况下,服务器的一个网卡上只绑定了一个ip,对外通信都使用这个ip进行。其实网卡是支持一个绑定多个IP的(必须确保ip是有效的且未使用的)

ifconfig eth0:1 10.0.0.5

以上命令可以在eth0网卡上增加一个ip 10.0.0.5,服务器网卡每增加一个ip,就可以允许在这个ip上再创建65535左右的链接数。

最大的TCP链接数=所有有效ip排列组合的数量*端口数量64000

1.3、server最大tcp连接数

1.3.1、理论连接数

server通常固定在某个本地端口上监听,等待client的连接请求。不考虑地址重用(unix的SO_REUSEADDR选项)的情况下,即使server端有多个ip,本地监听端口也是独占的,因此server端tcp连接4元组中只有remote ip(也就是client ip)和remote port(客户端port)是可变的,因此最大tcp连接为客户端ip数×客户端port数,对IPV4,不考虑ip地址分类等因素,最大tcp连接数约为2的32次方(ip数)×2的16次方(port数),也就是server端单机最大tcp连接数约为2的48次方。

1.3.2、实际连接数

上面给出的是理论上的单机最大连接数,在实际环境中,受到机器资源、操作系统等的限制,特别是sever端,其最大并发tcp连接数远不能达到理论上限。在unix/linux下限制连接数的主要因素是内存和允许的文件描述符个数(每个tcp连接都要占用一定内存,每个socket就是一个文件描述符),另外1024以下的端口通常为保留端口。在默认2.6内核配置下,经过试验,每个socket占用内存在15~20k之间
影响一个socket占用内存的参数包括:

net.core.rmem_max=16777216
net.core.wmem_max=16777216
net.ipv4.tcp_rmem=4096 87380 16777216
net.ipv4.tcp_wmem=4096 65536 16777216
net.ipv4.tcp_mem=
grep skbuff /proc/slabinfo

1.4、单台服务器支撑的最大TCP并发连接数

在linux下编写网络服务器程序的朋友肯定都知道每一个tcp连接都要占一个文件描述符,一旦这个文件描述符使用完了,新的连接到来返回给我们的错误是“Socket/File:Can’t open so many files”。

1.4.1、进程限制句柄限制

查看进程句柄数限制
 ulimit -n

输出 1024,说明对于一个进程而言最多只能打开1024个文件,所以你要采用此默认配置最多也就可以并发上千个TCP连接。

临时修改
ulimit -n 1000000

这种临时修改只对当前登录用户目前的使用环境有效,系统重启或用户退出后就会失效。

重启后失效的修改(不过我在CentOS 6.5下测试,重启后未发现失效)

编辑 /etc/security/limits.conf 文件

root soft nofile 1000000
root hard nofile 1000000
* soft nofile 1000000
* hard nofile 1000000
永久修改

编辑/etc/rc.local,在其后添加如下内容

ulimit -SHn 1000000

1.4.2、全局限制

执行 cat /proc/sys/fs/file-nr 输出 9344 0 592026,分别为:1.已经分配的文件句柄数,2.已经分配但没有使用的文件句柄数,3.最大文件句柄数。但在kernel 2.6版本中第二项的值总为0,这并不是一个错误,它实际上意味着已经分配的文件描述符无一浪费的都已经被使用了 。

我们可以把这个数值改大些,用 root 权限修改 /etc/sysctl.conf 文件:

fs.file-max = 1000000
net.ipv4.ip_conntrack_max = 1000000
net.ipv4.netfilter.ip_conntrack_max = 1000000

执行命令生效

sysctl -p

2、tcp内核参数调优

2.1、查看net.ipv4参数

cat /proc/sys/net/ipv4/tcp_rmem

修改则修改文件/ect/sysctl.conf

Linux下查看tcp连接数及状态命令

netstat -n | awk '/^tcp/ {++S[$NF]} END {for(a in S) print a, S[a]}'

2.2、推荐配置

net.ipv4.ip_local_port_range = 1024 65536
net.core.rmem_max=16777216 
net.core.wmem_max=16777216
net.ipv4.tcp_rmem=4096 87380 16777216
net.ipv4.tcp_wmem=4096 65536 16777216
net.ipv4.tcp_fin_timeout = 10
net.ipv4.tcp_tw_recycle = 1
net.ipv4.tcp_timestamps = 0
net.ipv4.tcp_window_scaling = 0
net.ipv4.tcp_sack = 0
net.core.netdev_max_backlog = 30000
net.ipv4.tcp_no_metrics_save=1
net.core.somaxconn = 262144
net.ipv4.tcp_syncookies = 0
net.ipv4.tcp_max_orphans = 262144
net.ipv4.tcp_max_syn_backlog = 262144
net.ipv4.tcp_synack_retries = 2
net.ipv4.tcp_syn_retries = 2

2.3、参数解释

TCP最大连接数调优_第1张图片

2.3.1、 建立连接阶段

  • net.ipv4.tcp_syn_retries
    控制三次握手第一步客户端发送syn得不到服务端响应时重传syn的次数,如果是内网环境,中间链路少,网络稳定,服务端无响应很可能是服务端应用出了问题,重传多次的意义不大,还会加大服务端压力,可以调低重传次数,让客户端尽快去尝试连接其他服务端。

  • net.ipv4.tcp_syncookies
    开启SYN Cookies,默认开启,建议保持默认值,可以提升SYN Flood攻击的防护能力。

  • net.ipv4.tcp_synack_retries
    控制三次握手第二步服务端发送syn+ack得不到客户端响应时重传syn+ack的次数,如果是内网环境,中间链路少,网络稳定,客户端无响应很可能是客户端出了问题,重传多次的意义不大,可以调低重传次数。

  • net.ipv4.tcp_max_syn_backlog
    控制半连接队列大小,所谓半连接是指还没有完成TCP三次握手的连接。服务端收到了客户端的SYN包后,就会把这个连接放到半连接队列中,然后再向客户端发送SYN+ACK,为了应对新建连接数暴增的场景,建议调大,半连接队列溢出观察方法:netstat -s | grep “SYNs to LISTEN”

  • net.core.somaxconn
    全连接队列=min(somaxconn,backlog),所谓全连接,是指服务端已经收到客户端三次握手第三步的ACK,然后就会把这个连接放到全连接队列中,全连接队列中的连接还需要被 accept()系统调用取走,服务端应用才可以开始处理客户端的请求,建议适当调大,全连接队列溢出观察方法:netstat -s | grep “listen queue”

  • net.ipv4.tcp_abort_on_overflow
    当全连接队列满了之后,新的连接就会被丢弃掉。服务端在丢弃新连接时,默认行为是直接丢弃不去通知客户端,有的时候需要发送reset来通知客户端,这样客户端就不会再次重试,至于是否需要给客户端发送reset,是由tcp_abort_on_overflow参数控制,默认为0,即不发送reset给客户端,如非特殊需求,建议保持默认值。

  • net.ipv4.tcp_timestamps

    0关闭,1关闭

    tcp_timestamps的本质是记录数据包的发送时间。基本的步骤如下

    1. 发送方在发送数据时,将一个timestamp(表示发送时间)放在包里面
    2. 接收方在收到数据包后,在对应的ACK包中将收到的timestamp返回给发送方(echo back)
    3. 发送发收到ACK包后,用当前时刻now - ACK包中的timestamp就能得到准确的RTT。当然实际运用中要考虑到RTT的波动,因此有了后续的(Round-Trip Time Measurement)RTTM机制

2.3.2、 数据传输阶段

  • net.ipv4.tcp_wmem
    tcp发送缓冲区大小,包含min、default、max三个值,内核会控制发送缓冲区在min-max之间动态调整,可根据实际业务场景和服务器配置适当调大,如果设置了socket的SO_SNDBUF,动态调整功能失效,一般不建议设置。
  • net.core.wmem_max
    socket发送缓冲区的最大值,需要设置net.core.wmem_max的值大于等于 net.ipv4.tcp_wmem的max值。
  • net.ipv4.tcp_mem
    系统中所有tcp连接最多可消耗的内存,有三个值,当TCP总内存小于第1个值时,不需要内核进行自动调节,在第1和第2个值之间时,内核开始调节缓冲区的大小,大于第3个值时,内核不再为TCP分配新内存,此时无法新建连接,需要注意的是,三个值的单位都是内存页,也就是4KB。
  • net.ipv4.tcp_rmem
    tcp接收缓冲区大小,包含min、default、max三个值,内核会控制接收缓冲区在min-max之间动态调整,可根据实际业务场景和服务器配置适当调大,如果设置了socket的 SO_RECVBUF或者关闭了net.ipv4.tcp_moderate_rcvbuf,动态调整功能失效。
  • net.core.rmem_max
    socket接收缓冲区的最大值,需要设置net.core.rmem_max的值大于等于net.ipv4.tcp_rmem 的max值。
  • net.ipv4.tcp_moderate_rcvbuf
    接收缓冲区动态调整功能,默认打开,建议保持默认配置。
  • net.ipv4.tcp_window_scaling
    扩充滑动窗口,tcp头部中,窗口字段只有2个字节,最多只能达到2的16次方,即65535字节大小的窗口,打开此开关可以扩充窗口大小,默认打开,建议保持默认配置。
  • net.ipv4.tcp_keepalive_probes
    keepalive探测失败后通知应用前的重试次数,建议适当调低。
  • net.ipv4.tcp_keepalive_intvl
    keepalive探测包的发送间隔时间,建议适当调低。
  • net.ipv4.tcp_keepalive_time
    最后一次数据包到keepalive探测包的间隔时间,建议适当调低。
  • net.ipv4.tcp_available_congestion_control
    查看内核支持的拥塞控制算法。
  • net.ipv4.tcp_congestion_control
    配置拥塞控制算法,默认cubic,内核4.9版本后支持BBR,弱网络条件下建议配置成BBR。

2.3.3、 断开连接阶段

  • net.ipv4.tcp_fin_timeout
    是从Fin_WAIT_2到TIME_WAIT的超时时间,长时间收不到对端FIN包,大概率是对端机器有问题,不能及时调用close()关闭连接,建议调低,避免等待时间太长,资源开销过大。
  • net.ipv4.tcp_max_tw_buckets
    系统TIME_WAIT连接的最大数量,根据实际业务需要调整,超过最大值后dmesg会有报错TCP: time wait bucket table overflow。
  • net.ipv4.tcp_tw_reuse
    允许TIME_WAIT状态的连接占用的端口用到新建连接中,客户端可开启。
  • net.ipv4.tcp_tw_recycle
    开启后,TIME_WAIT状态的连接无需等待2MSL时间就可用于新建连接,在NAT环境下,开启tcp_tw_recycle参数会触发PAWS机制导致丢包,建议不开启,事实上,内核在4.1版本后就把这个参数删除了。

参考博客

TCP单机最大连接数优化

Linux系统TCP内核参数优化总结

你可能感兴趣的:(linux,网络,服务器,linux)