连接数上不去?先看系统瓶颈在哪
线上服务突然响应变慢,监控显示新建连接数卡在几千上不去,重启服务只能撑十分钟。这种情况别急着改代码,大概率是协议栈层面的连接数没调好。
Linux 默认的连接限制偏保守,一个普通云服务器刚起来时,能同时处理的 TCP 连接通常不超过 3 万。对于网关、长连接服务或者高并发 API,这数字根本不够用。
检查当前连接状态
先用 netstat 或 ss 看看真实情况:
ss -s输出里会显示当前 ESTAB(已建立)、TIME-WAIT、SYN-RECV 的数量。如果 SYN 队列堆积严重,说明握手阶段就卡住了。
调整内核参数是关键
打开 /etc/sysctl.conf,加几行硬货:
net.core.somaxconn = 65535
net.core.netdev_max_backlog = 65535
net.ipv4.tcp_max_syn_backlog = 65535
net.ipv4.ip_local_port_range = 1024 65535
net.ipv4.tcp_tw_reuse = 1
net.ipv4.tcp_fin_timeout = 15这几条分别管的是:最大监听队列、网卡收包队列、SYN 队列深度、本地端口范围、TIME-WAIT 复用和 FIN 超时时间。改完执行 sysctl -p 生效。
别忘了文件描述符限制
每个 TCP 连接都占一个 fd,系统默认 ulimit -n 可能只有 1024。服务跑起来没多久就报 "Too many open files"。
编辑 /etc/security/limits.conf,给运行用户加上:
* soft nofile 65536
* hard nofile 65536如果是 systemd 启动的服务,还得在 service 文件里加 LimitNOFILE=65536,不然不生效。
应用层也要配合
Java 服务用 Netty 做通信框架时,默认 backlog 是 128。就算系统调再高也没用。得显式设置:
ServerBootstrap b = new ServerBootstrap();
b.option(ChannelOption.SO_BACKLOG, 65535);Node.js 也一样,listen 的第二个参数就是 backlog,不设就是系统默认值,可能远低于你调的 somaxconn。
压测验证才敢上线
改完别直接扔生产。用 wrk 或者 jmeter 模拟高并发连接,观察是否还会出现连接超时或拒绝。
比如用 wrk 打接口:
wrk -t12 -c4000 -d30s http://your-api.com/health逐步加压,看到 RPS 稳定、延迟不飙升才算真正撑住了。
某次我们调了一个 MQTT 接入层,从最初撑不住 8000 连接,到最后单机扛下 12 万长连接,核心就是上面这几步一步步摸出来的。系统资源够,协议栈不拖后腿,服务才能放开跑。