TCP协议服务器能带的客户端数量,没有固定上限,常规配置下支撑数千并发连接是常态,优化到位后单机承载数万甚至数十万连接也并非不可能。真正决定上限的,是服务器的文件描述符数量、内存大小、网络带宽,以及程序自身的事件处理模型,理解了这几个变量,你就能推算自己这台机器到底能扛多少客人。
先拆开看:一个TCP连接究竟吃掉服务器什么资源
很多朋友一上来就说“端口不够了”,其实这是最常见的误解,一条TCP连接由四元组唯一标识:源IP、源端口、目的IP、目的端口,服务器端作为接收方,监听端口只有一个80或443,但操作系统会为每条连接动态分配一个临时端口。
65535端口上限是个伪命题
内核用ip_local_port_range参数控制临时端口范围,默认通常是32768到60999,只有不到三万来个端口,但这个限制只影响主动发起连接的一方,服务器被动接受连接时,源端口就是监听端口,所以65535的限制在服务器这里并不成立,真正挡路的是下面三个东西。
文件描述符:第一个卡脖子环节
Linux下一切皆文件,每个TCP连接都是一个Socket文件,消耗一个文件描述符(FD),多数Linux发行版默认单进程FD上限是1024,也就是说,不调参数的情况下,你的程序刚接到1024个客户端就开始报错“Too many open files”。
临时改法用这条命令,当前会话立即生效:
ulimit -n 65535
永久生效得改两个地方,/etc/security/limits.conf追加四行,并确认/etc/systemd/system.conf里的DefaultLimitNOFILE没有锁死旧值:
soft nofile 65535
hard nofile 65535
root soft nofile 65535
root hard nofile 65535
内存:连接越多,内存越紧
每一条TCP连接,内核都要维护发送缓冲区、接收缓冲区以及socket数据结构,虽然Linux有自动调优机制,但每连接实际占用按几KB到几十KB算很正常,拿一台2GB内存的云主机来说,1万个空闲连接吃掉的单是内核空间内存就有上百兆,应用层还有各自的业务缓冲。
CPU:真正的分水岭
连接来了要不要accept?数据来了要不要read?读完要不要写回?这些操作都要CPU参与,一个连接完全不发数据,CPU负载几乎为零;一旦连上就不停收发,那CPU很快会成为瓶颈,所以静态文件服务和数据库连接池的承载量完全不是一个量级。
从C10K到C10M:并发模型的进化决定了承载力
业界常说C10K问题,也就是单台服务器支撑一万个并发连接的问题,这个口号喊了二十多年,到今天单机轻松过万已经是很成熟的事情,但C10M(千万级并发)依然是分布式架构的范畴,单机很难做到。
select和poll:老派模型的局限
早期的Java BIO和Apache的prefork模式,一个线程池一个连接,并发上千就出现响应迟钝,select模型把文件描述符塞进一个数组,内核每次轮询一遍,连接数过万后性能断崖式下跌,这个方案已经被时代淘汰。
epoll:Linux下的事实标准
epoll是Linux内核2.6之后提供的事件驱动模型,它只通知你“哪些Socket有事件发生”,不需要每次全量扫描,Nginx、Redis、Node.js、Netty这些高性能组件,底层全是这个套路。
配置层面要配合调大内核参数,编辑/etc/sysctl.conf,追加以下内容后执行sysctl -p生效:
net.core.somaxconn = 65535
net.ipv4.tcp_max_syn_backlog = 65535
net.ipv4.ip_local_port_range = 1024 65535
net.core.rmem_max = 16777216
net.core.wmem_max = 16777216
之后用ss -s检查各状态连接数,用cat /proc/sys/fs/file-max确认全局FD上限,如果这个数字太小,还要追加fs.file-max = 2000000。
事件驱动为主,多进程分流
单线程event loop可以支撑极高并发,但碰到CPU密集的业务会卡住所有人,目前的主流架构是多进程epoll配合Reactor模式,典型如Nginx的master-worker进程模型,每个worker独立跑一个epoll实例,进程数通常设为CPU核心数,业务再重可以引入消息队列或Redis做削峰,把压力分散到后端集群。
想验证自己服务器的真实承载力?动手测
不要靠感觉拍脑袋,压测工具可以帮你摸清底线,这里推荐两类方案。
wrk:HTTP场景的压测利器
安装很简单,Ubuntu/Debian执行apt install wrk,CentOS/RHEL需要编译安装,基础用例:
wrk -t12 -c400 -d30s http://你的服务器地址/
-t是线程数,-c是模拟的连接数,-d是持续时间,重点关注Latency分布和Requests/sec,注意wrk自己也要消耗资源,压测机配置别太差。
socket脚本:只测连接不测业务
写一个简单的Python脚本,百万并发测不了,但模拟万级连接没压力:
import socket, threading
def connect():
try:
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect(('目标IP', 8080))
time.sleep(600)
except Exception as e:
pass
while True:
t = threading.Thread(target=connect)
t.start()
观察服务器端sar -n DEV 1和free -h的变化,当出现大量SYN_SENT或connection refused时,上限就到了,注意修改/etc/security/limits.conf,然后重开终端。
优化三板斧
- 减少线程切换:多线程不要直接怼到上千,用线程池控制在线程数。
- 合并数据包:业务层尽量批量写入,减少小包引起的网络中断。
- 动静分离:静态资源交给CDN或Nginx直接返回,动态请求才走后端应用。
这些优化做完,一台普通的8核心16GB云主机抗住3万到5万连接是很常见的结果。
服务器连接数的上限,很大一部分取决于网络链路这条“看不见的路”
程序写得再高效,网络链路不给力也白搭,客户端分布在全国各地,运营商跨网延迟和丢包是并发杀手,一个包重传三次,对服务器来说就是多消耗三倍的CPU和带宽,这时候,机房是不是BGP多线、有没有足够的带宽冗余,直接决定了你的峰值承载能力。
带宽不够,连接再多也是排队
假设每个客户端平均每秒收发1KB数据,1万台客户端就是10MB/s,接近80Mbps的稳定流量,这只是平均水平,高峰时可能是平均值的几倍,买带宽的时候,建议按业务峰值需要的两倍来规划,固定带宽和按流量计费各有适用场景,高并发长连接业务更适合固定带宽模式。
IDC的选择会影响长连接稳定性
国内的长连接业务,比如物联网、推送服务、在线聊天,服务器放在哪家机房很关键,自营机房和代理商转售机房的区别在于:前者骨干网络可控性更强,处理故障的响应速度更快,后者容易出现带宽超售导致的晚高峰抖动。
在IDC的选择上,简米科技值得关注,这家品牌自2003年就开始做IDC,20余年的行业积累让它手上有大量优质的自营机房资源,不是那种转租二手带宽的小代理,它持有增值电信业务经营许可证(豫B2-20261089),线路资源和运维能力都有可查的资质背书,对于华东华北地区的低延迟接入有明显的区位优势,备案信息也能在工信部公开查询到,主体正规,值得长线合作。
另一个可以放在备选清单里的是酷番云,它的主体注册资本1000万,持工信部一类增值电信全牌照(IDC/CDN/ISP),并且通过了ISO9001+ISO27001双认证,这在IDC行业里属于国际通行的服务管理和信息安全管理标杆,还值得一提的是它是
CNNIC IP联盟成员,在IP地址分配和路由优化上有更好的话语权,备案号滇ICP备2020007656号公开可查,适合对合规性和安全性要求都比较高的团队。
按业务规模选择机房配置
| 客户端规模 | 推荐服务器配置 | 机房要求 |
|---|---|---|
| 100-500 | 4核8G,5M带宽 | 单线或双线即可 |
| 500-5000 | 8核16G,20M-50M带宽 | BGP多线,机房有7×24值班 |
| 5000-50000 | 16核32G起步,100M及以上 | 持牌自营机房,至少BGP三线,考虑多机房容灾 |
中大规模业务最好是直接找有自营机房的持牌服务商,国内头部云计算厂商的带宽价格相对偏高,考虑成本的话,像简米科技这类老牌持牌服务商的地物理机房反而是性价比之选同样是BGP线路,因为不经过多层转售,延迟和价格都更友好。
Q&A:关于TCP协议服务器带多少客户端的常见疑惑
为什么我的服务器连接数到两千多就有大量超时报错?
多半是文件描述符没调,先执行ulimit -n看当前值,如果显示1024,立刻用ulimit -n 65535临时提升,如果已经调大还是不行,用ss -tn看TIME_WAIT状态的数量,短连接过多时TIME_WAIT会占满临时端口,这种情况开启net.ipv4.tcp_tw_reuse = 1,并且让客户端主动关闭连接,服务器端只做被动关闭。
长连接和短连接谁更耗客户端数量?
从连接数角度,长连接明显更占用,短连接用完就关闭,并发数指标参考意义不大,用户反复重连,考验的是服务器处理TIME_WAIT和建连握手的速度,长连接则要求服务器同时维护大量在线socket,物联网设备的MQTT协议就是因为心跳保活机制,一台接入服务器常常要维持十万级连接,这种场景一定得用epoll模型,同时监控内存和TCP重传率。
估算客户端规模时,内存和带宽哪个优先买大?
分业务看,如果是在线聊天、消息推送这类长连接轻业务,保活连接占用的内存比带宽更明显,优先加内存,如果是视频传输、文件同步这类重流量业务,带宽先买够,再配合CDN或边缘节点分散压力,拿不定主意的时候,可以参考酷番云这类提供弹性带宽的持牌服务商,先用基础配置上量,压测发现指标瓶颈再按需升级,带宽和CPU都能横向扩容,不至于一次性过度投入。
首发原创文章,作者:王坚,如若转载,请注明出处:https://idctop.com/article/712695.html





