深色模式
连接数耗尽排查
摘要:"连接数不够"至少有四种完全不同的成因:进程句柄限制、backlog 队列、TIME_WAIT 堆积、内核 conntrack 表满。本文按现象分别给出判定命令与处置方式,避免一律调大参数的错误做法。
适用环境
bash
cat /proc/sys/fs/file-max
ulimit -n
cat /proc/sys/net/core/somaxconn
cat /proc/sys/net/netfilter/nf_conntrack_max 2>/dev/null1
2
3
4
2
3
4
排障步骤
第 1 步:看连接总览与状态分布
bash
ss -s
ss -ant | awk 'NR>1 {print $1}' | sort | uniq -c | sort -rn1
2
2
重点关注 TIME_WAIT、SYN_RECV、CLOSE_WAIT 三类异常堆积。
第 2 步:判断是进程句柄不够
bash
ls /proc/<PID>/fd | wc -l
cat /proc/<PID>/limits | grep -i 'open files'
lsof -p <PID> 2>/dev/null | wc -l1
2
3
2
3
systemd 服务的限制不看 limits.conf
由 systemd 管理的服务以 unit 中的 LimitNOFILE 为准,/etc/security/limits.conf 对其无效。
第 3 步:CLOSE_WAIT 堆积 = 应用没关连接
bash
ss -antp state close-wait | head -201
CLOSE_WAIT 是被动关闭方收到对方 FIN 后未发 FIN,属应用代码缺陷(连接泄漏),调内核参数无效,必须修复代码或重启。
第 4 步:TIME_WAIT 堆积与端口耗尽
bash
ss -ant state time-wait | wc -l
cat /proc/sys/net/ipv4/ip_local_port_range
ss -ant state time-wait '( sport = :<本地端口范围起始> : 65535 )' | wc -l1
2
3
2
3
TIME_WAIT 本身是正常的
TIME_WAIT 是 TCP 可靠关闭的必要状态,只有在本机作为主动发起方且临时端口区间被占满(出现 Cannot assign requested address)时才需要处理。
第 5 步:backlog 与半连接队列
bash
cat /proc/sys/net/core/somaxconn
cat /proc/sys/net/ipv4/tcp_max_syn_backlog
netstat -s 2>/dev/null | grep -i -E 'listen|overflow|drop'1
2
3
2
3
ListenOverflows、SYNs to LISTEN sockets dropped 计数持续增长说明 backlog 不足或应用 accept 太慢。
第 6 步:conntrack 表满(网关/LB 常见)
bash
cat /proc/sys/net/netfilter/nf_conntrack_count 2>/dev/null
cat /proc/sys/net/netfilter/nf_conntrack_max 2>/dev/null
dmesg -T | grep -i 'nf_conntrack: table full'1
2
3
2
3
表满时新连接直接被丢,抓包看不到任何异常握手,极易误判为网络问题。
验证
bash
ss -s
ss -ant | awk 'NR>1 {print $1}' | sort | uniq -c | sort -rn | head
curl -sS -o /dev/null -w 'code=%{http_code} connect=%{time_connect}\n' http://127.0.0.1:8080/1
2
3
2
3
常见坑
用 netstat 在大连接量机器上会卡死
netstat 遍历 /proc/net/tcp 效率低,连接数上万时应一律使用 ss。
只调大参数不查泄漏
连接数被打满往往是应用未正确关闭连接或连接池配置过大,单纯调 fd 上限只是推迟故障。
容器内的连接计数与宿主机不一致
网络命名空间隔离,容器内 ss 只看到自己的连接,conntrack 表通常是宿主机共享的。
启用已废弃的 tcp_tw_recycle
该参数在较新内核中已被移除,且在 NAT 环境下会导致连接被随机丢弃。不要照搬过时文档启用它。