努力
加油

CentOS 7.6服务器持续开机数月后变卡是什么原因?

CentOS 7.6 这种“老古董”系统,持续开机几个月后变卡,这其实是 Linux 运维中非常经典的一个现象。别急着重装系统,大多数情况下不是硬件坏了,而是资源管理或软件层面的“慢性中毒”。

我们可以从以下几个最核心的维度来排查和解决:

1. Swap 交换分区与内存压力(最常见原因)

CentOS 7 默认开启 Swappiness(通常值为 60)。当物理内存(RAM)快用完时,内核会频繁地将不常用的内存页置换到磁盘上的 Swap 分区。

  • 现象:服务器负载(Load Average)可能不高,但 I/O Wait(iowait)飙升,CPU 使用率看似正常,但响应极慢。
  • 原因:机械硬盘或低速 SSD 作为 Swap 介质时,随机读写性能极差。如果业务有内存泄漏或者突发流量导致内存耗尽,系统会在 RAM 和 Swap 之间反复颠簸(Thrashing),导致 CPU 大部分时间都在等待磁盘 I/O。
  • 验证方法:
    free -h
    vmstat 1 5
    # 观察 si (swap in) 和 so (swap out) 列是否有大量数据流动
  • 解决方案:
    • 短期:重启服务释放内存。
    • 长期:检查是否有进程内存泄漏(用 top 或 htop 按 M 键排序看谁占内存最多)。适当增加 Swap 大小(虽然治标不治本,但能避免 OOM Kill),或者优化应用代码减少内存占用。
    • 参数调整:可以尝试将 vm.swappiness 调低(如设为 10 或 1),让内核更倾向于保留物理内存,而不是轻易使用 Swap。
      sysctl vm.swappiness=10

2. 文件句柄与进程数限制

Linux 对每个用户和系统总的文件描述符(file descriptors)是有上限的。

  • 现象:新连接无法建立,数据库报错 Too many open files,Nginx/Apache 拒绝服务。
  • 原因:某些 Java 应用、Python 脚本或自定义服务如果没有正确关闭连接或文件句柄,会造成“句柄泄漏”。几个月下来,累积的未关闭句柄可能触发了系统的 fs.file-max 限制。
  • 验证方法:
    cat /proc/sys/fs/file-nr
    ulimit -n
    lsof | wc -l  # 查看当前打开的文件总数
  • 解决方案:
    • 修改 /etc/security/limits.conf,提高 nofile 限制。
    • 检查并修复应用程序中的资源泄露问题。

3. 日志爆炸与磁盘空间碎片化

  • 现象:df -h 显示磁盘空间不足,或者 du -sh /* 发现某个目录(通常是 /var/log)异常巨大。
  • 原因:
    • 日志未轮转:某些应用没有配置 logrotate,导致单个日志文件无限增长,塞满磁盘。
    • 僵尸进程/孤儿进程:虽然不直接占磁盘,但如果伴随大量错误日志输出,会迅速消耗磁盘空间和 I/O 带宽。
    • Inode 耗尽:如果目录下有数百万个小文件(如缓存、会话文件),即使磁盘容量没满,也可能因为 Inode 用完而无法创建新文件。
  • 验证方法:
    df -i  # 检查 Inode 使用情况
    du -sh /var/log/* | sort -hr # 找出最大的日志文件
  • 解决方案:
    • 清理或归档旧日志。
    • 配置 logrotate 自动切割和压缩日志。
    • 如果是 Inode 耗尽,需要删除大量小文件或扩容文件系统(Ext4 支持在线扩容 Inode,但需谨慎操作)。

4. 定时任务(Cron)堆积或冲突

  • 现象:CPU 突然飙高,然后慢慢恢复,周期性出现。
  • 原因:
    • 某个 Cron 任务执行时间过长,覆盖了下一个周期的开始时间,导致多个实例并行运行,资源竞争加剧。
    • 某些备份脚本、监控脚本在深夜集中运行,如果脚本写得不好(比如全表扫描、大文件拷贝),会拖垮整个系统。
  • 验证方法:
    crontab -l
    ls -lt /var/spool/cron/
    # 结合 lastcomm 或 auditd 查看历史命令执行情况
  • 解决方案:
    • 优化 Cron 任务的执行逻辑,添加锁机制(如 flock)防止并发。
    • 将高负载任务错峰执行。

5. 内核参数与网络栈积压

  • 现象:网络连接不稳定,TCP 连接建立缓慢,丢包率高。
  • 原因:
    • TCP TIME_WAIT 过多:高并发短连接场景下,大量连接处于 TIME_WAIT 状态,占用端口和资源。
    • Netfilter/IPTables 规则复杂:如果防火墙规则非常多且复杂,每次数据包都要经过长长的规则链匹配,CPU 开销巨大。
    • 中断平衡(IRQ Balance):多核服务器上,如果网卡中断只集中在一个 CPU 核心上,会导致单核满载而其他核心空闲。
  • 验证方法:
    ss -s  # 查看 TCP 连接状态统计
    iptables -L -n --line-numbers  # 检查规则数量和复杂度
    cat /proc/interrupts | grep eth0  # 查看网卡中断分布
  • 解决方案:
    • 调整 TCP 内核参数(如 tcp_tw_reuse, tcp_fin_timeout)。
    • 精简防火墙规则,或使用 nftables/firewalld 的规则优化。
    • 确保 irqbalance 服务正在运行,使中断均匀分布在各个 CPU 核心上。

6. CentOS 7.6 自身的已知问题

  • 内核版本较老:CentOS 7.6 使用的是 3.10.x 内核,这个内核在处理现代高并发、NUMA 架构、以及某些新型存储驱动时效率不如后续版本(如 4.19+ 或 5.10+)。
  • SELinux 干扰:如果 SELinux 处于 Enforcing 模式,且应用权限设置不当,会导致大量的 AVC 拒绝记录,不仅影响性能,还会产生海量审计日志。
  • 验证方法:
    getenforce
    ausearch -m avc -ts recent  # 查看最近的 SELinux 拒绝记录
  • 解决方案:
    • 如果确认应用兼容,可以将 SELinux 设置为 Permissive 模式测试性能提升。
    • 考虑迁移到 AlmaLinux/Rocky Linux 8/9 或 Ubuntu LTS,获得更新的内核和安全补丁。

总结建议

  1. 第一步:登录服务器,运行 top 和 vmstat 1 5,确定是 CPU、内存还是 I/O 瓶颈。
  2. 第二步:如果是 I/O 瓶颈,重点查 Swap 和日志;如果是 CPU 瓶颈,查 Cron 任务和特定进程。
  3. 第三步:检查 dmesg 和 /var/log/messages,看是否有硬件错误或内核警告。
  4. 长期策略:CentOS 7 已于 2024 年 6 月停止维护(EOL),强烈建议规划迁移至受支持的操作系统。对于生产环境,定期重启(如每月一次)也是一种简单有效的“清理”手段,但这不应成为常态。

记住,Linux 不像 Windows 那样需要频繁重启来“清理”,它的设计哲学是稳定运行数年。如果出现变卡,一定是某个环节出现了资源泄漏或配置不当,找到那个“漏水的桶”比换掉整个水箱更重要。