“CPU 不高、内存不涨,不代表没有问题。”
28 k 的 ESTABLISHED 教会我:
排查 TCP 第一步,先看 netstat,再看 ulimit。
希望这条经验能帮你少熬一个通宵。

一、现象:业务高峰时接口偶发 502
上周六晚,生产环境突然告警:
「/order/create 接口 502 比例 3%」。
登录跳板机,top 一看 CPU 仅 30%,内存 50%,一切看似风平浪静。
于是,我祭出那条“老伙计”命令:
bash
netstat -n | awk '/^tcp/{++S[$NF]} END{for(k in S) print k,S[k]}'
输出:
ESTABLISHED 28212
TIME_WAIT 4532
CLOSE_WAIT 7
FIN_WAIT2 11
28212 条 ESTABLISHED!直觉告诉我——连接没释放?
但数据库连接池才 200 条,远小于 28 k,问题不在 DB。
二、定位:先分清“谁”在连
1. 揪出 Java 进程
bash
netstat -apn | grep java | head -20
输出(节选):
tcp6 0 0 :::9080 :::* LISTEN 12345/java
tcp6 0 0 10.0.0.31:9080 10.0.0.42:56788 ESTABLISHED 12345/java
...
12345 正是 Tomcat 进程。
继续统计 Tomcat 端口 9080 上的连接数:
bash
netstat -n | grep :9080 | wc -l
结果:
28193
28 k 连接几乎全怼在 9080!
再扫一眼数据库 1521:
bash
netstat -n | grep :1521 | wc -l
87
DB 连接果然“岁月静好”。
结论:压力在应用层,不在数据库。
三、深挖:句柄数成“隐形天花板”
1. 查看当前用户 limit
bash
ulimit -a | grep "open files"
输出:
open files (-n) 4096
4096 太小!
当 ESTABLISHED 数 > 4 k 时,新连接会因 fd 耗尽而失败,
Nginx 收到 502 就理所当然了。
2. 确认系统级上限
bash
cat /proc/sys/fs/file-max
1000000
系统总句柄 100 w,绰绰有余;瓶颈在用户级 ulimit。
四、解决:永久调大 nofile
1. 临时生效(重启失效)
bash
ulimit -n 100001
2. 永久生效(推荐)
在 启动 Tomcat 的账号 下,编辑 ~/.bash_profile 追加:
bash
# 2025-06-21 增加句柄数,解决 TCP 连接 502 问题
ulimit -n 100001
保存后 source ~/.bash_profile,重启 Tomcat。
再次观察:
bash
netstat -n | awk '/^tcp/{++S[$NF]} END{for(k in S) print k,S[k]}'
ESTABLISHED 31002
TIME_WAIT 5123
连接数继续上涨,但 502 归零!
ulimit 调整成功。
五、彩蛋:CPU 核数别忘看
文中同事问:“这台机器 CPU 核心数多少?”
顺手查一下:
bash
lscpu | grep '^CPU(s)'
输出:
CPU(s): 12
12 核,足以支撑 3 w 长连接。
所以垂直扩容不如先调参数,别急着加机器。
六、一键检查脚本(收藏)
把下面脚本丢到跳板机,下次 502 直接跑:
bash
#!/bin/bash
# file: tcp_health.sh
echo ====== TCP 连接概览 ======
netstat -n | awk '/^tcp/{++S[$NF]} END{for(k in S) print k,S[k]}'
echo ====== 9080 端口连接 ======
netstat -n | grep :9080 | wc -l
echo ====== 1521 端口连接 ======
netstat -n | grep :1521 | wc -l
echo ====== 当前用户句柄数 ======
ulimit -n
七、结语
如果文章对你有用,**点个「赞」+「收藏」**支持原创!
评论区聊聊你踩过的 TCP 坑,一起进阶~
4984

被折叠的 条评论
为什么被折叠?



