100万并发连接服务器--1M并发连接--tcp_mem优化

高并发下TCP参数调优
本文详细介绍了在服务端连接数达到50万时,如何通过调整TCP参数解决TCP:toomanyorphanedsockets错误。重点讨论了tcp_rmem、tcp_wmem和tcp_mem的调整方法,以及在实际测试环境中达到1024000个持久连接的目标。

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

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

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

默认值为87380 byte ≈ 86K,最小为4096 byte=4K,最大值为4064K。

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

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

解释同上

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

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

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

  • 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)。

这样和tcp_mem最大页面值数量比较吻合,因此此值也需要修改。

三个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_rmemtcp_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 "* - 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等大量参数。

<think>我们正在讨论如何计算服务器并发连接数。用户的问题已经从5G手机并发连接转向了服务器并发连接数的计算方法。需要明确的是,服务器并发连接数的计算与网络环境和应用类型密切相关,但核心原理是通用的。 服务器并发连接数通常指服务器同时处理的活跃连接数量。计算时需要考虑多个因素,包括网络协议、服务器配置、应用架构等。以下是分步骤的计算方法: 1. **基础理论计算模型** 根据TCP/IP协议,每个连接由四元组唯一标识:源IP、源端口、目标IP、目标端口。服务器最大并发连接数理论值受限于: - 端口范围:客户端端口范围(通常1024-65535,共$2^{16}-1024=64512$个) - 服务器资源:文件描述符限制、内存容量、CPU处理能力 - 网络带宽 理论最大并发连接数公式: $$ C_{max} = \min \left( \begin{array}{c} \text{文件描述符上限} \\ \text{内存限制} \\ \text{端口数} \times \text{客户端IP数} \end{array} \right) $$ 例如:单客户端IP最多建立64512个连接(端口耗尽),但实际受服务器限制[^1]。 2. **关键限制因素详解** a. **操作系统级限制** - 文件描述符上限(Linux默认1024,可调整至百级) ```bash # 查看当前限制 ulimit -n # 临时修改 ulimit -n 1000000 ``` - 内核参数优化(如`net.core.somaxconn`定义TCP监听队列长度)[^2] b. **内存消耗计算** 每个TCP连接占用内核内存约: - 接收缓冲区:$ \text{default} \times 2 = (87380 \times 2) \text{ bytes} $ - TCP控制块:约$ 3 \text{ KB} $ 总内存需求公式: $$ M_{\text{total}} = C \times (M_{\text{buffer}} + M_{\text{control}}) $$ 例如:10连接需 $100000 \times (174.76 \text{ KB} + 3 \text{ KB}) \approx 17.3 \text{ GB}$[^3]。 c. **CPU处理能力** 每秒新建连接数(CPS)公式: $$ \text{CPS} = \frac{\text{CPU核心数} \times \text{时钟频率}}{\text{单连接处理周期数}} $$ 现代服务器(如32核3.0GHz)理论CPS可达50+,但受协议栈效率限制[^4]。 3. **实际测量方法** a. **监控工具实时统计** - Linux系统使用`ss -s`命令: ```bash $ ss -s Total: 187 (kernel 0) TCP: 1256 (estab 42, closed 1200, orphaned 0, timewait 1200) ``` "estab"字段即为当前并发连接数[^2]。 b. **压力测试工具** 使用wrk模拟并发请求: ```bash wrk -t12 -c1000 -d30s http://server_ip/ ``` 参数说明: - `-c1000`:模拟1000个并发连接 - 结果中"Requests/sec"反映服务器处理能力[^3]。 4. **应用层优化策略** | 优化方向 | 效果 | 实施示例 | |----------------|-----------------------|----------------------------| | 连接复用 | 减少新建连接数 | HTTP/2多路复用[^4] | | 异步I/O | 降低线程开销 | Node.js事件循环 | | 负载均衡 | 分散连接至多台服务器 | Nginx反向代理集群 | | 协议优化 | 提升传输效率 | QUIC替代TCP | 5. **典型场景计算案例** **视频流媒体服务器**: -连接带宽需求:2 Mbps(1080p) - 服务器总带宽:10 Gbps - 理论并发数:$ \frac{10 \times 1000}{2} = 5000 $ - 实际值:受CPU解码能力限制,通常降至3000-4000[^4]。 --- ### 结论 服务器并发连接数计算需综合考量: 1. **硬件限制**:内存、CPU、网卡 2. **系统配置**:文件描述符、内核参数 3. **应用特性**:连接生命周期、数据处理复杂度 实际部署前应通过压力测试验证,公式: $$ C_{\text{real}} = \min \left( \frac{\text{总内存}}{\text{单连接内存}}, \frac{\text{总带宽}}{\text{单连接带宽}} \right) \times \text{效率系数} $$ 效率系数通常取0.6-0.8[^4]。 --- §§相关问题§§ 1. 如何优化Linux服务器的文件描述符限制以支持更高并发? 2. 在微服务架构中,如何准确统计分布式系统的总并发连接数? 3. 哪些监控工具可以实时显示服务器并发连接数变化趋势? 4. HTTP/2的多路复用机制如何影响并发连接数的计算?</think>### 服务器并发连接数计算方法详解 #### 一、核心计算公式与要素 服务器并发连接数由硬件资源、操作系统配置和应用层协议共同决定,核心计算公式如下: $$ C = \min \left( \frac{M}{m}, \frac{F}{f}, \frac{B}{b} \right) \times \eta $$ 其中: - $C$:实际并发连接- $M$:系统可用内存(GB) - $m$:单连接内存开销(GB/连接- $F$:文件描述符上限 - $f$:单连接文件描述符消耗(通常为1- $B$:网络带宽(Mbps) - $b$:单连接平均带宽(Mbps) - $\eta$:系统效率系数(通常0.6-0.8)[^1] #### 二、关键限制因素计算 1. **内存限制** 单TCP连接内存开销包括: - 内核缓冲区:$ \text{default} \times 2 = (87380 \times 2) \text{ bytes} $ - TCP控制块:约$ 3 \text{ KB} $ - 应用层缓冲:$ 4-64 \text{ KB} $ 总内存需求: $$ m = \frac{(174.76 \text{ KB} + 3 \text{ KB} + \text{应用缓冲}) \times 10^3}{1024^2} \text{ GB} $$ 示例:32GB内存服务器支持连接数上限: $$ C_{\text{mem}} = \frac{32}{0.0002} \approx 160,000 $$ 2. **文件描述符限制** Linux系统查看与修改: ```bash # 查看当前限制 ulimit -n # 永久修改(CentOS) echo "fs.file-max=1000000" >> /etc/sysctl.conf sysctl -p ``` 理论连接数:$ C_{\text{fd}} = F - \text{系统预留} $(通常预留100-200)[^2] 3. **带宽限制** 带宽计算公式: $$ C_{\text{bw}} = \frac{B \times 1024^2 / 8}{b \times \text{包大小}} $$ 示例:10Gbps带宽,HTTP请求平均15KB: $$ C_{\text{bw}} = \frac{10 \times 1024}{0.015} \approx 682,666 $$ #### 三、操作系统级监控方法 1. **实时连接统计** ```bash # 查看ESTABLISHED状态连接数 ss -s | grep "ESTAB" # 按协议统计 netstat -tan | awk '/^tcp/ {print $6}' | sort | uniq -c ``` 2. **内核参数优化** | 参数 | 作用 | 推荐值 | |------|------|--------| | `net.core.somaxconn` | TCP监听队列 | 65535 | | `net.ipv4.tcp_max_syn_backlog` | SYN队列 | 262144 | | `net.core.netdev_max_backlog` | 网卡缓冲 | 300000 |[^3] #### 四、应用层影响因素 1. **连接生命周期模型** ```mermaid graph LR A[连接建立] --> B[数据传输] B --> C[连接保持] C --> D[连接释放] ``` -连接:高新建/释放开销(HTTP/1.0) -连接:低开销高内存占用(HTTP/1.1 Keep-Alive) 2. **协议效率对比** | 协议 | 并发效率 | 内存开销 | |------|----------|----------| | HTTP/1.1 | 低(6-8连接/域名) | 中 | | HTTP/2 | 高(单连接多路复用) | 低 | | HTTP/3(QUIC) | 极高(0-RTT连接) | 低 |[^4] #### 五、压力测试验证 使用wrk工具测试实际并发能力: ```bash wrk -t12 -c5000 -d30s http://your-server.com/ ``` 参数说明: - `-t12`:12线程 - `-c5000`:模拟5000并发连接 - 输出关键指标: ``` Requests/sec: 15,328 Latency: 32.54ms (p99=215ms) ``` #### 六、典型场景计算案例 **视频直播服务器配置:** - 硬件:64GB内存/25Gbps带宽 -连接1080p流@4Mbps,内存开销0.3MB - 计算: $$ C_{\text{mem}} = \frac{64 \times 1024}{0.3} \approx 218,453 $$ $$ C_{\text{bw}} = \frac{25 \times 1000}{4} = 6,250 $$ $$ C = \min(218453, 6250) \times 0.7 \approx 4,375 $$ --- ### 结论 服务器并发连接数需通过**分层计算+压力测试**确定: 1. 计算理论上限:$$ \min(C_{\text{mem}}, C_{\text{fd}}, C_{\text{bw}}) $$ 2. 应用效率系数:$\eta$(通常0.6-0.8) 3. 压力测试验证:使用wrk/jmeter等工具 4. 监控优化:实时调整内核参数和应用配置[^4] ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值