CentOS服务器在高负载场景下,资源调优和计划任务优化是两个直接影响系统稳定性和业务连续性的核心环节。简单来说,资源调优就是让CPU、内存、磁盘I/O、网络这些硬件能力被充分且合理地利用,而计划任务优化则是让定时执行的脚本和命令不会在错误的时间抢占资源、不会重复执行、不会因为失败而无人知晓。下面我把这两块内容拆开,从内核参数、文件描述符、内存管理到crontab调度策略,全部给你讲透。

一、系统资源调优的核心思路

CentOS 7和CentOS 8在资源管理上有差异,但底层逻辑一致:先诊断瓶颈,再针对性调整。你可以用top、vmstat、iostat、free -m这几个命令快速定位问题。top看CPU和内存占用排序,vmstat看系统整体吞吐量和swap使用情况,iostat看磁盘读写等待,free -m看内存详细分布。找到瓶颈之后,才是调优的开始。

二、内核参数调优(sysctl.conf)

Linux内核有大量可调参数,集中在/etc/sysctl.conf文件中。对于高并发Web服务或者数据库服务器,以下几个参数必须调整。首先是网络连接相关的参数,默认的连接数限制太低,容易出现"Too many open files"或者连接被拒绝的问题。

# 网络连接优化
net.core.somaxconn = 65535
net.core.netdev_max_backlog = 65535
net.ipv4.tcp_max_syn_backlog = 65535
net.ipv4.tcp_tw_reuse = 1
net.ipv4.tcp_fin_timeout = 15
net.ipv4.tcp_keepalive_time = 600
net.ipv4.tcp_keepalive_probes = 5
net.ipv4.tcp_keepalive_intvl = 15

# 本地端口范围
net.ipv4.ip_local_port_range = 1024 65535

# 内存相关
vm.swappiness = 10
vm.dirty_ratio = 15
vm.dirty_background_ratio = 5
vm.overcommit_memory = 1

net.core.somaxconn控制的是listen队列的最大长度,默认128,生产环境至少设到1024以上。net.ipv4.tcp_tw_reuse设为1允许将TIME_WAIT状态的socket重新用于新连接,这对高并发短连接场景非常关键。vm.swappiness设为10意味着系统尽量少用swap,把内存留给应用程序,而不是频繁换页。这些参数修改后用sysctl -p立即生效,不需要重启。

三、文件描述符和用户限制调优

CentOS默认每个进程最多打开1024个文件描述符,这对于跑数据库、跑大量并发连接的服务远远不够。需要同时改两个地方:一个是/etc/security/limits.conf,另一个是systemd服务的LimitNOFILE。

# /etc/security/limits.conf
* soft nofile 65535
* hard nofile 65535
* soft nproc 65535
* hard nproc 65535
root soft nofile 65535
root hard nofile 65535

改完limits.conf之后,如果你的服务是用systemd管理的,还需要在对应的unit文件里加一行。比如你要调优nginx服务:

# /etc/systemd/system/nginx.service.d/limits.conf
[Service]
LimitNOFILE=65535

然后执行systemctl daemon-reload和systemctl restart nginx。注意,limits.conf的修改需要用户重新登录才对新会话生效,所以如果你是通过SSH操作的,需要断开重连或者用su -切换用户。

四、磁盘I/O和文件系统调优

磁盘I/O是很多CentOS服务器的隐形瓶颈。如果你的服务器用的是机械硬盘,I/O等待高是常态;如果是SSD,也需要合理配置。首先,文件系统挂载参数很重要。ext4文件系统建议加上noatime和nodiratime,减少不必要的元数据写入。

# /etc/fstab 示例
/dev/sda1 /data ext4 defaults,noatime,nodiratime,discard 0 2

noatime意味着每次读取文件时不更新访问时间戳,这对数据库和日志服务器来说能明显降低写操作。discard参数对SSD有用,告诉系统可以做TRIM操作。另外,如果你的业务是大量小文件随机读写,可以考虑把/tmp挂载为tmpfs,利用内存做临时存储,避免磁盘压力。

# /etc/fstab
tmpfs /tmp tmpfs defaults,size=2G 0 0

还有一个容易被忽略的点:磁盘调度算法。对于SSD,把调度算法改成deadline或者noop,不要用默认的cfq。可以通过grub修改内核启动参数,或者用echo命令临时切换。

# 查看当前调度算法
cat /sys/block/sda/queue/scheduler

# 临时切换为noop(适合SSD)
echo noop > /sys/block/sda/queue/scheduler
五、内存管理深度优化

CentOS的内存管理策略默认偏向保守,对于跑Java应用、MySQL、Redis这类吃内存的服务,需要更激进的策略。除了前面提到的vm.swappiness=10之外,还有几个关键点。第一是透明大页(THP),默认开启,但在某些数据库场景下反而会造成性能抖动,建议关闭。

# 关闭透明大页
echo never > /sys/kernel/mm/transparent_hugepage/enabled
echo never > /sys/kernel/mm/transparent_hugepage/defrag

# 永久生效,写入rc.local或创建systemd服务

第二是调整vm.min_free_kbytes,这个参数控制内核保留多少内存不被分配。默认是64MB,对于大内存服务器可以适当调高,比如设为256MB或者512MB,防止内存耗尽时系统完全卡死。

vm.min_free_kbytes = 262144

第三是OOM Killer的策略调整。当内存真的不够用时,Linux会杀掉进程。你可以通过调整/proc/PID/oom_score_adj来保护关键进程,让OOM Killer优先杀掉不重要的进程而不是你的数据库。

六、计划任务(Crontab)优化策略

CentOS的计划任务主要靠crond服务管理,配置文件在/etc/crontab和/var/spool/cron/目录下。很多运维踩的坑是:任务堆积、重复执行、执行时间不合理、出错没人知道。下面逐一解决。

首先是执行时间的规划。绝对不要把所有重任务都放在整点执行,比如0 2 * * *这种写法。凌晨2点可能有备份、有日志清理、有数据同步,全部堆在一起,CPU和I/O直接打满。正确的做法是错峰调度,把任务分散到不同的时间点。

# 错误示范:所有任务集中在凌晨2点
0 2 * * * /opt/scripts/full_backup.sh
0 2 * * * /opt/scripts/log_cleanup.sh
0 2 * * * /opt/scripts/data_sync.sh

# 正确示范:错峰执行
0 2 * * * /opt/scripts/full_backup.sh
30 3 * * * /opt/scripts/data_sync.sh
0 4 * * * /opt/scripts/log_cleanup.sh

其次是防止任务重复执行。有时候脚本执行时间过长,超过了下一次调度间隔,就会出现多个实例同时跑的情况。解决办法是在脚本开头加锁机制。

#!/bin/bash
# 使用flock防止重复执行
exec 200>/var/lock/myscript.lock
flock -n 200 || exit 1

# 你的业务逻辑放在下面
/opt/scripts/actual_task.sh

flock命令会尝试获取文件锁,如果锁已经被占用,说明上一次还没跑完,直接退出,避免资源争抢。这个方法比写PID文件判断更可靠。

第三是任务失败的监控和告警。默认情况下,crontab任务执行出错只会把错误信息发邮件给执行用户,但大多数服务器根本没配邮件服务,出错了你根本不知道。建议在每条任务后面加上日志重定向,并且配合简单的监控脚本。

# 每条任务记录执行结果
0 2 * * * /opt/scripts/backup.sh >> /var/log/cron_backup.log 2>&1
30 3 * * * /opt/scripts/sync.sh >> /var/log/cron_sync.log 2>&1

你还可以写一个简单的监控脚本,每天早上检查前一天的cron日志,如果有ERROR关键字就发通知。

#!/bin/bash
# /opt/scripts/cron_monitor.sh
LOG_DIR="/var/log"
ERROR_LOG=""

for log in $LOG_DIR/cron_*.log; do
    if grep -q "ERROR\|FAILED\|failed" "$log" 2>/dev/null; then
        ERROR_LOG="$ERROR_LOG\n$(basename $log): $(grep 'ERROR' $log | tail -1)"
    fi
done

if [ -n "$ERROR_LOG" ]; then
    echo -e "Cron任务执行异常:$ERROR_LOG" | mail -s "Cron Alert" admin@example.com
fi

把这个监控脚本也放进crontab,每天早上8点跑一次,这样任何计划任务出问题你都能第一时间知道。

七、Crontab权限和安全加固

很多人忽略了crontab的权限管理。/etc/cron.allow和/etc/cron.deny这两个文件控制谁能用crontab。建议只允许root和特定运维账号使用,其他用户全部禁止。另外,crontab文件本身不要给其他用户写权限,防止被篡改植入恶意任务。

# 只允许root和deploy用户使用crontab
echo "root" > /etc/cron.allow
echo "deploy" >> /etc/cron.allow
chmod 600 /etc/cron.allow

还有一个安全细节:不要在crontab里直接写密码。如果脚本需要认证信息,用环境变量或者专门的配置文件,并且设置好文件权限为600。

八、总结与实操建议

CentOS资源调优和计划任务优化不是一次性的工作,而是持续的过程。我的建议是:先用监控工具(比如Zabbix、Prometheus+Grafana)跑一周,拿到真实的资源使用数据,再动手调参数。不要凭感觉改内核参数,每个参数都有它的适用场景。计划任务方面,核心原则就是错峰、防重、可监控。把这三点做到位,你的CentOS服务器在高负载下也能稳如磐石。调优完成后记得做压力测试,用stress、sysbench这些工具验证效果,别调完就不管了。