这是一个非常好的问题,也是运维中常见的场景。简单来说:需要担心,而且应该立即着手排查,这通常意味着系统存在潜在问题或配置不当。
CPU使用率正常但连接数很高,说明系统没有在进行繁重的计算,但正在维持大量的网络连接状态。这就像一家餐厅,厨师(CPU)不忙,但门口挤满了等待的客人(连接),或者餐厅里坐满了只聊天不点菜的客人(空闲/僵死连接)。
为什么需要担心?
- 资源耗尽风险:每个连接都会占用一定的内存(内核态的内存,如
tcp_mem)、文件描述符和端口号。连接数过高可能导致这些资源耗尽,导致新连接无法建立,服务完全不可用。 - 性能下降和延迟增加:即使CPU不高,大量的连接也会增加网络栈的处理负担,可能导致数据包处理延迟、应用程序响应变慢。
- 可能是攻击或异常行为的迹象:
- DDoS攻击:特别是连接耗尽型攻击(如Slowloris攻击),会故意建立并保持大量慢速或空闲连接,耗尽服务器的连接资源。
- 应用程序Bug:客户端没有正确关闭连接(连接泄漏),或者服务端处理完请求后没有及时释放连接。
- 客户端配置问题:例如,使用了连接池但配置不当,导致连接数膨胀。
如何排查?—— 一个系统的排查思路
第一步:分析连接的类型和状态
在ECS实例上执行以下命令,查看连接的详细信息:
-
查看总体连接统计:
netstat -an | grep -w '80|443' | wc -l # 查看指定端口(如80/443)的总连接数 ss -s # 推荐使用ss命令,更清晰。查看总连接数、各状态连接数统计重点关注
TIME_WAIT,CLOSE_WAIT,ESTABLISHED状态的数量:TIME_WAIT过多:通常是主动关闭连接的一方(很可能是你的服务器)产生的。这是TCP协议的正常部分,但数量过多(例如上万)可能消耗端口资源。通常需要优化内核参数(如net.ipv4.tcp_tw_reuse,net.ipv4.tcp_tw_recycle– 注意后者在较新内核中已废弃)。CLOSE_WAIT过多:这是危险信号! 表示对方已经关闭连接,但你的应用程序没有主动调用close()。几乎可以肯定是应用程序Bug导致连接泄漏。ESTABLISHED过多:活跃连接。需要看是否与你的业务量匹配。
-
查看连接来源:
ss -tnp state established sport = :80 # 查看80端口所有已建立连接的客户端IP和进程 netstat -anp | grep :80 | grep ESTABLISHED- 检查连接是否来自大量不同的IP(可能是攻击或正常用户访问)。
- 检查是否集中在少数几个IP(可能是某个客户端/爬虫的异常行为)。
第二步:定位关联的进程和应用程序
使用ss或netstat的-p选项(需要sudo)查看是哪个进程创建的连接。
sudo ss -tnp | head -20
sudo netstat -tnp | head -20
确定是Nginx、Apache、Java应用、MySQL还是其他进程。这能帮你缩小排查范围。
第三步:检查应用程序和中间件配置
- Web服务器(Nginx/Apache):检查
worker_connections,MaxClients,MaxRequestsPerChild等配置是否设置过低或过高。 - 数据库(MySQL/Redis):检查
max_connections配置和当前连接数。应用端连接池配置是否过大。 - 应用服务器(Java/Python/Go):检查应用框架的连接池配置(如HikariCP, Druid, HTTP客户端连接池)。连接池设置过大是常见原因。
- 检查应用日志:查看是否有连接超时、读写错误等异常日志。
第四步:检查系统限制
ulimit -n # 查看单个进程可打开的文件描述符(FD)限制
cat /proc/sys/fs/file-nr # 查看系统全局已使用/可用的FD数
cat /proc/sys/net/ipv4/ip_local_port_range # 查看客户端可用端口范围
如果连接数接近这些限制,系统将无法建立新连接。
可能的解决方案
-
应急扩容:临时提升ECS实例的规格(特别是内存),并调高系统级限制:
# 临时修改 echo 1000000 > /proc/sys/fs/file-max ulimit -n 100000(永久修改需编辑
/etc/sysctl.conf和/etc/security/limits.conf) -
优化内核参数(针对
TIME_WAIT多的情况):# 编辑 /etc/sysctl.conf net.ipv4.tcp_tw_reuse = 1 net.ipv4.tcp_fin_timeout = 30 # 降低FIN等待时间 net.ipv4.tcp_max_tw_buckets = 5000 # 限制TIME_WAIT最大数量 # 执行 sysctl -p 生效 -
修复应用程序:
- 如果是
CLOSE_WAIT多,必须修复代码中的资源关闭逻辑。 - 合理配置连接池大小,通常不需要设置得非常大。
- 实现连接的健康检查和超时关闭机制。
- 如果是
-
架构优化:
- 引入负载均衡,将连接分散到多台后端服务器。
- 对于HTTP服务,考虑使用HTTP/2以减少多个并发连接。
- 对于静态资源,使用CDN分担连接压力。
- 在ECS前配置Web应用防火墙(WAF)或DDoS高防,抵御连接型攻击。
总结
| 连接状态 | 可能原因 | 危险程度 | 行动 |
|---|---|---|---|
| CLOSE_WAIT 多 | 应用程序未关闭连接(Bug) | 非常高 | 立即修复应用代码 |
| TIME_WAIT 多 | 主动关闭连接频繁(短连接多) | 中等 | 优化内核参数、改用长连接 |
| ESTABLISHED 多 | 业务流量大、连接池过大、攻击 | 高 | 分析来源、优化配置、扩容 |
| SYN_RECV 多 | 可能遭受SYN Flood攻击 | 非常高 | 启用防御、联系云厂商 |
结论:CPU正常但连接数高,不是一个可以忽略的“正常”状态。它是一个明确的警报,提示你需要立即检查系统的网络连接健康状况、应用程序逻辑和配置,以避免潜在的服务中断。 建议从ss -s命令开始,快速定位连接状态分布,然后按上述步骤深入排查。
CLOUD技术笔记