Linux TCP并发连接受限本质是socket句柄受三重限制:用户级(ulimit -n)、服务级(systemd LimitNOFILE)和内核级(fs.file-max等),必须同步调整三者并重新登录或重启服务才能生效。

Linux 中 TCP 并发连接受限,本质是每个连接对应一个 socket 文件句柄,而系统对文件句柄有层层限制。要真正放开并发能力,必须同时调整用户级、服务级和内核级三处配置,缺一不可。
查清当前瓶颈在哪
先确认问题是否真出在文件句柄上:
- 运行 ulimit -n 查看当前 shell 进程的软限制(通常默认 1024)
- 用 cat /proc/sys/fs/file-max 看系统全局上限(比如 80 万)
- 执行 lsof -n | awk '{print $2}' | sort | uniq -c | sort -nr | head -5 找出打开句柄最多的进程
- 检查具体服务进程:比如 cat /proc/$(pgrep nginx)/limits | grep "Max open files"
用户级:放宽单进程句柄上限
这是最常被忽略的第一层限制。修改 /etc/security/limits.conf:
- 为特定用户(如 www-data 或 root)添加两行:
www-data soft nofile 65536
www-data hard nofile 65536 - 不能只写 * soft nofile 65536 —— root 不匹配通配符,systemd 也不读它
- 确保 /etc/pam.d/common-session(Ubuntu/Debian)或 /etc/pam.d/login(CentOS)中含 session required pam_limits.so
- 改完需重新登录 SSH(su - 不生效),才能让新会话加载限制
服务级:让 systemd 进程真正用上新限制
现代 Linux 下,nginx、redis 等通过 systemctl start 启动的服务完全无视 limits.conf。必须显式配置:
- 对单个服务(推荐):sudo systemctl edit nginx.service,加入:
-
[Service]
LimitNOFILE=65536 - 或全局生效:sudo systemctl edit --full systemd-system.conf,加 DefaultLimitNOFILE=65536
- 每次修改后必须执行:sudo systemctl daemon-reload && sudo systemctl restart nginx
- 验证:cat /proc/$(pgrep nginx)/limits | grep "Max open files" 应显示 65536
内核级:保障系统资源兜底
再大的进程限制,也得有内核支撑。编辑 /etc/sysctl.conf:
- fs.file-max = 1000000 —— 整机最大可分配句柄数
- net.core.somaxconn = 65535 —— listen() 队列长度,影响新建连接吞吐
- net.ipv4.ip_local_port_range = 1024 65535 —— 扩展客户端可用端口范围
- 生效命令:sudo sysctl -p
- 注意:hard nofile 不能超过 fs.file-max,否则 ulimit 设置会被静默拒绝


















