接手过不少“莫名其妙卡得要死”的CentOS 7服务器,第一反应基本都是加内存、换硬盘、重启大法三连。但做多了就会发现,很多问题不是硬件不够,而是系统装好之后一直用默认配置在硬扛。CentOS 7虽然已经进入生命周期尾声,可大量存量服务器、内网环境和虚拟机里它依然是主力系统,系统优化与性能调优这套基本功,短期之内不会过时。
这篇文章是我这些年折腾CentOS 7的实战笔记,主要覆盖从虚拟机安装、yum源替换、内核参数、文件系统、服务裁剪到MySQL这类典型应用调优的完整链路。不管是刚接触Linux的新手,还是想把手头服务器性能再压榨一轮的运维老手,里面提到的思路和命令都能直接用,尤其适合那些“不敢乱动生产环境,但虚拟机可以先练练手”的人。
1. 安装层面的优化,先把底子打对
很多人觉得性能调优是从系统装完以后才开始的,其实安装阶段就已经决定了后面一大半的上限。选错镜像、分区不合理、多余组件装了一堆,后面再怎么调都别扭。
1.1 VirtualBox 上创建 CentOS 7 虚拟机:镜像、分区与初始配置
最近折腾测试环境,我习惯用 VirtualBox 配合 CentOS 7 x86_64 minimal 2009.iso 这个镜像。2009 是 7.x 的最终版本号,minimal 镜像只有几百 MB,装出来就是一个干干净净的最小系统,没有图形界面、没有一堆用不上的办公软件。很多人装系统喜欢装 DVD 版,图省事,结果光系统自带的乱七八糟服务就吃掉几百 MB 内存,这对性能调优来说是从起点就输了。
创建虚拟机的时候,几个关键参数我是这么给的:
- 内存:建议至少 2GB。低于这个值,后面跑 MySQL 或者编译软件时会频繁触发 swap,负载看着不高但卡成 PPT。
- CPU:按宿主机核心数分配,但不要超过物理核心数的一半,否则虚拟机调度开销反而拖累性能。
- 磁盘:动态分配即可,但建议预留 40GB 以上,别只给 20GB,因为 yum 缓存、日志、数据库文件这些东西涨起来比你想象的快得多。
- 网络:默认 NAT 可以,如果要模拟生产环境,建议加一张桥接网卡。
分区这一步是重点。生产环境我强烈建议用 LVM,后面扩容就不用重新分区了,这是我在生产上踩过几次坑之后养成的习惯。最小化安装时手动分区,推荐这样规划:
- /boot 分区:512MB 到 1GB,放内核和引导文件,不需要大。
- swap 分区:内存 2GB 以下的机器给内存的 1.5 到 2 倍;内存 8GB 以上反而不用给太多,给 4GB 到 8GB 足够,swap 太大容易让人忽略内存不足的问题。
- 剩余空间全部给根分区(/),用 LVM 创建。
还有个小细节:安装时选择最小化安装,但建议在“软件选择”里勾选“开发工具”。很多人漏了这一步,后面想装编译工具或者虚拟机增强功能的时候发现 gcc、make 全都没有,还得重新挂载光盘折腾 yum,非常麻烦。
1.2 aarch64 架构 CentOS 7 更换 yum 源的完整方法
很多人在 ARM 机器上装 CentOS 7 之后第一件事就被 yum 源卡住了,因为默认官方源要么慢要么已经停止维护。网上搜“arrch64 centos 7 更换yum源”,实际应该是 aarch64 架构,也就是 ARM 64 位,跟 x86_64 的源路径不一样,不能直接用 x86 的源。
以清华源为例,aarch64 的 CentOS 7 要使用的是 altarch 路径,操作步骤先备份原配置,再写入新源:
cp -a /etc/yum.repos.d/CentOS-Base.repo /etc/yum.repos.d/CentOS-Base.repo.bak然后编辑 /etc/yum.repos.d/CentOS-Base.repo,把 baseurl、gpgkey 都指到 aarch64 对应路径下。关键就是安装架构字段不能写错,x86_64 对应的是 /centos/7/x86_64/,而 aarch64 对应的是 /centos-altarch/7/aarch64/。写完之后清理缓存验证:
yum clean all yum makecacheaarch64 架构下,epel 源也要用 altarch 路径,不能安装 x86 版的 epel-release。这一点容易忽略,但不管你是 x86 还是 ARM,装完系统第一件事先把源换掉,后面装软件的速度会提升非常明显。实测下来,从官方源换成国内镜像源,单纯 yum 更新这一步的时间能从半小时缩短到几分钟,这也是最立竿见影的基础优化。
2. 内核参数与系统层调优
系统装好之后,先别急着装业务软件,内核参数才是性能调优的主战场。CentOS 7 默认内核参数照顾的是通用场景,对高并发、高磁盘 IO 或高连接数的业务来说,默认值往往太保守。但内核参数也不能乱改,改错一个,轻则服务异常,重则直接宕机。
2.1 真正值得改的几个内核参数及原因
我调内核参数最常用的配置文件是 /etc/sysctl.conf,改完执行sysctl -p生效。下面这几个参数是经过生产环境验证的,也是调优收益最高的。
首先是文件句柄,也就是 fs.file-max。默认值经常只有几十万,但高并发业务下文件句柄很快会被耗尽,表现就是日志里报 “Too many open files”。我一般会调高,但要结合机器内存来定:
fs.file-max = 6553560然后是网络连接相关的几个参数。net.core.somaxconn默认 128,对于接入层或者代理服务器来说太低,排队连接会被丢弃。我通常调到 65535。net.ipv4.tcp_max_syn_backlog是 SYN 队列长度,并发高的时候建议也调大。
net.ipv4.ip_local_port_range控制本地可用端口范围,默认 32768 到 60999,短连接多的服务很容易把端口用光。可以扩大到 1024 到 65000。
有个参数我要特别提醒:net.ipv4.tcp_tw_recycle一定不要开启。CentOS 7 基于 3.10 内核,这个参数在 NAT 环境下会造成丢包,很多用户反馈“网页一会儿能开一会儿打不开”,排查下来就是有人开了这个参数。在 CentOS 7 里sysctl -p不会报错,但实际坑了不少人。TIME_WAIT 连接多的话,优先用net.ipv4.tcp_tw_reuse=1,这个安全得多。
内存层面的参数,最常见的是 vm.swappiness,默认 30,代表系统在内存还有 70% 空闲时就可能开始换页。对数据库服务器来说,我一般调到 10 左右,让内存尽量留给业务;但对内存本来就吃紧的机器,强行调到 0 反而容易触发 OOM。
提示:调内核参数之前,先
sysctl -a > /tmp/sysctl_before.txt保存一份原始配置,方便出问题时回滚。
2.2 文件系统挂载与磁盘 IO 调度器调整
磁盘性能是整个系统优化里最容易被人忽略的一环。很多人看性能只盯着 CPU 和内存,其实很多“假 CPU 高”都是磁盘 IO 卡出来的。
先看当前磁盘用的 IO 调度器:
cat /sys/block/sda/queue/schedulerCentOS 7 默认一般是 deadline 或者 cfq。根据磁盘类型有不同的选择:
- 机械硬盘:建议用 deadline,它能减少单个请求的延迟,对数据库这种随机读写多的场景更友好。
- SSD 或 NVMe:建议用 none(也就是 noop),因为 SSD 内部已经做了大量调度优化,内核再排队反而是多余的。
- 虚拟机里的虚拟磁盘:大多数场景建议 none 或 noop,特别是 VirtualBox 和 VMware 这类虚拟化磁盘,物理磁盘调度已经由宿主机处理了。
修改调度器可以用 udev 规则或者直接改 /sys 下的文件,但后者重启就失效。我一般用 grub2 的内核引导参数来持久化:编辑 /etc/default/grub,在 GRUB_CMDLINE_LINUX 中加上elevator=none(或elevator=deadline),然后重新生成引导配置:
grub2-mkconfig -o /boot/grub2/grub.cfg这里要注意,如果是 UEFI 启动的机器,输出路径要改成 /boot/efi/EFI/centos/grub.cfg。改错路径会导致重启后配置没生效,这是个很隐蔽的坑。
挂载参数方面,我强烈建议给数据分区加上 noatime。Linux 默认每次读取文件都会更新 atime 时间戳,这会产生额外的写 IO。在 /etc/fstab 的挂载选项里加上 noatime,可以显著减少无意义的磁盘写入。
2.3 服务裁剪:用最少的进程干最多的活
装完系统默认会启动一大堆服务,但大部分场景下它们只是单纯占内存和 CPU。查看开机自启的服务:
systemctl list-unit-files --type=service --state=enabledCentOS 7 里我通常会关掉这些:postfix(邮件服务,内网机器基本用不上)、abrtd 和 abrt-journal-core(崩溃报告工具,占了内存还经常误报)、kdump 服务(如果不是做内核调试可以关掉,但它會预留一块内存,关之前要慎重)。还有 avahi-daemon,这是个局域网设备发现服务,数据中心环境里没必要开。
裁剪服务前先确认依赖关系再动手。比如直接systemctl disable postfix没问题,但如果你跑的是邮件相关应用,关了就会出大事。我的原则是:先systemctl status看谁在跑、跑的是什么,确认无害再关,而不是一上来就批量 disable。
另外,CentOS 7 自带 tuned 调优服务,它可以根据系统类型套用不同的优化方案。运行tuned-adm recommend查看推荐方案,比如数据库服务器推荐 throughput-performance 或 latency-performance。如果不想手动调内核参数,可以用 tuned 做基础调优,但要注意它可能会覆盖你在 /etc/sysctl.conf 里手动设置的参数。我之前就吃过这个亏,手动配的参数重启后全部失效,最后发现是 tuned 在启动时把我的配置覆盖了。如果你要手动调内核参数,记得systemctl disable tuned。
3. 应用层瓶颈与 MySQL 性能调优
系统层优化做完之后,你会看到服务器负载明显下降,但这只是把基础路面修好了。真正让业务卡顿的,往往是应用层的配置问题。MySQL 是最典型的场景,网上关于 mysql 性能调优的内容很多,但大多数都停留在“抄参数”层面,实际效果因人而异。
3.1 MySQL 性能调优的正确顺序
很多人一上来就改 innodb_buffer_pool_size,以为内存给得越大越好。其实 MySQL 性能调优的正确顺序应该是:先看慢查询日志和当前状态,再定位瓶颈,最后才改参数。
开启慢查询日志,先找出那些拖后腿的 SQL:
SET GLOBAL slow_query_log = ON; SET GLOBAL long_query_time = 1;慢查询日志一旦打开,通常能发现两类问题:一种是没走索引的全表扫描,这种是 SQL 本身的问题,改参数没用,得优化查询或加索引;另一种是数据库本身资源不足,高并发下连接数被打满,表现就是大量查询排队等锁。
确认是资源问题之后,再调整关键参数。以 CentOS 7 上常见的 MySQL 5.7 为例,这几个参数是收益最明显的:
- innodb_buffer_pool_size:InnoDB 的缓冲池,建议设置为物理内存的 50% 到 70%。比如 8GB 内存的机器,设成 5GB 左右。注意不是随便填,设置前要看监控里 InnoDB 的缓存命中率,如果命中率不到 95%,说明缓冲池太小。
- innodb_flush_log_at_trx_commit:默认是 1,意味着每次事务提交都要刷盘,安全性最高但磁盘 IO 压力大。对可容忍秒级数据丢失的场景,可以改成 2,性能提升非常显著。
- max_connections:默认 151,很多业务跑着跑着就报 “Too many connections”。但也不要盲目调到 10000,每个连接都要占用线程栈内存,数值过大反而适得其反。我一般根据当前连接数的峰值再加 50% 余量。
- table_open_cache:如果表数量多,打开表的缓存默认值容易不够,日志里会出现 “Table open cache is full”。建议根据
SHOW GLOBAL STATUS LIKE 'Open_tables'的实际值来调整。
还有一个参数很多人忽略:innodb_log_file_size。redo log 太小会导致刷盘频繁,写性能上不去。5.7 里面这个参数在配置文件里设置后需要重启并清理 redo log 文件,改动有风险,要先做好备份再操作。
3.2 监控工具组合:先定位再动手
调优之前没有数据支撑,等于闭着眼睛开车。我常用的组合方案是 top、iostat、vmstat 三个命令交叉验证。
- top 看整体负载和进程状态:如果 CPU 使用率很高但 IO 等待 wa 也很高,那瓶颈很可能在磁盘,加 CPU 是没用的。
- iostat -x 1 看磁盘利用率:重点看 %util、await、svctm。%util 接近 100% 但 await 不高,说明磁盘吞吐到了上限;await 很高但 %util 只有二三十,说明可能有随机 IO 或锁等待。
- vmstat 1 看内存换页和上下文切换:si/so 长期不为 0,说明内存不足,在频繁换页。cs 列数值特别大,说明系统在疯狂切换上下文,可能是线程数设置不合理。
CentOS 7 上 sysstat 包里的 sar 也是长期监控的好帮手。我一般会配置 cron 定期采集 sar 数据,出问题的时候回看历史曲线,比事后拍脑袋猜原因靠谱得多。
4. 常见问题与真实排错记录
系统优化和性能调优这两个词听起来很玄,但落地过程中遇到的问题往往很具体。我挑三个出现频率最高的问题,把排查过程写清楚,也算给后来人排雷。
4.1 系统优化配置不生效到底怎么排查
很多人遇到“未开启系统优化”的问题,其实不是没做优化,而是做了配置之后没有生效。我见过最多的几种情况:
第一种是改了 /etc/sysctl.conf 但没执行sysctl -p,或者执行了但报错没注意。这种情况最简单地解决:改完立即sysctl -p,然后sysctl -a | grep 参数名验证。
第二种是被 tuned 或其他工具覆盖了。tuned 服务如果开着,启动时会读取自己的方案重新应用内核参数,手动改的配置在重启后会被重置。解决方法是systemctl disable tuned,或者把参数同时写进 tuned 的配置里。
第三种是文件句柄限制的问题,这个特别隐蔽。你改了 fs.file-max,但你的应用和进程的实际句柄限制,还受 /etc/security/limits.conf 以及 systemd 服务单元里的 LimitNOFILE 控制。CentOS 7 上 systemd 管理的服务,直接在 /etc/security/limits.conf 改可能不生效,要在服务单元文件里加:
[Service] LimitNOFILE=65535我之前帮人排查过一个 Nginx 报 “too many open files” 的案例,sysctl 配了、limits.conf 也改了,就是不生效,最后发现是 nginx.service 单元文件里默认 LimitNOFILE 只有 1024,加上了才真正解决。
4.2 虚拟机里 VMware Tools 和 VirtualBox 增强工具安装的坑
在虚拟机里跑 CentOS 7,很多人遇到分辨率调不了、剪贴板不共享、网卡性能差的问题,这时候就要装虚拟机增强工具。CentOS 7 里 VMware Tools 安装不算复杂,但有几个坑非常典型。
先在 VMware 的虚拟机菜单里点击“安装 VMware Tools”,然后挂载光驱:
mkdir /mnt/cdrom mount /dev/cdrom /mnt/cdrom tar zxf /mnt/cdrom/VMwareTools-*.tar.gz -C /tmp cd /tmp/vmware-tools-distrib ./vmware-install.pl -d最大的坑是安装前没有装 kernel-devel 和 gcc,导致 VMware Tools 编译内核模块失败。CentOS 7 内核升级过之后,kernel-devel 版本必须和当前内核版本严格一致,先确认:
uname -r yum install -y kernel-devel-$(uname -r) gccVirtualBox 上类似,安装增强工具要用 VBoxGuestAdditions,运行 VBoxLinuxAdditions.run 之前同样需要先装好 kernel-devel 和 build 工具链。另外,增强工具装完之后建议重启一次,不然新模块不会完全加载。很多人装完没重启,发现剪贴板还是不能用,以为安装失败,其实重启就好。
4.3 我见过的三种最坑的调优方式
这些年看别人调优,也接手过不少被"优化"搞坏的服务器,发现三个反复出现的坑。
第一个是照抄互联网上的所谓“万能优化脚本”。从网上复制了一段 sysctl 参数,里面把vm.swappiness=0、net.ipv4.tcp_tw_recycle=1全给配上了,结果在高并发 NAT 环境下出现随机丢包,排查一整天。内核参数必须根据业务场景来配,没有放之四海而皆准的“万能参数”。
第二个是只调数据库不调系统。MySQL 把 max_connections 调到 2000,但系统 open files 限制还是 1024,连接一多照样报错。做 MySQL 调优之前,先确认系统层文件句柄、swap、TCP 连接参数都配合到位,否则永远差一口气。
第三个是改完不做验证。生产环境改了 innodb_buffer_pool_size,确认没问题,但没做压测,过两天业务高峰期直接内存不足,OOM 把数据库进程杀了。任何参数改动之后,至少要观察一个业务周期,并且准备好回滚方案。这是责任心问题,不是技术问题。
我个人做系统优化的习惯是,每个改动之前先把原值记下来,严格按“监控、分析、小步调整、验证、回滚预案”这套流程走。系统优化拼的不是谁参数堆得猛,而是谁能在一个又一个不起眼的小配置里,提前把未来可能出现的坑填掉。最后再分享一个小技巧:调优告一段落后,把所有改动项整理成一份清单,保存到 /root/optimization_notes.txt。下次系统重启或者迁移环境,这份清单就是你最有价值的参考,比任何网上抄的优化教程都可靠。