1. 为什么我们需要监控TCP连接?
在Linux服务器运维和网络问题排查中,TCP连接状态监控是每个系统管理员必须掌握的技能。想象一下这样的场景:你的Web服务器突然响应变慢,用户投诉不断,而你需要在几分钟内定位问题。这时,快速查看活跃的TCP连接状态就能帮你判断是DDoS攻击、数据库连接池泄漏,还是后端服务异常。
我在处理线上事故时,曾遇到过一个典型案例:某电商大促期间,Nginx服务器出现大量TIME_WAIT状态的连接,导致新用户无法下单。通过实时监控TCP连接状态,我们迅速发现是PHP-FPM配置不当,没有正确复用TCP连接,最终通过调整keepalive_timeout参数解决了问题。
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. TCP连接监控的四大核心工具
2.1 /proc/net/tcp:内核级的连接快照
Linux内核将所有TCP连接信息暴露在/proc/net/tcp这个虚拟文件中。这个文件包含了每个连接的十六进制表示的:
- 本地IP:端口
- 远程IP:端口
- 连接状态
- 传输队列信息
我常用这个命令快速查看关键信息:
bash复制cat /proc/net/tcp | awk '{print $1,$2,$3,$4,$10}'
注意:IP和端口显示为十六进制,本地地址是小端字节序。比如
0100007F:0016表示127.0.0.1:22
2.2 ss命令:现代版的netstat
ss是iproute2工具包的一部分,比传统的netstat更快速、更详细。我最常用的几个参数组合:
bash复制ss -tulnp # 查看所有TCP/UDP监听端口
ss -s # 统计摘要
ss -o state established '( dport = :443 or sport = :443 )' # 筛选特定状态和端口的连接
2.3 netstat:经典工具的深度用法
虽然逐渐被ss取代,但netstat在某些场景下仍然有用:
bash复制netstat -tanp | grep ESTABLISHED | awk '{print $5}' | cut -d: -f1 | sort | uniq -c | sort -nr
这个管道命令可以统计已建立连接的远程IP数量,快速发现异常连接。
2.4 lsof:当需要进程关联信息时
当需要知道哪个进程持有特定连接时,lsof是终极武器:
bash复制lsof -iTCP -sTCP:ESTABLISHED -P -n
参数说明:
-iTCP:只显示TCP连接-sTCP:ESTABLISHED:只显示已建立连接-P -n:禁止端口号转换和服务名解析(提升速度)
3. 实战:用AWK分析TCP连接状态
AWK是处理/proc/net/tcp的神器。下面分享我常用的分析脚本:
3.1 状态统计脚本
bash复制cat /proc/net/tcp | awk 'BEGIN {
states["01"]="ESTABLISHED"; states["02"]="SYN_SENT";
states["03"]="SYN_RECV"; states["04"]="FIN_WAIT1";
states["05"]="FIN_WAIT2"; states["06"]="TIME_WAIT";
states["07"]="CLOSE"; states["08"]="CLOSE_WAIT";
states["09"]="LAST_ACK"; states["0A"]="LISTEN";
states["0B"]="CLOSING";
}
NR>1 {count[states[$4]]++}
END {for(s in count) print s,count[s]}' | sort -rnk2
这个脚本会输出类似:
code复制ESTABLISHED 142
TIME_WAIT 38
LISTEN 12
3.2 连接数TOP IP统计
bash复制cat /proc/net/tcp | awk 'NR>1 {
split($3,remote,":");
ip=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));
count[ip]++
}
END {for(i in count) print i,count[i]}' | sort -rnk2 | head -10
4. 高级监控技巧与实战案例
4.1 实时监控脚本
这个脚本我用来监控关键服务的连接状态变化:
bash复制watch -n 5 '
echo -e "\n$(date)"
echo "====== 连接状态统计 ======"
ss -s | grep -A 10 Total
echo "====== ESTABLISHED连接TOP IP ======"
ss -nt state established | awk '\''{print $5}'\'' | cut -d: -f1 | sort | uniq -c | sort -rn | head -5
'
4.2 连接泄漏排查案例
某次我们发现Java应用内存持续增长,通过以下步骤定位问题:
- 用
ss -s发现CLOSE_WAIT状态连接异常多 - 用
lsof -iTCP -sTCP:CLOSE_WAIT找到相关进程 - 用
strace -p <pid>跟踪发现应用没有正确关闭socket - 最终定位到try-with-resources块中漏关了连接
4.3 TCP状态机深度解析
理解TCP状态转换对问题排查至关重要:
code复制三次握手:
CLOSED -> SYN_SENT -> SYN_RECV -> ESTABLISHED
四次挥手:
ESTABLISHED -> FIN_WAIT_1 -> FIN_WAIT_2 -> TIME_WAIT -> CLOSED
-> CLOSE_WAIT -> LAST_ACK -> CLOSED
常见异常状态:
- 大量
SYN_RECV:可能遭受SYN Flood攻击 - 大量
FIN_WAIT2:对端没有发送FIN - 大量
TIME_WAIT:短连接过多,考虑调整tcp_tw_reuse
5. 性能优化关键参数
在/etc/sysctl.conf中调整这些参数可以优化TCP连接处理:
conf复制# TIME_WAIT连接快速回收
net.ipv4.tcp_tw_reuse = 1
net.ipv4.tcp_tw_recycle = 1 # 注意:NAT环境下不要启用
# 连接追踪表大小
net.ipv4.ip_conntrack_max = 65536
net.ipv4.netfilter.ip_conntrack_max = 65536
# 半连接队列大小
net.ipv4.tcp_max_syn_backlog = 8192
# 文件描述符限制
fs.file-max = 100000
修改后执行sysctl -p生效。我在生产环境中调整这些参数后,将Nginx的并发处理能力提升了约30%。
6. 容器环境下的特殊考量
在Docker/K8s环境中,TCP监控有几个特殊点:
- 每个容器有自己的网络命名空间,需要用
nsenter进入容器网络空间:
bash复制docker inspect --format '{{.State.Pid}}' <container> | xargs -I {} nsenter -t {} -n ss -ant
-
K8s的Service会创建大量
TIME_WAIT连接,这是正常现象 -
容器网络插件(如Calico)会增加连接跟踪的开销
7. 编写自定义监控工具
对于需要长期监控的场景,我通常会写Python脚本收集TCP指标:
python复制import psutil
def get_tcp_connections():
stats = {}
for conn in psutil.net_connections('tcp'):
state = conn.status
stats[state] = stats.get(state, 0) + 1
return stats
这个脚本可以集成到Prometheus中,配合Grafana展示TCP状态变化趋势。
