ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

Linux性能调优实战:监控命令与内核参数调整指南

Linux性能调优实战:监控命令与内核参数调整指南 简介面向Linux运维与服务器管理人员的性能调优总结文档聚焦网络与磁盘两大子系统涵盖内核参数、磁盘挂载、硬件选择等多个层面适用于需要提升服务器吞吐量、降低响应延迟的中级技术人员。包体仅1个docx文件压缩包大小51KB内容精炼易读。文档从内核参数调整切入详细讲解TCP同步Cookie防SYN洪水、TCP窗口缩放、收发缓冲区上限、本地端口范围等网络优化项并给出写入/etc/sysctl.conf后通过sysctl -p生效的具体做法例如可将rmem_max/wmem_max提高到16MB扩大ip_local_port_range至1024-65000以支撑更多并发连接。磁盘部分则针对LAMP架构下磁盘性能对Web服务和数据库的影响介绍禁用atime、修改fstab挂载选项、用hdparm执行基准测试等操作同时探讨ext4、RAID、SSD等文件系统与硬件优化方向。文中包含可直接参考的配置示例与命令并提醒不同系统环境需灵活调整参数。已有214人学习下载适合作为Linux性能调优的速查笔记或生产环境调参前的参考手册。1. LINUX 性能调优不是玄学先把瓶颈定性再动手服务器响应慢、接口超时、数据库连接堆积很多人第一反应是加配置、升 CPU结果钱花了问题还在。干这行久了你会发现LINUX 性能调优方法说穿了就一条主线先判断瓶颈在 CPU、内存、磁盘还是网络再针对那一类资源做参数调整最后用压测数据说话。它更像排查而不是堆参数很多所谓的优化反而是负优化。这篇笔记适合刚接手服务器 linux 的运维、做嵌入式 Linux 和云上业务的开发我把监控命令、内核参数、IO 选型和持久化方案一条条讲清楚每个命令都能直接复制去跑也会把容易翻车的操作单独拎出来说。调优最忌讳的就是看到一篇教程照着 sysctl 一顿改改完也不知道有没有用。2. 先定住瓶颈再动手top、vmstat、iostat 的实战读法调优的第一步永远是监控而且是连续采样不是看一眼 top 就下结论。很多 linux 常用命令大全里都有 top、vmstat、iostat但很少有人把三个命令的输出串起来读。这一章按 CPU、内存、磁盘三个维度讲清楚每个命令该看哪几列、数值到什么程度算异常。2.1 top 的正确打开方式别只盯着 CPU 那一行接手一台性能异常的服务器我习惯先跑一轮 top -b -n 1 把快照存下来而不是直接进交互模式。交互模式虽然能按 P 按 CPU 排序、按 M 按内存排序但没法留痕脚本里跑更容易对比前后变化。top -b -n 1 | head -20-b 是批处理模式-n 1 表示只采样一轮head -20 取前 20 行。输出里第一件要看的不是 %Cpu 那一行而是 load average 后面三个数。1 分钟、5 分钟、15 分钟的平均负载如果 1 分钟远大于 15 分钟说明负载正在快速上升三个数都高说明问题持续有一阵子了。判断标准是拿负载数和 CPU 逻辑核数比负载超过核数意味着有进程在排队等着被调度。第二件要看 %Cpu 这一行里的 wa 和 st。wa 是 CPU 花在等待 IO 上的时间wa 长期超过 30%基本可以断定磁盘是瓶颈这时候调 CPU 参数没用改 IO 调度器或加盘才对症。st 是虚拟机场景下的 steal time宿主机把 CPU 时间抢走了st 高说明云厂商宿主机超卖调自己虚拟机里的参数也没用得找服务商。这两个列经常被忽略但它们恰恰能说明CPU 明明不高为什么服务还是慢。第三件是看进程状态。top 进程列表里如果有大量 D 状态uninterruptible sleep的进程说明它们在等 IOCPU 占用率再低也白搭。可以配合 ps 再筛一遍ps -eo state,pid,comm | awk $1 ~ /D/ {print}把 D 状态进程的 PID 和命令名打出来看看是不是集中在某个程序上。我踩过的一个坑是看见 load average 到 30 就慌着加 CPU 核数后来发现是 NFS 挂载点抽风所有进程都在等同一个慢 IO加核完全没用。所以调优第一步不是改参数是把现象对应到资源上去。2.2 vmstat 的 r、b、si、so、cs 五列内存和进程状态一起看top 看的是瞬时快照vmstat 适合连续采样观察趋势。命令写成交替执行vmstat 1 5每秒采样一次一共 5 次。重点看五列r 是正在运行和等待 CPU 的进程数长期大于 CPU 核数说明 CPU 不够b 是阻塞在 IO 上的进程数持续非零就要查磁盘si 和 so 是换入换出的内存页数这两个一旦持续非零说明内存吃紧、系统在靠 swap 续命性能会明显劣化cs 是上下文切换次数数值特别大比如每秒几万往往是线程频繁切换可能是锁竞争或者线程池开太大。一个常见误判是只看内存剩余量觉得还剩几个 G 就没事。但 si/so 非零时虽然内存有剩余活跃数据已经被踢到 swap 里每次访问都要先换回来应用层感知就是忽快忽慢。这种场景先别急着调参配合 free -h 看 swap 的 used 值再查是哪个进程占用内存高优先限制 JVM 堆或 MySQL buffer pool比调内核参数有效得多。r 列和 cs 列还能验证 CPU 调优效果。比如你说做了进程优先级调整怎么看有没有用先记录调优前的 r 和 cs 值调完再对比。r 列降了说明排队变少cs 降了说明上下文切换减少这两个比人工感受可靠。vmstat 是 Linux 运维最值得练熟的命令输出稳定、字段含义几十年没大变化。2.3 iostat 与 sar磁盘和网卡的真实负载磁盘问题用 iostat -x 看扩展统计机械盘、SSD 都要看iostat -x 1 3-x 输出详细列1 3 表示每 1 秒采样 3 次。重点看 %util、await、r/s、w/s 和 avgqu-sz。机械硬盘 %util 接近 100% 说明盘基本满了但对 SSD 和 NVMe%util 的算法会失真。我曾在 NVMe 上看到 %util 只有 20%实际上 IO 队列已经堆起来了因为 NVMe 的并发能力让传统忙占比失去意义这时要看 avgqu-sz平均队列长度和 awaitIO 平均等待时间。await 持续大于 30ms 对数据库这类应用算异常如果磁盘本身是高端 SAS 盘还这么高大概率是随机读写太多或固件有问题。网卡负载用 sar 看sar 属于 sysstat 包sar -n DEV 1 5rxkB/s 和 txkB/s 能看出流量趋势如果网卡吞吐长期顶在带宽上限再配合 ip -s link 看丢包和错误计数。我遇到过业务方说网络慢查下来是走了一张千兆网卡流量早就到瓶颈了换万兆直接解决根本不涉及内核参数调整。性能调优的排序永远是先确认硬件资源是不是真到顶再动内核这个顺序反过来就是前面说的加核没用的翻车现场。3. CPU 调优实操nice 值、CFS 参数与 CPU 绑核CPU 调优有个原则能用用户态手段解决就不动内核态参数。生产环境里八成以上的 CPU 问题是资源分配不合理而非内核调度有 bug。这一章从最安全的进程优先级讲起再讲内核参数和绑核越往后风险越高。3.1 先用 renice 给关键进程让路别急着改内核最常见的需求是两个业务抢 CPU。比如数据仓库跑批任务和线上 API 服务在同一台机器希望 API 优先响应。这时第一选择是 nice/renice改进程优先级不需要重启随时能回退。renice -n -5 -p 12345nice 值范围是 -20 到 19默认 0值越小优先级越高。普通用户只能把 nice 调大降低优先级要调成负数得 root而且 nice 只影响 CFS 调度权重不影响实时调度策略的进程。改完用 top 看 NI 列确认别凭感觉。如果跑批任务有几十个进程逐个 renice 太累写个小 linux 脚本配合进程匹配命令for pid in $(pgrep -f data_process.py); do renice -n 10 -p $pid donepgrep -f 按完整命令行匹配把跑批相关进程全部降权。这个方案的好处是不需要重启服务也不影响下次发布属于最好回退的后悔药手段。记住一点renice 调的是单个进程如果进程是线程池模型比如 Java 应用光调主进程没用得调所有线程用 ps -eLf 确认线程列表。这也是 linux 面试题里经常追问的细节JVM 的线程优先级和进程优先级不是一回事。3.2 CFS 与 autogroup改内核调度参数前先想清楚场景内核 CFS完全公平调度器暴露了一些可调参数但绝大多数生产场景不建议动。比如 /proc/sys/kernel/sched_autogroup_enabled这个特性本来是给桌面交互设计的把同一会话的进程分到一组让前台应用响应更快。服务器上它反而会让不同登录会话的进程互相抢 CPU表现成同一台机器一个会话里的任务把另一个会话的任务饿死。多用户服务器上我一般会关掉sysctl -w kernel.sched_autogroup_enabled0sysctl -w 立即写入内核参数重启失效持久化放到第 6 章。另一个值得了解的是 sched_wakeup_granularity控制唤醒进程的抢占粒度延迟敏感场景可以适当调大减少频繁抢占。但别迷信这个参数绝大多数线上服务改了也感知不到差异需要压测数据支撑。给新手的建议是CFS 参数里真正值得碰的就 autogroup 和 sched_wakeup_granularity前者服务器关后者按需微调。每次只改一个参数改完压测对比别把 /proc/sys/kernel/sched_* 当玩具挨个试。改内核调度参数的成本比 renice 高得多因为出问题后现场很难快速复原尤其是多核机器上的抢占行为复现成本很高。3.3 taskset 与 NUMA绑核之前先看拓扑绑核是数据库和高性能网关常用的手段把进程钉在固定 CPU 上减少上下文切换和缓存抖动。命令很简单taskset -c 2,3 ./app-c 2,3 表示允许进程在 CPU 2 和 3 上运行启动时绑定。运行中的进程改绑核用 taskset -cp 2,3 PID。但绑核必须配合 NUMA 拓扑看不然可能适得其反。先执行 numactl --hardware 看机器有几个 NUMA 节点每个节点上有哪些 CPU 和内存。numactl --hardware如果看到 node0 和 node1 各有一半 CPU 和内存说明这是双路或多节点架构。跨节点访问内存比本节点慢一截差距一般是 1.5 到 2 倍延迟。这时候用 taskset 只绑 CPU 不绑内存进程的内存可能被分配到另一个节点访问延迟飙升性能比不绑还差。正确做法是用 numactl 把 CPU 和内存绑在同一个节点numactl --cpunodebind0 --membind0 ./app我在一台 64 核双路服务器上踩过这个坑只 taskset 绑了前 16 个核结果吞吐比不绑还降了 20%加上 --membind 才把性能拉回来。绑核的真实收益场景是进程数量固定、CPU 资源充足、且对延迟敏感的服务比如网络网关、缓存中间件。普通 web 服务并发线程多硬绑核反而浪费空闲核不建议。实时调度策略单独提一句chrt -f -p 90 PID 能把进程设为 SCHED_FIFO 实时优先级。这个手段只在极端低延迟场景用比如工业控制、DPDK 数据面。设置不当会让系统其他进程饿死连 ssh 都进不去属于高风险操作生产环境务必先备份现场再尝试。提示任何 CPU 绑核或实时调度改动先在测试环境或低峰期验证 24 小时再推广别拿生产直接做实验。4. 内存与磁盘 IO 调优swappiness、脏页比例与 IO 调度器选型内存和磁盘 IO 是性能调优里最容易被套路化的部分。一堆人告诉你 swappiness 要设 0、调度器要选 none却不告诉你前提条件是什么。这一章先把参数原理讲明白再给不同场景的取值建议。4.1 swappiness 和 dirty_ratio先理解再设置内存调优里被问最多的是 vm.swappiness。默认值 60表示内核在回收匿名内存页和文件缓存之间的倾向程度值越大越积极换出匿名页。很多人直接改成 0以为是禁用 swap其实是尽可能不换出匿名页不代表永远不会 swap。sysctl -w vm.swappiness10这个值适合大多数服务器 linux 场景保留一点 swap 兜底避免内存突发耗尽时直接 OOM。数据库实例MySQL、PostgreSQL我一般用 0 到 10 之间前提是 buffer pool 已经按物理内存定好上限。一个反直觉的点如果这台机器本来就在大量使用 swap改成 swappiness0 后内存回收压力会转移到文件缓存脏页写回变频繁某些场景反而更慢。内存本身超卖、swap 当第二内存用的机器别盲目改 0。真正影响写吞吐的是脏页比例。vm.dirty_background_ratio 默认 10表示脏页占内存 10% 时内核开始后台写回vm.dirty_ratio 默认 20到 20% 时进程自己会阻塞写。对写密集型的数据库服务器脏页涨得快时后台写回跟不上很容易顶到 dirty_ratio 触发全局阻塞表现成间歇性写停顿。我一般把两个值一起调低sysctl -w vm.dirty_background_ratio5 sysctl -w vm.dirty_ratio15让后台写回提前启动尽量避免顶到阻塞阈值。注意这不是越低越好调低能减少突发停顿但写回频率变高小块写变多调高能攒批写但一旦触发同步写回停顿更久而且意外断电丢数据的窗口变大。带电池的 RAID 卡或企业级 NVMe 盘可以稍微激进普通 SATA 盘保持默认或微调。内存调优的关键是知道这台机器是读多写少还是写多读少参数跟着业务特性走不跟教程走。4.2 IO 调度器选型NVMe、SATA SSD、机械盘各用哪个Linux 系统里每个块设备都有自己的 IO 调度器查看方式cat /sys/block/sda/queue/scheduler cat /sys/block/nvme0n1/queue/scheduler输出里方括号括起来的是当前生效的调度器。主流的内核调度器有 mq-deadline、none、kyber、bfq。我的选择经验NVMe 固态用 none因为盘本身的队列机制和硬件调度已经很成熟内核再插一层调度纯属增加延迟SATA 接口的 SSD 用 mq-deadline兼顾延迟和公平性机械硬盘并发不高用 mq-deadline桌面交互场景想减少卡顿可以试 bfq但服务器上别碰 bfq它的公平性算法会引入额外 CPU 开销。修改调度器直接写 sysfsecho none /sys/block/nvme0n1/queue/scheduler这个操作即时生效不用重启但重启会丢。要持久化常见做法是写 udev 规则放在第 6 章统一说。这里补充一个细节改调度器之前先看盘的硬件队列深度cat /sys/block/nvme0n1/queue/nr_requests 和 hw_queue_depth。如果你的应用 IO 模式是大块顺序读写视频转码、备份脚本调度器的影响很小如果是 4k 随机小 IO数据库、消息队列调度器和队列深度的影响才明显。这也是我坚持用 fio 对比而不是直接照搬某盘该用某调度器的结论。4.3 用 fio 做调优前后基准对比调参数不能靠感觉fio 是 linux 下最常用的 IO 基准工具。至少跑两组随机读和随机写命令参数保持完全一致才能对比。fio -namerandread -ioenginelibaio -direct1 -bs4k -rwrandread \ -size4G -numjobs4 -iodepth32 -runtime60 -group_reporting-name 只是任务名ioenginelibaio 用异步 IO 模拟数据库这类负载direct1 绕过 page cache 直接测磁盘真实性能bs4k 是块大小rwrandread 是随机读。size4G 是每个 job 写多少数据numjobs4 是并发任务数iodepth32 是队列深度runtime60 表示跑 60 秒group_reporting 把 4 个 job 的结果汇总输出。跑完看两行数据IOPS 和 lat avg平均延迟。调优前先跑一轮保存结果改完脏页参数或调度器再跑一轮同一套 fio 命令对比。如果 IOPS 没变、延迟没降说明这次调优对 IO 路径没有实质影响赶紧回滚。调优后感觉流畅了这种主观判断在 fio 数据面前经常站不住脚这是我做性能调优最坚持的一点所有结论都要有前后对比数据背书。提示fio 默认会生成测试文件跑完记得清理别把测试文件留在生产数据盘上占空间。5. 避坑指南Linux 性能调优最常见的 5 个翻车现场前面每章都提了一些注意点这一章集中整理我见过和踩过的坑。每个坑按现象、原因、解决三段写遇到类似问题可以直接对号入座。性能调优最怕的不是没效果而是改完参数制造了新问题下面这几个都属于典型的好心办坏事。5.1 现象swappiness0 后MySQL 反而变慢还频繁 OOM网上很多教程让数据库服务器把 swappiness 改成 0照做之后有的机器出现诡异现象空闲内存还有几个 Gmysqld 却被 OOM killer 杀了或者 SQL 查询延迟忽高忽低。原因swappiness0 只是降低匿名页换出倾向内核回收内存时会优先回收 page cache 中的文件页。MySQL 的 innodb_buffer_pool 占了大头这部分属于匿名内存回收不了太多而 page cache 被大量回收后读 InnoDB 数据文件的磁盘命中率下降查询变慢。一旦内存真的耗尽没有 swap 缓冲OOM killer 直接挑大内存进程下手mysqld 往往是第一个。解决把 swappiness 从 0 调回 10同时给 MySQL 设置 innodb_buffer_pool_size让 buffer pool 匹配物理内存的 60% 到 70%给操作系统和 page cache 留出余地。我习惯在测试机先压测一轮确认不会 OOM 再上生产。这个坑的本质不是参数错了是只改一个参数、忽略配套参数造成的。5.2 现象taskset 绑核后吞吐不升反降罪魁是跨 NUMA 访问前面提到我自己踩过这个坑这里完整展开。双路服务器上把进程绑到 node0 的 CPU内存却被分配到了 node1每次访问内存都走跨节点总线延迟翻倍。原因taskset -c 只约束 CPU 亲和性不约束内存分配策略。内核默认的 NUMA 策略是优先在进程当前 CPU 所在节点分配内存但如果进程启动时没绑核内存已经有了跨节点分布后续绑核不会自动迁移内存。解决先用 numactl --hardware 确认拓扑再用 numactl --cpunodebindN --membindN 同时绑 CPU 和内存节点。验证方法是用 numastat -p PID 看进程的本地内存命中率低于 80% 基本可以断定有跨节点访问。调优前后跑同样的压测对比吞吐和平均延迟绑核本身不是目的降低访问延迟才是。5.3 现象改完 limits.confnginx 还是报 too many open files高并发服务把文件句柄数调大是常规操作但改完 /etc/security/limits.conf 重启 nginx日志里照样报 too many open files。原因limits.conf 只对通过 PAM 登录的会话生效systemd 托管的服务包括大部分发行版用 systemd unit 启动的 nginx不读这个文件。另外 nginx 自己还有 worker_rlimit_nofile 指令即使系统限制调大了nginx 进程自身没调也一样受限。解决两步都要做。systemd 服务在 unit 文件里加 LimitNOFILE65535然后 daemon-reload 并重启服务nginx 配置里加 worker_rlimit_nofile 65535 再 reload。还要确认内核层的 fs.file-max 够大sysctl -w fs.file-max100000 cat /proc/sys/fs/file-nrfile-nr 的第一个数是当前已分配句柄数第二个是峰值第三个是上限。已分配数接近上限才需要调 fs.file-max。查某个进程实际打开的句柄数用 ls /proc/PID/fd | wc -l比看错误日志直观。这个坑我帮人排查过好几次每次都是 systemd 和 limits.conf 割裂导致的。5.4 现象把 NVMe 的调度器改成 none 后延迟没降反升有人听说 NVMe 应该用 none照做之后发现性能更差于是怀疑盘有问题。原因none 调度器不做合并、不做排序直接把请求丢给硬件。对绝大多数现代 NVMe 这确实是最优解但有两个前提内核版本够新5.x 的块层和 NVMe 驱动才成熟以及盘本身固件对高队列深度支持良好。老内核或固件有问题的盘none 反而让软件层的命令合并减少小 IO 变多拖慢整体。解决先看内核版本 uname -r5.x 内核上 NVMe 放心用 none老内核老平台用 mq-deadline 和 none 各跑一轮 fio 再决定。另一个细节改调度器后检查盘的 write cache 是否开启很多时候性能差距来自这里而不是调度器。IO 调优里的标准答案常常有前提条件硬件型号和内核版本就是最大的前提。5.5 现象perf 采样的数据全是 unknown火焰图没法看CPU 性能分析绕不开 perf但非 root 用户跑 perf record 之后perf report 里大量 symbol 显示 unknown火焰图基本是空的。原因内核的 perf_event_paranoid 参数默认值限制非特权用户访问内核态采样信息用户态程序的符号表也拿不全采样结果自然没有函数名。解决临时放开用 sysctl 调低 perf_event_paranoid设为 0 允许非特权用户采样用户态和内核态但仅限本进程设为 -1 完全放开。生产环境不想放开全局权限用 root 跑采样、普通用户看报告sysctl -w kernel.perf_event_paranoid0 perf record -F 99 -g -p PID -- sleep 30 perf report-F 99 是采样频率 99Hz-g 记录调用栈-p 指定目标进程sleep 30 表示采 30 秒。采样时 CPU 有一定额外开销线上高峰期别全核采样。perf 数据如果还是 unknown检查进程是否带 debug symbol用 debuginfo 包补上再看。调优里最怕的就是工具不给数据perf 的权限和符号问题不解决后面的分析全白搭。6. 重启不丢用 tuned 和 sysctl 固化调优参数6.1 tuned 自定义 profile一组参数管一台机器sysctl 和调度器改动重启后会退回默认生产环境不可能每次开机手动敲一遍。tuned 是 Red Hat 系发行版自带的调优守护进程能按 profile 批量应用参数。先看当前状态tuned-adm active tuned-adm list服务器场景通常用 throughput-performance 或 latency-performance但内置参数不一定符合业务更推荐自定义 profile继承一个基础 profile 再覆盖自己的参数mkdir -p /etc/tuned/myprofile tee /etc/tuned/myprofile/tuned.conf EOF [main] includethroughput-performance [sysctl] vm.swappiness10 vm.dirty_background_ratio5 kernel.sched_autogroup_enabled0 [disk] devices_udev_regex.* EOF tuned-adm profile myprofile[main] 段的 include 表示继承父 profile没指定的参数沿用父值避免漏项。切换后用 sysctl vm.swappiness 验证。tuned 不同版本对 [disk] 段的支持略有差异如果调度器没变回到 udev 规则那是最底层的持久化手段。6.2 udev 规则与 sysctl 持久化两条腿走路IO 调度器是设备级属性写 udev 规则最可靠系统启动、设备接入时自动应用tee /etc/udev/rules.d/60-io-scheduler.rules EOF SUBSYSTEMblock, KERNELsd*, ATTR{queue/scheduler}mq-deadline SUBSYSTEMblock, KERNELnvme*, ATTR{queue/scheduler}none EOF udevadm control --reload udevadm triggerreload 让 udev 重读规则trigger 让已有设备重新匹配执行两个都要跑。sysctl 持久化不要往 rc.local 里塞正确位置是 /etc/sysctl.d/ 下的独立文件tee /etc/sysctl.d/99-tuning.conf EOF vm.swappiness10 vm.dirty_background_ratio5 vm.dirty_ratio15 fs.file-max100000 kernel.sched_autogroup_enabled0 EOF sysctl --system文件名 99- 开头靠后加载能覆盖发行版默认。我见过同事写完参数忘记触发加载重启前没生效、重启后突然生效导致服务异常这种延迟生效比不生效更坑。6.3 验收方法三个命令确认调优真正生效每次调完一轮我固定跑三个命令sysctl vm.swappiness vm.dirty_background_ratio fs.file-max tuned-adm active cat /sys/block/nvme0n1/queue/scheduler第一个确认内核参数当前值第二个确认 profile 确实生效而不是报错回退第三个确认调度器。三个都对了再跑一轮压测对比数据并留存档。我习惯把每次调优记录成一段话加一条命令像API 集群swappiness 60 改 10dirty_ratio 15压测 p99 下降 220ms下次直接翻记录不用重新踩一遍。参数是死的经验是攒出来的性能调优最后拼的不是知道多少参数而是知道每个参数在这台机器上会产生什么连锁反应。希望帮到你。本文还有配套的精品资源点击获取
返回列表