Linux系统性能调优实战:从监控到优化的全链路指南 1. 项目概述为什么系统调优不是玄学每次看到服务器负载飙红、应用响应慢如蜗牛或者新上的业务总觉得哪里“不得劲”时很多运维和开发朋友的第一反应可能就是“加配置”——加内存、升CPU、换SSD。这当然有效但成本也高。其实在硬件资源不变的情况下通过系统层面的精细调整往往能释放出惊人的性能潜力这就是Linux系统调优的价值所在。它绝不是网上流传的几条神秘命令的堆砌而是一套基于对Linux内核、硬件资源和应用特性深刻理解的系统工程方法。这篇文章的目标就是帮你建立起这套系统性的调优思维和实操能力。无论你是面对一台刚上线的Web服务器还是一个需要极致延迟的数据库实例亦或是一个资源受限的嵌入式环境你都能像老中医一样通过“望闻问切”监控、分析、定位、调整找到性能瓶颈的症结所在并开出精准的“药方”。我们会从最基础的性能观测工具讲起深入到CPU、内存、I/O、网络这四大核心子系统最后落脚于不同场景下的综合调优策略。我的经验是调优的乐趣不在于背命令而在于理解数据背后的故事并亲手让系统“跑”得更顺畅。2. 性能观测调优的前提是看见问题在动手调整任何参数之前你必须清楚地知道系统当前的状态。盲目的调优就像蒙着眼睛开车不仅危险还可能让情况更糟。Linux提供了极其丰富的性能观测工具我们需要掌握一套从全局到局部、从宏观到微观的观测方法。2.1 全局状态一览top/htop与vmstattop命令是大多数人的第一选择它能实时显示系统概览。但看top不能只看第一行的负载平均值load average。负载平均值表示的是处于可运行状态和不可中断睡眠状态的进程数的平均值。对于单核CPU1.0表示刚好满负荷对于4核CPU4.0才是满负荷。更重要的是看下面进程列表中的几个关键列%CPU: 进程的CPU使用率。超过100%意味着它使用了多个核心。%MEM: 进程使用的物理内存占总内存的百分比。TIME: 进程自启动后使用的总CPU时间。一个长期运行但CPU占用很低的进程如果TIME很高是正常的。RES: 常驻内存集即进程实际使用的物理内存大小不含Swap。VIRT: 虚拟内存使用量包含了进程申请的所有内存包括共享库、Swap等。htop是top的增强版界面更友好支持鼠标操作和颜色高亮能更直观地看到CPU核心使用情况和内存/交换分区状态。注意top默认按CPU使用率排序按M可以切换为按内存使用率排序这在排查内存问题时非常有用。vmstat是另一个查看系统整体状态的利器特别是它的“系统”维度信息。常用的命令是vmstat 1表示每秒输出一次报告。重点关注这几列r: 运行队列中的进程数。如果这个值持续大于CPU核心数说明CPU可能饱和了。b: 处于不可中断睡眠通常是I/O等待的进程数。这个值如果长期不为0说明I/O可能存在瓶颈。swpd: 已使用的交换分区大小。如果这个值在增长说明物理内存可能不足。si/so: 每秒从磁盘交换进内存si和从内存交换出到磁盘so的数据量。只要so不为0就说明发生了Swap Out这是内存不足的明确信号会严重拖慢系统。us/sy/id/wa: CPU时间百分比。us是用户态时间sy是系统态时间id是空闲时间wa是I/O等待时间。wa过高是I/O瓶颈的典型标志。2.2 内存深度剖析free与/proc/meminfo很多人用free -m看内存但只关注used和free两列这其实是个误区。在Linux中由于磁盘缓存cache和缓冲区buffer机制内核会利用空闲内存来缓存磁盘数据以提升I/O性能。这部分内存在应用需要时是可以被立刻回收的。因此真正应该关注的是available列在较新版本中或计算free buffers cached。如果available内存长期很低才是内存紧张的信号。更详细的内存信息藏在/proc/meminfo里。这里有几个关键指标MemTotal: 总物理内存。MemFree: 完全空闲的内存。MemAvailable: 估算的可用内存包含可回收的缓存。Buffers/Cached: 缓冲区与页面缓存。SwapCached: 被换出过、但又再次被访问而留在Swap中的缓存。这部分数据如果再次被访问速度会比从磁盘读快但比物理内存慢。Active/Inactive: 活跃与非活跃内存页有助于理解内存压力。SwapTotal/SwapFree: 交换分区总量与剩余量。2.3 I/O性能观测iostat与iotop当应用变慢而CPU和内存看起来都还充裕时瓶颈很可能在磁盘I/O。iostat是诊断I/O问题的核心工具。使用iostat -x 1可以查看扩展统计信息每秒刷新一次。关键列解读%util: 设备利用率。表示设备有I/O请求的时间百分比。对于机械硬盘接近100%通常意味着饱和但对于SSD由于其并行性即使%util很高也可能还有吞吐能力。await: 平均I/O等待时间毫秒。包括队列等待时间和设备服务时间。这是衡量I/O延迟的关键指标值越小越好。svctm: 平均设备服务时间毫秒。理论上应小于await。这个指标在较新版本的iostat中已被标记为不可靠仅供参考。r/s, w/s: 每秒读/写请求数。rkB/s, wkB/s: 每秒读/写数据量KB。avgqu-sz: 平均请求队列长度。队列越长等待时间可能越长。如果iostat发现某个磁盘await很高%util也很高接下来就需要用iotop需要root权限来定位是哪个进程在疯狂读写磁盘。iotop类似于top但显示的是进程的I/O使用情况可以按O键只显示有实际I/O操作的进程。2.4 网络流量观测sar与netstat/ss网络瓶颈可能出现在带宽、连接数、延迟或错误率上。sar命令来自sysstat包可以收集和报告历史性能数据对于网络常用sar -n DEV 1查看每个网络接口的实时流量关注rxkB/s和txkB/s是否接近网卡带宽上限。对于连接数问题传统的netstat和更现代的ss命令是必备的。ss -tlnp可以快速查看所有TCP监听端口及对应的进程。当遇到“Cannot assign requested address”或“TIME_WAIT”过多的问题时ss -s显示的汇总信息非常有用它能告诉你当前各种状态的连接数。实操心得建立一个简单的性能监控基线非常重要。在系统负载正常时用上述命令记录下关键指标如CPU idle, memory available, disk await, network bandwidth usage的典型范围。这样当问题发生时你就能快速识别出哪些指标偏离了基线从而缩小排查范围。3. CPU子系统调优让计算资源物尽其用CPU是系统的“大脑”其调优的核心目标是减少不必要的上下文切换、中断处理开销并让任务在合适的核心上高效执行。3.1 理解CPU调度与中断Linux内核的进程调度器如CFS完全公平调度器负责决定哪个进程在何时使用哪个CPU核心。过多的上下文切换vmstat中的cs列会消耗CPU时间降低有效计算能力。这通常发生在进程数远多于CPU核心数或者进程频繁进行I/O操作时。中断IRQ是硬件通知CPU有紧急事件需要处理的方式比如网卡收到数据包、磁盘完成一次读写。每个中断都会打断CPU当前的工作如果中断过于频繁特别是网络或存储高负载时也会显著影响性能。我们可以通过cat /proc/interrupts查看各CPU核心的中断分布情况。3.2 关键内核参数调优与CPU相关的内核参数主要在/proc/sys/kernel/目录下可以通过sysctl命令临时或永久修改。sched_min_granularity_ns与sched_wakeup_granularity_ns: 这两个参数影响CFS调度器的行为。min_granularity决定了进程最少要运行的时间片调大它可以减少上下文切换适合计算密集型任务调小它则能提升交互式任务的响应速度。wakeup_granularity影响唤醒抢占的粒度一般与min_granularity保持一定比例关系如一半。对于Web服务器、数据库等后台服务可以适当增大这两个值例如分别设置为10000000和15000000单位纳秒。sysctl -w kernel.sched_min_granularity_ns10000000 sysctl -w kernel.sched_wakeup_granularity_ns15000000sched_migration_cost_ns: 这个参数定义了任务在被迁移到其他CPU核心之前需要在当前核心上运行多长时间才“值得”。调大这个值可以减少不必要的任务迁移有利于缓存局部性对性能敏感的应用有益。默认是500000纳秒0.5毫秒可以尝试提高到1000000或更高。sysctl -w kernel.sched_migration_cost_ns1000000中断亲和性IRQ Affinity: 默认情况下中断可能由所有CPU核心处理。我们可以将特定设备如高性能网卡、NVMe SSD的中断绑定到特定的CPU核心上避免中断打扰主要的应用计算核心。这需要用到irqbalance服务通常需要停止它以便手动设置和/proc/irq/[IRQ号]/smp_affinity文件。例如将IRQ 90绑定到CPU核心0和1二进制掩码3即00000011echo 3 /proc/irq/90/smp_affinityCPU频率调节器CPUFreq Governor: 对于虚拟机或云主机这个可能由宿主机管理。对于物理机CPU频率调节器会影响性能和功耗。performance模式让CPU始终以最高主频运行适合对延迟敏感的应用powersave模式则相反ondemand是折中方案。对于数据库、缓存服务器建议设置为performance。# 查看当前调节器 cat /sys/devices/system/cpu/cpu0/cpufreq/scaling_governor # 设置为performance需要root且内核支持 echo performance | tee /sys/devices/system/cpu/cpu*/cpufreq/scaling_governor3.3 进程与任务绑定taskset与cgroups对于极度性能敏感的应用我们可以手动将进程绑定到特定的CPU核心上这称为CPU亲和性CPU Affinity。使用taskset命令可以实现。# 启动一个程序并绑定到CPU核心0和2上 taskset -c 0,2 /path/to/your_app # 修改一个已运行进程PID1234的亲和性绑定到核心1-3 taskset -cp 1-3 1234这样做的好处是减少了缓存失效Cache Miss和上下文切换但绑定时要小心避免将多个高负载进程绑到同一个核心上造成新的瓶颈。更高级的管理方式是使用cgroupsControl Groups它可以对一组进程的CPU资源进行更精细的限制和分配比如设置CPU使用份额cpu.shares、硬性限制使用时间cpu.cfs_quota_us等。这在容器化环境中是基础功能。注意事项CPU调优参数并非越大越好或越小越好。调整前务必做好基准测试Benchmark调整后持续观察关键指标如上下文切换次数cs、CPU利用率us/sy、应用吞吐量和延迟。不同的工作负载OLTP数据库、批处理任务、Web服务的最佳参数组合可能完全不同。4. 内存子系统调优平衡速度与容量内存调优的目标是最大化缓存命中率、减少缺页异常Page Fault并避免昂贵的磁盘交换Swap。4.1 理解虚拟内存与页面缓存Linux使用虚拟内存系统让每个进程都拥有独立的地址空间。物理内存RAM被划分成“页”通常4KB。内核通过“页表”管理虚拟地址到物理页的映射。当进程访问一个尚未映射到物理内存的虚拟地址时会触发一个“缺页异常”内核需要从磁盘可能是可执行文件、共享库或Swap分区中将对应的数据加载到物理页中这个过程相对较慢。为了加速对磁盘数据的访问Linux使用了强大的“页面缓存”Page Cache。读文件时数据会被缓存在内存中写文件时数据也先写到缓存再由后台进程pdflush等异步刷到磁盘。这就是为什么free命令中cached部分通常很大的原因它是性能加速的关键不是内存浪费。4.2 关键内核参数调优内存相关的内核参数在/proc/sys/vm/目录下。swappiness: 这个参数控制内核将内存页交换到磁盘的“积极程度”。值范围0-100。值越高内核越倾向于使用交换分区值越低则越倾向于保留页面缓存。对于拥有大量内存的服务器特别是运行数据库如MySQL, Redis时强烈建议降低swappiness比如设为10甚至1因为数据库期望数据在内存中发生Swap会导致性能骤降。对于桌面系统可以保持默认值通常为60。sysctl -w vm.swappiness10dirty_ratio与dirty_background_ratio: 这两个参数控制脏页已被修改但未写入磁盘的缓存页的回写行为。dirty_background_ratio: 当系统脏页占总内存的百分比达到这个阈值时内核后台线程开始异步地将脏页写回磁盘。默认通常是10。dirty_ratio: 当脏页占比达到这个更高的阈值时触发新的写操作的进程会被阻塞同步地进行磁盘回写直到脏页比例下降。默认通常是20。 对于写密集型应用如日志服务器、大数据处理如果遇到间歇性的I/O停顿可以适当调高这两个值如分别设为20和40让内核积累更多的脏页再批量写入提升吞吐量。但风险是系统崩溃时可能丢失更多数据。同时也可以调整dirty_expire_centisecs脏页最长存活时间和dirty_writeback_centisecs回写线程唤醒间隔来配合。overcommit_memory: 控制内核的内存分配策略Overcommit。0(默认): 启发式overcommit。内核会估算可用内存但允许轻微的过度承诺。1: 总是允许overcommit。适用于某些科学计算场景但风险高。2: 禁止超过CommitLimit的overcommit。CommitLimit由物理内存和Swap大小以及overcommit_ratio参数计算得出。这是最严格的模式可以防止因内存耗尽导致系统突然崩溃而是让malloc()在内存不足时返回失败。对于要求高可靠性的关键服务可以考虑设置为2。sysctl -w vm.overcommit_memory2 # 同时overcommit_ratio定义了可用于overcommit的物理内存百分比默认50 sysctl -w vm.overcommit_ratio80min_free_kbytes: 系统保留的最小空闲内存KB。内核会尝试维持至少这么多内存是空闲的用于应对突发的内存申请避免直接进入内存回收的紧急状态。设置得太小系统在内存压力下容易不稳定设置得太大又会浪费可用内存。一个常见的经验法则是根据总内存来设置sqrt(总内存KB)但不超过总内存的5%。例如对于64GB内存64*1024*1024 KBsqrt约为8192所以可以设置为8192000约8GB。# 计算并设置例如总内存为64GB时 echo 8192000 /proc/sys/vm/min_free_kbytes透明大页Transparent Huge Pages, THP: THP试图自动将普通内存页4KB合并成大页通常2MB以减少页表项TLB Miss和缺页异常的开销对使用大量内存的应用如Java, MongoDB可能有益。但它的自动合并和拆分操作在某些高负载、内存敏感的数据库如PostgreSQL, Redis上可能引起性能波动和延迟尖峰。因此很多数据库官方建议禁用THP。# 查看THP状态 cat /sys/kernel/mm/transparent_hugepage/enabled # 临时禁用重启失效 echo never /sys/kernel/mm/transparent_hugepage/enabled echo never /sys/kernel/mm/transparent_hugepage/defrag # 永久禁用需要修改GRUB配置并重启4.3 针对特定应用的调优数据库如前所述禁用Swapswappiness1谨慎对待THP并确保为数据库实例分配足够的内存如InnoDB Buffer Pool, Redis maxmemory。避免操作系统缓存挤占数据库缓存。Java应用合理设置JVM堆大小-Xms, -Xmx避免堆设置过大导致频繁的Full GC同时也避免过小导致OutOfMemoryError。监控GC日志是关键。对于使用大量内存的Java服务可以尝试启用THP并观察效果。文件服务器/缓存服务器可以适当增加dirty_ratio和dirty_background_ratio来提升写吞吐。确保有足够的物理内存来容纳活跃的工作集和文件缓存。常见问题排查如果发现系统响应变慢vmstat显示si/so持续不为零free显示available极低那么系统正在发生Swap。第一步是立即用iotop或pidstat找到消耗内存最多的进程。第二步是评估是否可以终止或重启该进程或者增加物理内存。第三步是检查并调整swappiness防止未来再次发生。在紧急情况下可以临时关闭Swapswapoff -a但这可能导致内存耗尽而崩溃需谨慎。5. 文件与I/O子系统调优打破存储瓶颈磁盘I/O通常是系统中最慢的环节尤其是机械硬盘。调优的目标是减少I/O等待时间提升吞吐量并合理利用缓存。5.1 文件系统选择与挂载参数不同的文件系统有其特点。ext4成熟稳定是通用服务器的默认选择。XFS在处理大文件和高并发方面表现优异适合大型存储和媒体服务器。Btrfs和ZFS提供了高级功能如写时复制、快照、压缩等但复杂度也更高。即使选择了ext4挂载参数也能显著影响性能。在/etc/fstab中常见的调优选项有noatime或relatime禁用或减少访问时间atime的更新。每次读文件都会更新atime这意味着一次读操作会引发一次写元数据的I/O。noatime完全禁用relatime仅在atime早于mtime/ctime时更新是很好的折中现代Linux默认已是relatime。datawriteback这是ext4的日志模式之一。dataordered默认保证数据在元数据提交前已写入安全性高但性能稍差。datawriteback允许数据在元数据提交后写入性能最好但崩溃后可能造成旧数据出现在文件中。对于非关键数据或已有其他备份/恢复机制的场景如数据库有自己的事务日志可以考虑使用writeback。barrier0禁用写屏障。写屏障用于确保日志数据在对应数据之前落盘保证一致性。在配备电池备份缓存BBU的RAID卡或带有断电保护PLP的SSD上可以安全地禁用屏障以提升性能。普通磁盘禁用此选项有数据损坏风险。nodelalloc禁用延迟分配。延迟分配是ext4的一个优化可以提升连续写入性能但在某些特定负载如虚拟机镜像文件下可能引起碎片化问题。一般不建议修改。一个针对高性能SSD的ext4挂载选项示例UUIDxxxx /data ext4 defaults,noatime,nodelalloc,barrier0 0 15.2 调整I/O调度器I/O调度器决定了内核如何将I/O请求排序和合并后下发给块设备。不同的调度器适合不同的场景。CFQ (Completely Fair Queuing)为每个进程维护独立的I/O队列试图公平分配I/O带宽。适合桌面系统或混合负载。Deadline为读和写请求分别维护队列并附带一个最后期限Deadline优先处理即将超时的请求尤其是读请求能有效减少I/O延迟。适合数据库和虚拟化环境。Noop简单的FIFO队列几乎不做排序。适用于自身有强大调度能力的设备如虚拟机下的虚拟磁盘、或高端SAN/NVMe SSD。Kyber(较新内核)一种基于令牌桶的调度器旨在控制读取和写入的延迟。适合需要低延迟的块设备如SSD。BFQ (Budget Fair Queuing)在CFQ的基础上改进更强调低延迟和公平性适合桌面和交互式应用。对于SATA/SAS SSD或高速NVMe SSD通常推荐使用none即Noop或kyber、mq-deadline多队列版本的Deadline。对于机械硬盘deadline或bfq可能更合适。查看和修改调度器以sda磁盘为例# 查看当前调度器 cat /sys/block/sda/queue/scheduler # 输出可能为[mq-deadline] kyber bfq none # 修改为none echo none /sys/block/sda/queue/scheduler5.3 调整队列深度与预读队列深度块设备队列深度nr_requests决定了能同时排队等待处理的I/O请求数量。对于高速SSD增加队列深度可以更好地发挥其并行处理能力。但设置过大也可能增加延迟。需要根据设备特性和负载测试。# 查看当前队列深度 cat /sys/block/sda/queue/nr_requests # 临时增加队列深度例如增加到256 echo 256 /sys/block/sda/queue/nr_requests预读Read-Ahead内核会预测应用即将读取的数据并提前加载到缓存中。对于顺序读性能很重要。可以通过blockdev命令调整。# 查看当前预读值单位512字节扇区 blockdev --getra /dev/sda # 设置预读值例如设置为8192个扇区即4MB blockdev --setra 8192 /dev/sda对于随机读为主的数据盘如数据库数据文件预读值可以设小或保持默认。对于顺序读为主的盘如日志盘、备份盘可以适当调大。5.4 使用LVM和RAID的考量如果使用了LVM逻辑卷管理器确保/etc/lvm/lvm.conf中的write_cache_state设置为0并定期清理/etc/lvm/cache/.cache以避免在某些情况下导致I/O卡顿。对于RAID阵列选择合适的RAID级别和条带大小Stripe Size至关重要。RAID 10在性能和冗余上取得了很好的平衡是数据库等关键应用的常见选择。条带大小需要与应用的I/O模式匹配对于大量小随机I/O较小的条带如64KB可能更好对于大顺序I/O较大的条带如256KB或512KB可能更优。实操心得I/O调优的黄金法则是“对症下药”。在调整任何参数前务必用fio或ioping等工具进行基准测试模拟你的实际工作负载随机读、随机写、顺序读、顺序写、混合负载。记录下调整前后的IOPS、吞吐量Bandwidth和延迟Latency数据。没有基准测试的调优都是盲目的。6. 网络子系统调优提升连接与吞吐能力网络调优的目标是降低延迟、提高吞吐量、增强连接处理能力并保证稳定性。6.1 TCP/IP协议栈关键参数TCP协议的众多参数控制着连接建立、数据传输、拥塞控制和连接关闭的行为。它们位于/proc/sys/net/ipv4/和/proc/sys/net/core/目录下。端口范围与TIME_WAITnet.ipv4.ip_local_port_range定义本地发起的连接可用的临时端口范围。对于需要发起大量外向连接的客户端如爬虫、代理服务器可以适当扩大这个范围如1024 65535。net.ipv4.tcp_tw_reuse和net.ipv4.tcp_tw_recycle用于快速回收处于TIME_WAIT状态的连接。注意tcp_tw_recycle在NAT环境下可能引起问题且在新版内核中已废弃不建议启用。通常只启用tcp_tw_reuse即可它允许新的连接复用处于TIME_WAIT状态的套接字。sysctl -w net.ipv4.tcp_tw_reuse1 # net.ipv4.tcp_tw_recycle0 保持默认或显式设置为0net.ipv4.tcp_max_tw_buckets系统同时保持的TIME_WAIT套接字的最大数量。如果超过这个值新的TIME_WAIT状态会被立即销毁。可以适当调高以应对高并发短连接场景。连接队列与半连接net.core.somaxconn监听套接字listen()的“完全建立连接队列”Accept Queue的最大长度。如果并发连接请求很高应用来不及accept()队列满了就会导致客户端收到“Connection refused”错误。需要同时调大这个内核参数和应用程序自己的listen()backlog参数如Nginx的backlog参数Tomcat的acceptCount参数。sysctl -w net.core.somaxconn65535net.ipv4.tcp_max_syn_backlog半连接队列SYN Queue的最大长度。用于存放那些已收到SYN但尚未完成三次握手的连接。在遭受SYN Flood攻击时可能需要调整但通常somaxconn更关键。缓冲区大小TCP发送和接收缓冲区的大小直接影响网络吞吐量。缓冲区太小高带宽或高延迟的网络中无法充分利用太大则会浪费内存。内核会自动调整但我们可以设置范围。net.core.rmem_max/wmem_max单个套接字接收/发送缓冲区的最大字节数。net.ipv4.tcp_rmem/tcp_wmem分别为每个TCP套接字的接收/发送缓冲区指定三个值最小值、默认值由内核动态调整的起始值、最大值。通常只需要调整最大值。net.core.netdev_max_backlog当网卡接收包的速度快于内核处理速度时这些包会被放入队列。这个参数控制了该队列的最大长度。在高流量场景下可以增加。# 示例增大TCP缓冲区以支持高带宽延迟积BDP网络 sysctl -w net.core.rmem_max134217728 sysctl -w net.core.wmem_max134217728 sysctl -w net.ipv4.tcp_rmem4096 87380 134217728 sysctl -w net.ipv4.tcp_wmem4096 65536 134217728 sysctl -w net.core.netdev_max_backlog10000拥塞控制与快速重传/恢复net.ipv4.tcp_congestion_control设置TCP拥塞控制算法。cubic是默认算法通用性好。bbr是Google提出的较新算法在高带宽、高延迟的网络中如跨洋链路能显著提升吞吐量并降低延迟。可以尝试切换。sysctl -w net.ipv4.tcp_congestion_controlbbrnet.ipv4.tcp_sack、tcp_dsack、tcp_fack这些是与选择性确认和快速重传相关的参数一般保持开启值为1即可有助于在丢包时提高性能。6.2 网卡与驱动调优中断合并Interrupt Coalescing高流量下网卡每秒产生大量中断会消耗CPU。中断合并允许网卡积累多个数据包后再产生一个中断从而降低中断频率。可以通过ethtool工具调整。# 查看当前设置 ethtool -c eth0 # 调整合并参数具体参数因驱动而异 ethtool -C eth0 rx-usecs 100 tx-usecs 100rx-usecs/tx-usecs定义了接收/发送方向上在产生中断前等待的微秒数。增加这个值可以减少中断次数但可能增加延迟。需要根据负载测试。接收端缩放RSS与队列多队列网卡可以将接收到的数据包负载均衡到多个CPU核心上处理避免单核瓶颈。使用ethtool -l eth0查看队列数量并确保中断亲和性IRQ Affinity被正确设置到不同的CPU核心上。巨型帧Jumbo Frames将标准以太网帧的MTU从1500字节增大如9000字节可以减少协议开销提升大块数据传输的效率。但这需要网络路径上所有设备交换机、路由器、对端主机都支持并配置相同的MTU否则会导致分片或丢包。适用于数据中心内部网络。ip link set eth0 mtu 90006.3 连接跟踪Conntrack与防火墙对于网关、负载均衡器或Docker主机等需要处理大量网络连接转发的系统连接跟踪表nf_conntrack可能成为瓶颈。当表满时新连接会被丢弃。net.netfilter.nf_conntrack_max连接跟踪表的最大条目数。net.netfilter.nf_conntrack_buckets哈希表桶的大小通常与max值相关。net.netfilter.nf_conntrack_tcp_timeout_established已建立TCP连接的跟踪超时时间秒默认是4320005天。对于短连接服务可以适当调低如1小时。sysctl -w net.netfilter.nf_conntrack_max1000000 sysctl -w net.netfilter.nf_conntrack_tcp_timeout_established3600如果不需要连接跟踪例如纯粹的路由器可以考虑卸载相关内核模块或使用NOTRACK规则。常见问题排查网络连接数暴涨出现“Cannot assign requested address”错误。首先用ss -s查看连接统计确认TIME-WAIT状态是否过多。如果是检查是否为短连接服务并考虑启用tcp_tw_reuse。其次检查net.ipv4.ip_local_port_range是否够用。最后检查连接跟踪表/proc/sys/net/netfilter/nf_conntrack_count是否接近nf_conntrack_max。对于高并发服务优化应用程序的连接池和使用长连接是根本。7. 综合场景调优实战理论最终要服务于实践。下面我们看几个典型场景下的综合调优思路。7.1 高并发Web服务器如Nginx目标支撑数万甚至数十万的并发HTTP连接快速响应。用户进程调整Nginx自身配置。worker_processes设置为CPU核心数或autoworker_connections设置每个worker能处理的最大连接数启用epoll事件模型设置multi_accept on。系统层面文件描述符大幅提高系统级和进程级的文件描述符限制fs.file-max,nofileulimit。网络增大net.core.somaxconn并在Nginx的listen指令中设置相应的backlog参数。调整TCP缓冲区大小启用tcp_tw_reuse。根据网络状况考虑使用bbr拥塞控制。CPU确保Nginx worker进程的CPU亲和性设置合理或者使用reuseport选项让多个worker监听同一个端口由内核进行负载均衡。监控重点ss -s中的连接数Nginx的active connectionsvmstat中的cs上下文切换和us用户态CPU。7.2 关系型数据库如MySQL/PostgreSQL目标低延迟、高吞吐的查询和事务处理。内存为王这是最重要的部分。分配尽可能多的内存给数据库的缓冲池如InnoDB Buffer Pool, PostgreSQL的shared_buffers。将vm.swappiness设置为1或0坚决避免Swap。考虑禁用透明大页THP。I/O优化数据库数据文件、日志文件redo log, binlog, WAL最好放在不同的物理磁盘上以减少I/O竞争。根据磁盘类型SSD/HDD选择合适的I/O调度器SSD用none或kyber。调整文件系统挂载参数noatime,datawriteback如果数据库有持久化保证。网络数据库连接通常是长连接但连接数也可能很高。确保max_connections设置合理并对应调整系统的文件描述符限制。对于主从复制确保网络带宽和延迟满足要求。CPU数据库是计算密集型。确保CPU频率调节器为performance模式。对于复杂的查询可以关注CPU的sys时间是否过高这可能意味着内核态锁竞争。7.3 内存缓存服务器如Redis目标极致的读写速度和低延迟。内存与Swap和数据库一样禁用Swap是铁律vm.swappiness0。为Redis设置合理的maxmemory和淘汰策略maxmemory-policy防止内存耗尽被OOM Killer干掉。大页内存Redis支持使用大页内存来分配内存可以减少页表项提升性能。但这需要系统支持并预先分配好大页。需谨慎测试。透明大页Redis官方文档建议禁用THP因为它可能导致延迟尖峰和内存使用率升高。网络Redis通常处理大量的小型请求。确保TCP缓冲区设置合理并且net.core.somaxconn足够大Redis的tcp-backlog配置依赖于此。如果使用Unix Domain Socket进行本地通信速度会更快。持久化如果使用RDB或AOF持久化写磁盘的I/O不能影响主线程的服务。确保appendfsync策略如everysec与磁盘性能匹配。将AOF文件放在高性能SSD上。7.4 虚拟化或容器宿主机目标稳定、高效地为虚拟机或容器分配资源减少宿主机自身开销。I/O调度与队列对于虚拟机使用的存储后端如Ceph RBD、iSCSI、本地磁盘根据设备类型调整调度器和队列深度。宿主机上使用deadline或none调度器可能更合适。网络如果使用桥接或OVS确保宿主机有足够的能力处理软中断。可以启用RPSReceive Packet Steering将软中断负载均衡到多个CPU核心。调整net.core.netdev_max_backlog。内存宿主机需要为自身和虚拟机的缓存预留足够内存。监控KSMKernel Samepage Merging的使用情况它合并相同内存页以节省空间但会消耗CPU。CPU为宿主机管理进程如libvirtd, dockerd和网络/存储中断预留专用的CPU核心通过taskset或cpuset cgroup避免它们干扰虚拟机的CPU调度。调优是一个持续迭代和验证的过程。没有一劳永逸的“银弹”配置。最好的方法是监控 - 建立基线 - 假设瓶颈 - 针对性调整 - 基准测试验证 - 监控对比。养成记录每次变更和其效果的习惯你就能逐渐积累起对自己系统最深刻的认知成为一名真正的调优高手。