ECS实例连接数很高但CPU使用率正常,需要担心吗?

这是一个非常好的问题,也是运维中常见的场景。简单来说:需要担心,而且应该立即着手排查,这通常意味着系统存在潜在问题或配置不当。

CPU使用率正常但连接数很高,说明系统没有在进行繁重的计算,但正在维持大量的网络连接状态。这就像一家餐厅,厨师(CPU)不忙,但门口挤满了等待的客人(连接),或者餐厅里坐满了只聊天不点菜的客人(空闲/僵死连接)。

为什么需要担心?

  1. 资源耗尽风险:每个连接都会占用一定的内存(内核态的内存,如tcp_mem)、文件描述符和端口号。连接数过高可能导致这些资源耗尽,导致新连接无法建立,服务完全不可用。
  2. 性能下降和延迟增加:即使CPU不高,大量的连接也会增加网络栈的处理负担,可能导致数据包处理延迟、应用程序响应变慢。
  3. 可能是攻击或异常行为的迹象
    • DDoS攻击:特别是连接耗尽型攻击(如Slowloris攻击),会故意建立并保持大量慢速或空闲连接,耗尽服务器的连接资源。
    • 应用程序Bug:客户端没有正确关闭连接(连接泄漏),或者服务端处理完请求后没有及时释放连接。
    • 客户端配置问题:例如,使用了连接池但配置不当,导致连接数膨胀。

如何排查?—— 一个系统的排查思路

第一步:分析连接的类型和状态

在ECS实例上执行以下命令,查看连接的详细信息:

  1. 查看总体连接统计

    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过多:活跃连接。需要看是否与你的业务量匹配。
  2. 查看连接来源

    ss -tnp state established sport = :80  # 查看80端口所有已建立连接的客户端IP和进程
    netstat -anp | grep :80 | grep ESTABLISHED
    • 检查连接是否来自大量不同的IP(可能是攻击或正常用户访问)。
    • 检查是否集中在少数几个IP(可能是某个客户端/爬虫的异常行为)。

第二步:定位关联的进程和应用程序

使用ssnetstat-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  # 查看客户端可用端口范围

如果连接数接近这些限制,系统将无法建立新连接。

可能的解决方案

  1. 应急扩容:临时提升ECS实例的规格(特别是内存),并调高系统级限制

    # 临时修改
    echo 1000000 > /proc/sys/fs/file-max
    ulimit -n 100000

    (永久修改需编辑/etc/sysctl.conf/etc/security/limits.conf

  2. 优化内核参数(针对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 生效
  3. 修复应用程序

    • 如果是CLOSE_WAIT多,必须修复代码中的资源关闭逻辑。
    • 合理配置连接池大小,通常不需要设置得非常大。
    • 实现连接的健康检查和超时关闭机制。
  4. 架构优化

    • 引入负载均衡,将连接分散到多台后端服务器。
    • 对于HTTP服务,考虑使用HTTP/2以减少多个并发连接。
    • 对于静态资源,使用CDN分担连接压力。
    • 在ECS前配置Web应用防火墙(WAF)DDoS高防,抵御连接型攻击。

总结

连接状态 可能原因 危险程度 行动
CLOSE_WAIT 多 应用程序未关闭连接(Bug) 非常高 立即修复应用代码
TIME_WAIT 多 主动关闭连接频繁(短连接多) 中等 优化内核参数、改用长连接
ESTABLISHED 多 业务流量大、连接池过大、攻击 分析来源、优化配置、扩容
SYN_RECV 多 可能遭受SYN Flood攻击 非常高 启用防御、联系云厂商

结论:CPU正常但连接数高,不是一个可以忽略的“正常”状态。它是一个明确的警报,提示你需要立即检查系统的网络连接健康状况、应用程序逻辑和配置,以避免潜在的服务中断。 建议从ss -s命令开始,快速定位连接状态分布,然后按上述步骤深入排查。

云服务器