Linux TCP连接监控与问题排查实战指南

📅 2026/8/5 12:16:38
Linux TCP连接监控与问题排查实战指南
1. TCP连接监控在Linux系统中的核心价值在Linux服务器运维和网络问题排查中TCP连接状态监控就像系统管理员的听诊器。上周处理线上服务超时问题时通过分析TCP连接状态发现大量TIME_WAIT状态的连接堆积最终定位到是客户端没有正确关闭连接导致。这种实战场景让我深刻体会到掌握TCP监控技术的重要性。Linux系统提供了从内核层到应用层的完整TCP监控工具链主要包括/proc/net/tcp伪文件 - 实时反映内核TCP栈的连接状态ss/netstat命令 - 用户态连接统计工具lsof命令 - 关联进程与连接信息tcpdump/wireshark- 抓包分析工具这些工具组合使用可以构建从宏观统计到微观分析的完整监控方案。比如先用ss -s查看全局统计再用ss -tlnp定位具体问题连接最后通过tcpdump抓包分析具体流量模式。2. /proc文件系统下的TCP连接详情2.1 /proc/net/tcp文件结构解析/proc/net/tcp是Linux内核暴露的原始TCP连接信息接口每行对应一个TCP连接包含16个字段。通过cat /proc/net/tcp查看时典型输出如下sl local_address rem_address st tx_queue rx_queue tr tm-when retrnsmt uid timeout inode 0: 0100007F:0016 00000000:0000 0A 00000000:00000000 00:00000000 00000000 0 0 12345 1 ffff88012a3b8e00 100 0 0 10 0 1: 00000000:14EB 00000000:0000 0A 00000000:00000000 00:00000000 00000000 1000 0 67890 1 ffff88012a3b8d00 100 0 0 10 0关键字段说明local_address本地IP:端口十六进制rem_address远端IP:端口十六进制st连接状态十六进制值如0A表示TCP_LISTENtx_queue/rx_queue发送/接收队列大小uid所属用户IDinode关联的socket inode号注意/proc/net/tcp显示的是原始内核数据IP和端口都是网络字节序大端的十六进制值需要转换后才能阅读。例如0100007F表示127.0.0.10016表示22端口。2.2 状态码与连接生命周期TCP连接状态st字段是监控的关键指标常见状态码包括十六进制值宏定义说明01TCP_ESTABLISHED连接已建立正常数据传输状态02TCP_SYN_SENT客户端发送SYN包后的等待状态03TCP_SYN_RECV服务端收到SYN包后的状态04TCP_FIN_WAIT1主动关闭方发送FIN后的状态05TCP_FIN_WAIT2半关闭状态等待对方FIN06TCP_TIME_WAIT连接完全关闭前的等待状态07TCP_CLOSE连接完全关闭08TCP_CLOSE_WAIT被动关闭方收到FIN后的状态09TCP_LAST_ACK被动关闭方发送FIN后的状态0ATCP_LISTEN服务端监听状态在实际监控中需要特别关注异常状态大量SYN_RECV可能遭受SYN Flood攻击堆积的CLOSE_WAIT通常表示应用没有正确关闭连接TIME_WAIT过多可能消耗端口资源3. 使用AWK进行高级TCP连接分析3.1 基础AWK处理脚本AWK是处理/proc/net/tcp的利器。这个脚本可以转换IP端口并统计各状态连接数awk BEGIN { printf %-15s %-20s %-20s %-12s %-8s\n, Local, Remote, State, UID, Inode } NR 1 { # 转换本地地址 split($2, local, :) local_ip sprintf(%d.%d.%d.%d, strtonum(0x substr(local[1],7,2)), strtonum(0x substr(local[1],5,2)), strtonum(0x substr(local[1],3,2)), strtonum(0x substr(local[1],1,2))) local_port strtonum(0x local[2]) # 转换远程地址 split($3, remote, :) remote_ip sprintf(%d.%d.%d.%d, strtonum(0x substr(remote[1],7,2)), strtonum(0x substr(remote[1],5,2)), strtonum(0x substr(remote[1],3,2)), strtonum(0x substr(remote[1],1,2))) remote_port strtonum(0x remote[2]) # 状态码转换 state_code strtonum(0x $4) state (state_code 1) ? ESTAB : (state_code 2) ? SYN_SENT : (state_code 3) ? SYN_RECV : (state_code 4) ? FIN_WAIT1 : (state_code 5) ? FIN_WAIT2 : (state_code 6) ? TIME_WAIT : (state_code 7) ? CLOSE : (state_code 8) ? CLOSE_WAIT : (state_code 9) ? LAST_ACK : (state_code 10) ? LISTEN : UNKNOWN printf %-15s:%-5d %-20s:%-5d %-12s %-8d %d\n, local_ip, local_port, remote_ip, remote_port, state, $8, $10 } /proc/net/tcp3.2 高级监控场景实现3.2.1 检测异常连接这个脚本可以检测异常状态的连接awk -v threshold10 BEGIN { abnormal[SYN_RECV] 可能遭受SYN Flood攻击 abnormal[CLOSE_WAIT] 应用未正确关闭连接 abnormal[TIME_WAIT] 连接关闭但未释放资源 } NR 1 { state_code strtonum(0x $4) state (state_code 3) ? SYN_RECV : (state_code 8) ? CLOSE_WAIT : (state_code 6) ? TIME_WAIT : if (state in abnormal) count[state] } END { for (s in count) { if (count[s] threshold) { printf 警告: 检测到%d个%s状态连接 - %s\n, count[s], s, abnormal[s] } } } /proc/net/tcp3.2.2 连接数趋势分析记录历史数据并分析趋势# 每5分钟记录一次连接数 while true; do date$(date %Y-%m-%d %H:%M:%S) total$(awk END{print NR-1} /proc/net/tcp) estab$(awk $401{count}END{print count} /proc/net/tcp) echo $date,$total,$estab /var/log/tcp_connections.log sleep 300 done # 使用gnuplot生成趋势图 gnuplot EOF set terminal png set output tcp_trend.png set xdata time set timefmt %Y-%m-%d %H:%M:%S set format x %H:%M set xlabel Time set ylabel Connections plot /var/log/tcp_connections.log using 1:2 title Total with lines, \ using 1:3 title ESTAB with lines EOF4. 生产环境问题排查实战4.1 CLOSE_WAIT连接堆积案例某次线上服务出现响应变慢通过监控发现CLOSE_WAIT状态连接持续增长。排查步骤使用增强版监控脚本定位问题awk $408{print $1,$2,$3,$8,$10} /proc/net/tcp | head -n 20通过inode号关联进程lsof -i -n -P | grep inode发现是Java应用未调用close()方法修复方案修改代码确保所有Socket使用try-with-resources增加连接池空闲超时设置添加finally块显式关闭连接4.2 TIME_WAIT优化方案当TIME_WAIT连接过多时通常超过3万可以调整内核参数# 查看当前配置 sysctl net.ipv4.tcp_fin_timeout sysctl net.ipv4.tcp_max_tw_buckets # 优化设置临时生效 sysctl -w net.ipv4.tcp_fin_timeout15 sysctl -w net.ipv4.tcp_max_tw_buckets180000 sysctl -w net.ipv4.tcp_tw_reuse1 sysctl -w net.ipv4.tcp_tw_recycle1 # 注意NAT环境下可能导致问题 # 永久生效 echo net.ipv4.tcp_fin_timeout15 /etc/sysctl.conf echo net.ipv4.tcp_max_tw_buckets180000 /etc/sysctl.conf sysctl -p重要提示tcp_tw_recycle在Linux 4.12后已移除NAT环境下使用可能导致连接问题。生产环境建议优先考虑应用层优化而非内核参数调整。5. 进阶监控工具与技巧5.1 使用ss命令替代netstat现代Linux系统推荐使用ss而非netstat因为它直接从内核获取信息效率更高# 显示所有TCP连接 ss -t -a # 显示监听端口 ss -t -l # 显示进程信息 ss -t -p # 统计各状态连接数 ss -s5.2 网络命名空间中的TCP监控在容器化环境中需要进入容器的网络命名空间进行监控# 查看容器的网络命名空间 docker inspect --format {{.State.Pid}} container_id # 进入命名空间监控 nsenter -t pid -n ss -t -a nsenter -t pid -n cat /proc/net/tcp5.3 构建实时监控面板使用Prometheus Grafana构建TCP监控面板配置node_exporter收集TCP指标# node_exporter配置 collectors: enabled: tcpstatGrafana面板关键指标TCP状态分布饼图连接数变化趋势异常状态告警各服务连接数排名告警规则示例groups: - name: tcp_alerts rules: - alert: HighCloseWaitConnections expr: node_sockstat_TCP_close_wait 100 for: 5m labels: severity: warning annotations: summary: High CLOSE_WAIT connections ({{ $value }}) description: Instance {{ $labels.instance }} has too many CLOSE_WAIT connections