100万并发链接服务器笔记之1M并发链接目标达成

第四个遇到的问题:tcp_mem

在服务端,链接达到必定数量,诸如50W时,有些隐藏很深的问题,就不断的抛出来。 经过查看dmesg命令查看,发现大量TCP: too many of orphaned sockets错误,也很正常,下面到了须要调整tcp socket参数的时候了。 linux

第一个须要调整的是tcp_rmem,即TCP读取缓冲区,单位为字节,查看默认值 centos

cat /proc/sys/net/ipv4/tcp_rmem
4096 87380 4161536

默认值为87380bit ≈ 86K,最小为4096bit=4K,最大值为4064K。 服务器

第二个须要调整的是tcp_wmem,发送缓冲区,单位是字节,默认值 socket

cat /proc/sys/net/ipv4/tcp_wmem
4096 16384 4161536

解释同上 tcp

第三个须要调整的tcp_mem,调整TCP的内存大小,其单位是页,1页等于4096字节。系统默认值: 测试

cat /proc/sys/net/ipv4/tcp_mem
932448 1243264 1864896

tcp_mem(3个INTEGER变量):low, pressure, high spa

  • low:当TCP使用了低于该值的内存页面数时,TCP不会考虑释放内存。
  • pressure:当TCP使用了超过该值的内存页面数量时,TCP试图稳定其内存使用,进入pressure模式,当内存消耗低于low值时则退出pressure状态。
  • high:容许全部tcp sockets用于排队缓冲数据报的页面量,当内存占用超过此值,系统拒绝分配socket,后台日志输出“TCP: too many of orphaned sockets”。

通常状况下这些值是在系统启动时根据系统内存数量计算获得的。 根据当前tcp_mem最大内存页面数是1864896,当内存为(1864896*4)/1024K=7284.75M时,系统将没法为新的socket链接分配内存,即TCP链接将被拒绝。 日志

实际测试环境中,据观察大概在99万个链接左右的时候(零头不算),进程被杀死,触发out of socket memory错误(dmesg命令查看得到)。每个链接大体占用7.5K内存(下面给出计算方式),大体可算的此时内存占用状况(990000 * 7.5 / 1024K = 7251M)。 code

这样和tcp_mem最大页面值数量比较吻合,所以此值也须要修改。 server

三个TCP调整语句为:

echo "net.ipv4.tcp_mem = 786432 2097152 3145728">> /etc/sysctl.conf
echo "net.ipv4.tcp_rmem = 4096 4096 16777216">> /etc/sysctl.conf
echo "net.ipv4.tcp_wmem = 4096 4096 16777216">> /etc/sysctl.conf

备注: 为了节省内存,设置tcp读、写缓冲区都为4K大小,tcp_mem三个值分别为3G 8G 16G,tcp_rmem和tcp_wmem最大值也是16G。

目标达成

通过若干次的尝试,最终达到目标,1024000个持久链接。1024000数字是怎么得来的呢,两台物理机器各自发出64000个请求,两个配置为6G左右的centos测试端机器(绑定7个桥接或NAT链接)各自发出640007 = 448000。也就是 1024000 = (64000) + (64000) + (640007) + (64000*7), 共使用了16个网卡(物理网卡+虚拟网卡)。 
终端输出

......
online user 1023990
online user 1023991
online user 1023992
online user 1023993
online user 1023994
online user 1023995
online user 1023996
online user 1023997
online user 1023998
online user 1023999
online user 1024000

在线用户目标达到1024000个!

服务器状态信息

服务启动时内存占用:

                 total       used       free     shared    buffers     cached
     Mem:         10442        271      10171          0         22         78
     -/+ buffers/cache:        171      10271
     Swap:         8127          0       8127

系统达到1024000个链接后的内存状况(执行三次 free -m 命令,获取三次结果):

                 total       used       free     shared    buffers     cached
     Mem:         10442       7781       2661          0         22         78
     -/+ buffers/cache:       7680       2762
     Swap:         8127          0       8127
 
                  total       used       free     shared    buffers     cached
     Mem:         10442       7793       2649          0         22         78
     -/+ buffers/cache:       7692       2750
     Swap:         8127          0       8127
 
                  total       used       free     shared    buffers     cached
     Mem:         10442       7804       2638          0         22         79
     -/+ buffers/cache:       7702       2740
     Swap:         8127          0       8127
这三次内存使用分别是7680,7692,7702,此次不取平均值,取一个中等偏上的值,定为7701M。那么程序接收1024000个链接,共消耗了 7701M-171M = 7530M内存, 7530M*1024K / 1024000 = 7.53K, 每个链接消耗内存在为7.5K左右,这和在链接达到512000时所计算较为吻合。 

虚拟机运行Centos内存占用,不太稳定,但通常相差不大,以上数值,仅供参考。

执行top -p 某刻输出信息:

   top - 17:23:17 up 18 min,  4 users,  load average: 0.33, 0.12, 0.11
     Tasks:   1 total,   1 running,   0 sleeping,   0 stopped,   0 zombie
     Cpu(s):  0.2%us,  6.3%sy,  0.0%ni, 80.2%id,  0.0%wa,  4.5%hi,  8.8%si,  0.0%st
     Mem:  10693580k total,  6479980k used,  4213600k free,    22916k buffers
     Swap:  8323056k total,        0k used,  8323056k free,    80360k cached
 
       PID USER      PR  NI  VIRT  RES  SHR S %CPU %MEM    TIME+  COMMAND                      
      2924 yongboy   20   0 82776  74m  508 R 51.3  0.7   3:53.95 server 

执行vmstate:

vmstat
procs -----------memory---------- ---swap-- -----io---- --system-- -----cpu-----
 r b swpd free buff cache si so bi bo in cs us sy id wa st
 0 0 0 2725572 23008 80360 0 0 21 2 1012 894 0 9 89 2 0

获取当前socket链接状态统计信息:

cat /proc/net/sockstat
sockets: used 1024380
TCP: inuse 1024009 orphan 0 tw 0 alloc 1024014 mem 2
UDP: inuse 11 mem 1
UDPLITE: inuse 0
RAW: inuse 0
FRAG: inuse 0 memory 0

获取当前系统打开的文件句柄:

sysctl -a | grep file
fs.file-nr = 1025216 0 1048576
fs.file-max = 1048576

此时任何相似于下面查询操做都是一个慢,等待若干时间还不见得执行完毕。

netstat -nat|grep -i "8000"|grep ESTABLISHED|wc -l 
netstat -n | grep -i "8000" | awk '/^tcp/ {++S[$NF]} END {for(a in S) print a, S[a]}'

以上两个命令在二三十分钟过去了,还未执行完毕,只好中止。

小结

本次从头至尾的测试,所须要有的linux系统须要调整的参数也就是那么几个,汇总一下:

    echo "yongboy soft nofile 1048576" >> /etc/security/limits.conf 
    echo "yongboy hard nofile 1048576" >>  /etc/security/limits.conf
 
     echo "fs.file-max = 1048576" >> /etc/sysctl.conf
     echo "net.ipv4.ip_local_port_range = 1024 65535" >> /etc/sysctl.conf
 
     echo "net.ipv4.tcp_mem = 786432 2097152 3145728" >> /etc/sysctl.conf
     echo "net.ipv4.tcp_rmem = 4096 4096 16777216" >> /etc/sysctl.conf
     echo "net.ipv4.tcp_wmem = 4096 4096 16777216" >> /etc/sysctl.conf

其它没有调整的参数,仅仅由于它们暂时对本次测试没有带来什么影响,实际环境中须要结合须要调整相似于SO_KEEPALIVE、tcpmax_orphans等大量参数。

本文表明一次实践,不足之处,欢迎批评指正。

相关文章
相关标签/搜索