
1. 先搞清楚ss和netstat到底在查什么排查网络连接问题尤其是 TCP/IP 和 Socket 连接状态是 Linux 系统运维和后台开发的基本功。很多人一遇到连接超时、端口占用、服务起不来就习惯性地敲netstat -tulpn或ss -tulpn。但这两个命令输出的LISTEN、ESTABLISHED、TIME_WAIT到底意味着什么为什么连接数会暴涨为什么端口明明在监听却连不上这些问题光看命令输出是不够的。这篇文章不打算罗列所有参数而是围绕“状态排查”这个核心带你像老手一样从现象倒推原因。我会假设你遇到了一个具体问题某个服务的连接异常增多或者端口无法建立新连接。然后我们用ss和netstat作为“听诊器”结合 TCP/IP 协议栈的原理一步步诊断。目标是让你看完后不仅能看懂状态还能根据状态推断出上游的应用行为或系统配置问题。最关键的几个状态是ESTABLISHED、TIME_WAIT、CLOSE_WAIT、FIN_WAIT2。它们直接反映了连接的生命周期是否健康。ss是netstat的现代替代品速度更快信息更直接建议新环境优先使用ss。2. 环境准备与命令选择为什么现在更推荐用ss在开始排查前得先确保你的“听诊器”是顺手且准确的。传统上大家用netstat它来自net-tools软件包历史久远。而现在主流的 Linux 发行版如 CentOS 7/8, Ubuntu 18.04, Rocky Linux更推荐使用iproute2套件中的ss命令。为什么选ss速度极快netstat通过读取/proc/net/tcp等文本文件来获取信息当连接数上万时解析会非常慢。ss直接从内核 TCP 协议栈获取数据结构几乎是瞬时返回。信息更丰富ss能显示更多内核级别的信息比如 socket 的内存使用情况skmem、过滤条件更强大。未来趋势net-tools已停止维护iproute2是现在和未来的标准。安装与基本检查如果你的系统没有ss通常安装iproute2包即可。对于netstat则需要net-tools。# 检查 ss 是否存在 which ss # 检查 netstat 是否存在 which netstat # 安装 iproute2 (通常已预装) # CentOS/Rocky/Fedora: sudo yum install iproute # Ubuntu/Debian: sudo apt install iproute2 # 安装 net-tools (如需) # CentOS/Rocky/Fedora: sudo yum install net-tools # Ubuntu/Debian: sudo apt install net-tools一个重要的前置步骤确认你排查的视角。你是要查监听端口服务端还是查发起连接客户端或者是查所有的活跃连接这决定了你使用命令的过滤选项。查监听端口关注LISTEN状态。确认服务是否成功绑定到指定 IP 和端口。查所有连接关注ESTABLISHED,TIME_WAIT,CLOSE_WAIT等。用于分析连接负载和异常。查特定进程需要知道进程的 PID或者通过端口反查进程。接下来我们进入核心环节解读状态。3. 拆解 TCP 连接状态从三次握手到四次挥手要排查必须先理解。TCP 连接的状态变迁图是排查的“地图”。我们不需要背下所有 11 种状态但必须深刻理解影响排查的这几个3.1 建立连接LISTEN-SYN-SENT/SYN-RCVD-ESTABLISHEDLISTEN: 服务端套接字调用listen()后进入的状态。它不是在“通信”而是在“等待连接请求”。用ss -tlpn或netstat -tlpn查看。ss -tlpn | grep :80 # 或 netstat -tlpn | grep :80排查点如果服务应该监听 80 端口但这里没显示那可能是服务没启动、绑定 IP 错误、端口冲突或者防火墙规则阻止了绑定。SYN-SENT与SYN-RCVD: 三次握手过程中的中间状态。SYN-SENT是客户端发出 SYN 包后等待服务器回复SYN-RCVD是服务器收到 SYN 并回复 SYN-ACK 后等待客户端 ACK。这些状态通常一闪而过如果大量存在意味着握手不成功可能是网络丢包、对端服务未响应或防火墙拦截。ss -t state syn-sent # 查看所有 SYN-SENT 状态的连接 ss -t state syn-recv # 查看所有 SYN-RCVD 状态的连接ESTABLISHED: 连接已建立数据可以双向传输。这是健康的、正在工作的连接。数量会随着业务流量波动。排查点ESTABLISHED连接数异常高可能是应用逻辑有 bug创建连接后未正常关闭虽然建立了但可能闲置。遇到了连接池配置问题或慢查询导致连接长时间占用。正常的高并发业务流量。3.2 断开连接核心故障高发区这是状态排查的重中之重TIME_WAIT和CLOSE_WAIT是“常客”。FIN-WAIT-1FIN-WAIT-2: 主动关闭方先调用close()的一方发送 FIN 后进入FIN-WAIT-1收到对方的 ACK 后进入FIN-WAIT-2此时等待对方发送 FIN。排查点如果FIN-WAIT-2状态连接过多且长时间存在通常是因为对端被动关闭方没有发送 FIN。这可能是因为对端应用卡住、崩溃或者网络问题导致 FIN 包丢失。系统有tcp_fin_timeout参数控制其超时时间默认 60 秒。CLOSE-WAIT:这是需要高度警惕的状态被动关闭方收到对端 FIN 的一方进入此状态。它意味着你的应用程序已经收到了对方的关闭请求FIN但你自己的应用程序没有调用close()来关闭本地的 Socket。排查点CLOSE-WAIT连接堆积是典型的应用程序 Bug。连接资源无法释放会导致可用文件描述符fd耗尽最终使服务无法接受新连接。看到大量CLOSE-WAIT第一反应是去查对应应用程序的日志和代码看是否有连接泄露。ss -t state close-waitLAST-ACK: 被动关闭方发送自己的 FIN 后等待对方最后一个 ACK 的状态。通常短暂存在。TIME-WAIT: 主动关闭方在发送完最后一个 ACK 后进入的状态。这是正常状态不是错误它会持续 2MSLMaximum Segment Lifetime报文最大生存时间通常为 60 秒。存在目的是确保最后一个 ACK 能到达对端如果丢失对端会重传 FINTIME-WAIT状态可以处理它。让旧连接的报文在网络中消逝避免被之后的新连接错误接收。排查点TIME-WAIT过多比如数万会占用大量端口和内存。常见于高并发短连接场景如频繁请求的 HTTP 客户端。解决方案不是消除它而是优化开启tcp_tw_reuse允许将TIME-WAIT套接字用于新的出向连接安全或tcp_tw_recycle强烈不推荐在 NAT 环境下会导致问题新版内核已移除。优化应用使用连接池减少短连接创建。增加本地端口范围net.ipv4.ip_local_port_range。CLOSING: 一种罕见的双方同时尝试关闭连接的状态。4. 实战排查流程从命令输出到问题根因现在我们模拟一个真实场景服务器监控报警某台机器的 TCP 连接数接近上限。4.1 第一步全局概览定位异常状态不要一上来就grep某个端口。先看全局哪种状态的数量异常。# 使用 ss按状态统计连接数这是最快的方法 ss -ant | awk ‘NR1 {print $1}’ | sort | uniq -c | sort -rn # 输出示例 # 1500 ESTAB # 8000 TIME-WAIT # 120 CLOSE-WAIT # 5 LISTEN # 2 FIN-WAIT-2解读TIME-WAIT有 8000 个虽然多但可能是业务特性短连接多先标记不是最紧急的。CLOSE-WAIT有 120 个红色警报。这代表有 120 个连接卡住了应用没有释放。必须立即处理。4.2 第二步深挖异常状态关联进程我们已经锁定CLOSE-WAIT。现在要找出是哪个进程干的。# 方法1使用 ss 显示进程信息 (推荐) ss -ntp state close-wait # 输出示例 # Recv-Q Send-Q Local Address:Port Peer Address:Port # 0 0 10.0.0.1:8080 10.0.0.2:54321 users:((java,pid1234,fd45)) # 关键看 users: 部分直接显示了进程名和 PID。 # 方法2使用 netstat netstat -ntp | grep CLOSE_WAIT # 输出类似最后一列是 PID/程序名找到了PID 是 1234进程是java。现在你有两个选择临时恢复重启这个 Java 进程以释放所有文件描述符。但这治标不治本。根因排查必须去分析这个 Java 应用的日志和代码。检查它的数据库连接池、HTTP 客户端连接池、或其他网络客户端如 Redis、MQ的使用逻辑看是否有连接在使用后没有正确关闭close()。常见于try-with-resources或finally块缺失的代码中。4.3 第三步分析TIME-WAIT问题如果TIME-WAIT多到影响了新连接创建报Cannot assign requested address错误就需要调整系统参数。检查当前系统配置# 查看本地可用端口范围 sysctl net.ipv4.ip_local_port_range # 输出net.ipv4.ip_local_port_range 32768 60999 # 可用端口数60999 - 32768 1 28232 个 # 查看 time-wait 相关参数 sysctl net.ipv4.tcp_tw_reuse sysctl net.ipv4.tcp_max_tw_buckets优化策略扩大端口范围谨慎需评估# 临时生效 sysctl -w net.ipv4.ip_local_port_range“10000 65000” # 永久生效写入 /etc/sysctl.conf echo “net.ipv4.ip_local_port_range 10000 65000” /etc/sysctl.conf sysctl -p开启tcp_tw_reuse对于出向连接通常安全sysctl -w net.ipv4.tcp_tw_reuse1 echo “net.ipv4.tcp_tw_reuse 1” /etc/sysctl.conf sysctl -p调整tcp_max_tw_buckets限制系统可持有的TIME-WAIT总数超过后会被直接回收。这是一个安全阀。sysctl -w net.ipv4.tcp_max_tw_buckets180000 echo “net.ipv4.tcp_max_tw_buckets 180000” /etc/sysctl.conf sysctl -p注意这只是一种限制根本解决之道是优化应用使用长连接或连接池。4.4 第四步排查“端口在监听却连不上”有时ss -tlpn能看到服务在LISTEN但客户端就是连接不上Connection refused或超时。排查顺序监听地址LISTEN的是0.0.0.0:80还是127.0.0.1:80如果是后者外部自然无法访问。防火墙检查 iptables/nftables 或 firewalld (firewall-cmd --list-all)。安全组如果是云服务器检查云平台的安全组规则。进程权限某些端口1024需要 root 权限监听。确认进程有权限。内核参数检查net.ipv4.tcp_tw_recycle已废弃和net.ipv4.tcp_timestamps的配置在 NAT 环境下不当配置会导致连接问题。建议保持tcp_timestamps1禁用tcp_tw_recycle。5. 进阶技巧与常用命令组合掌握了基础状态排查后这些组合命令能极大提升效率查看所有 TCP 连接并显示进程信息ss -ntp查看指定端口如 80的所有连接包括监听ss -ntp sport :80 or dport :80查看所有处于ESTABLISHED状态的连接并按远程 IP 统计ss -nt state established | awk ‘{print $5}’ | cut -d: -f1 | sort | uniq -c | sort -rn这有助于发现是否被某个 IP 建立了大量连接可能是正常流量也可能是攻击。查看 Socket 内存使用ss -tmss -tm关注skmem信息如果rmem_alloc或wmem_alloc异常高可能应用有内存泄漏或发送/接收缓冲区设置过大。对比netstat的类似功能netstat -ntp # 类似 ss -ntp netstat -s # 查看 TCP 协议栈统计信息对于分析重传、错误等很有用6. 总结建立你的排查清单TCP 连接状态排查核心是“状态即症状”。把这次的经验固化成你自己的排查清单下次遇到问题就能快速定位连接数暴涨先ss -ant | awk ...看状态分布。重点盯CLOSE-WAIT- 找对应进程 - 查应用日志和代码。关注TIME-WAIT- 检查端口范围、调整内核参数、优化应用连接策略。端口监听但连不上ss -tlpn确认监听 IP 和端口。检查防火墙iptables firewalld。检查云安全组。检查内核参数tcp_tw_recycle,tcp_timestamps。连接建立失败客户端抓包看是否有 SYN 发出。服务端看是否有SYN-RCVD状态ss -t state syn-recv。检查中间网络设备负载均衡、代理和防火墙规则。性能问题netstat -s或cat /proc/net/netstat查看重传率、错误计数。ss -tm查看 socket 内存。结合sar,top,vmstat看系统整体资源。最后记住ss和netstat是诊断工具它们告诉你“怎么了”但“为什么”和“怎么修”往往需要结合应用程序日志、代码审查和系统监控来回答。把连接状态当成应用与网络对话的“心电图”读懂它你就能从系统层面更深入地理解你的服务。