凌晨服务器CPU使用率飙高,先别急着加配置,九成是”定时任务、日志堆积、恶意爬虫或内存溢出”在作怪,按优先级排查定时任务和慢查询,通常能在十分钟内定位到元凶。
凌晨CPU异常飙高的常见场景与原因
服务器和你一样,白天忙晚上也想歇,如果每天固定凌晨CPU突然拉满,说明有东西在”加班”,而且多半是定时触发的,以下四类场景几乎覆盖了绝大多数情况。
定时任务扎堆启动
多数业务会设置凌晨跑批处理,比如数据汇总、报表生成、日志压缩、缓存预热,如果脚本写得不够精细,或者任务之间没有错峰,多个进程同时抢CPU,负载自然瞬间拉满。
- 检查crontab里是否所有任务都挤在同一分钟
- 检查是否有任务依赖上一个任务,但上一个任务没按时结束
- 检查脚本里是否存在死循环或者全表扫描逻辑
日志写入陷入雪崩
凌晨日志量通常不多,但恰恰是这个”不多”容易让人忽略,某些应用在凌晨做日志轮转或归档,如果目录权限配置不当,程序反复重试写入失败,会陷入疯狂循环,CPU飙到天花板。
恶意爬虫与攻击流量
这年头互联网上扫端口、撞库的脚本从不休息,凌晨正是攻击者爱挑的时段,因为运维盯着少,服务器CPU使用率高怎么解决?先看网络连接数,如果有大量来自同一IP的异常连接,多半是被爬了或打了。
内存溢出与GC连锁反应
Java、Node.js等带垃圾回收机制的应用,如果堆内存设置偏小,凌晨业务量低时反而容易触发Full GC,Full GC是极度吃CPU的操作,表现为瞬时飙高然后降下来,再飙高,很像”打摆子”。
快速定位CPU元凶的五步排查法
不要一上来就重启,也不要急着扩机器,按下面步骤操作,每一步都能产出可验证的结果。
第一步:确认是”持续高”还是”脉冲高”
先用top或htop观察五分钟,如果CPU持续在90%以上,说明有进程死循环;如果每隔几秒冲高再回落,大概率是GC或短期任务并发,这个区别直接决定后续排查方向。
第二步:按CPU占用排序找进程
执行top -o %CPU,记录排前三的进程PID,再用ps -fp PID看这个进程的启动命令和所属用户,常见情况是某个Java进程或PHP-FPM进程异常。
第三步:进进程内部找线程
找到进程后,用top -H -p PID看具体线程,记下CPU最高的线程ID,转成十六进制后执行jstack PID | grep -A 20 "nid=0x..."(Java应用)或gdb(C/C++应用),能看到当前在执行的代码位置,这一步能直接定位到是哪段代码在忙。
第四步:查数据库慢查询
凌晨CPU高通常伴随数据库压力大,登录MySQL执行SHOW FULL PROCESSLIST,看是否有大量SELECT处于Sending data状态,确认后打开慢查询日志:
mysqldumpslow -s c -t 10 /var/log/mysql/slow-query.log
把排前十的语句拿出来分析,业务侧最怕的全表扫描,在凌晨常因为统计任务触发。
第五步:查系统日志和网络连接
用dmesg -T | tail -50看有没有OOM、磁盘I/O错误,用netstat -an | awk '{print $5}' | cut -d: -f1 | sort | uniq -c | sort -rn统计外部IP连接数,如果某个IP的连接数奇高,再配合lsof -i看是什么进程被频繁访问。
常规优化方案:把凌晨的”热闹”错开
定位到原因之后,下面这些手段都是行业验证过的高性价比做法,不需要大改架构。
定时任务错峰与锁机制
- 在crontab里给不同任务设置不同分钟或小时,比如报表1点跑、同步2点跑
- 使用
flock命令给任务文件加锁,防止重复启动/5 flock -xn /tmp/backup.lock -c "bash /data/backup.sh" - 如果多台服务器共用同一个数据库,用分布式锁保证同一时间只有一台机器跑任务
业务侧优化
- 在任务脚本开头加一个”资源占用检查”,当CPU负载超过阈值时让脚本自己等几分钟再重试
- 把大数据量查询拆成分页或者按日期切片,避免一次性加载全量数据
- 对频繁访问的报表结果增加Redis缓存,设置凌晨五点自动失效重建
数据库侧调优
- 为慢查询里的WHERE字段补索引,这一步收益极大
- 把凌晨任务访问的表改用
REPLICA库,不影响主库业务 - 检查InnoDB缓冲池大小,如果服务器内存有富余,适当调大
innodb_buffer_pool_size
防患于未然:让凌晨CPU高这件事不再发生
排查和优化是治标,建立上报与自愈机制才是治本,凌晨服务器cpu使用率高怎么办,多数时候应该让系统自己说话。
配置监控与告警
- 使用Zabbix、Prometheus或云厂商监控,设置CPU使用率阈值告警
- 告警通道接钉钉或企业微信,别只发邮件,凌晨没人看邮件
- 针对”凌晨”单独设一个更敏感的阈值,比如白天80%才告警,凌晨60%就告警
写个自动缓解脚本
业内专家指出,在可控风险下,让机器自己先动手比等人工快,写一个守护脚本放在cron里,每两分钟检测一次:
#!/bin/bash
LOAD=$(uptime | awk -F'load average:' '{print $2}' | cut -d. -f1)
if [ $LOAD -gt 8 ]; then
systemctl restart heavy-task.service
echo "$(date) restarted" >> /var/log/auto-mitigation.log
fi
这里只给个思路,实际请按业务重动作设计保护机制,别把所有服务一锅端重启。
流量清洗与访问控制
- 在Nginx层对可疑IP做并发连接数限制
- 使用防火墙工具封禁短时间内连接数超阈值的IP,基础命令如下:
iptables -A INPUT -s 1.2.3.4 -j DROP - 如果业务对公网开放,接入云WAF或CDN能过滤掉大量恶意请求
什么时候该考虑升级配置
如果以上操作都做完了,CPU还是长期处于高位,才需要认真考虑资源扩容,但先回答一个问题:你的业务是真需要,还是代码写得差?
自查清单
- CPU核数是否常年跑满,还是只在凌晨跑满
- 单机负载是否超过
核数 2,如果没有,先优化代码 - 内存是不是先满了,CPU只是背锅
合理扩容路径
- 优先加内存,很多所谓CPU问题实际是内存不足导致频繁交换
- 其次升CPU主频,对单线程任务收益明显
- 最后才加核数,多核只对并行任务有效,对单线程任务加了也没用
凌晨服务器CPU使用率高是什么原因?常见疑问与解答
问:为什么我重启服务器后CPU降下来了,但第二天凌晨又高?
因为重启只是让进程从头开始,如果定时任务或脚本逻辑没改,它到点照样跑,重点去查crontab和队列消费者,这两个是主要复发源。
问:凌晨CPU高但业务量明明很低,正常吗?
不算异常,常见于后台批处理、数据备份、日志归档,只要不影响白天业务,且能在预设时间内跑完,可以接受,如果连备份都能把CPU跑满,说明脚本写得需要优化。
问:有没有快速区分是业务代码还是外部攻击的方法?
有,先打断点看进程状态:如果CPU高的是应用进程,多半是代码问题;如果是网络服务进程且连接数高,多半是攻击,再用strace -cp PID看系统调用,攻击场景下accept和read调用会异常密集。
凌晨CPU高不可怕,怕的是没有系统化排查思路,记住一个核心结论:先看定时任务,再看慢查询,然后查连接数,最后看GC日志,按这个顺序走,多数问题都能在半小时内解决。 把排查步骤固化成文档并配上监控告警,你的服务器就能安安静静度过每个凌晨了。
首发原创文章,作者:王坚,如若转载,请注明出处:https://idctop.com/article/696617.html





