- 对 Linux 内核进行调优需要结合架构配置、sysctl 和面向延迟的 CPU 调度。
- 自定义内核和 PREEMPT_RT 补丁可以大幅降低延迟,但它们会增加复杂性和维护难度。
- 网络、内存、磁盘和系统服务的优化应该始终通过严格的监控和基准测试来衡量。
- 迭代式、指标驱动的方法可以将内核改进转化为应用程序和用户的实际利益。
当我们谈论Linux的性能时,几乎所有讨论最终都指向同一个核心:内核。内核是控制延迟、稳定性和资源利用率的核心组件。对其进行精细调优,可以使系统从勉强运行升级到在服务器、桌面、云环境甚至非常老旧的硬件上都能流畅运行。
本指南重点介绍如何优化 Linux 内核以最大限度地降低延迟,同时确保安全性和可维护性。我们将涵盖从基本架构概念到使用 sysctl 进行调整、编译自定义内核、使用实时补丁、针对低延迟网络(例如 EC2)进行调优,以及监控和基准测试技术等所有内容,以衡量您的调整是否真正提高了性能。
Linux 内核架构及延迟关键点
Linux 内核充当应用程序和硬件之间的中间层,管理内存、进程、中断、驱动程序和文件系统。由于采用了可加载模块,其整体式模块化设计允许灵活地启用或禁用某些功能,而无需重新编译整个系统。
要了解延迟的根源,必须深入了解几个子系统:进程调度器、内存管理和中断处理。即使使用强大的硬件,配置不当的调度器、激进的内存策略或过多的不受控制的中断也会导致响应时间缓慢。
内核配置选项,例如CONFIG_PREEMPT、CONFIG_PREEMPT_VOLUNTARY 和 CONFIG_SMP,都发挥着作用。这些选项决定了内核在多大程度上可以被抢占以处理更紧急的任务,以及内核如何处理多核系统。选择合适的抢占模型会显著改变桌面、低延迟服务器或工业系统上的感知延迟。
在现代服务器中,硬件拓扑结构也至关重要:核心分布、插槽、NUMA 和缓存层次结构。微调 CPU 亲和性和 NUMA 策略(例如,将进程和内存分配到同一节点)有助于减少访问时间并提高缓存命中率,这对于最大限度地减少抖动和不可预测的延迟至关重要。
此外,CPU调度器与I/O子系统(磁盘和网络)之间的交互决定了应用程序的端到端吞吐量和延迟。在进行任何更改之前,建议记录当前状态(内核配置、sysctl、GRUB、已加载模块),以便在更改导致性能下降时能够快速回滚。
通过 sysctl 进行调整以改善延迟和性能
sysctl接口允许您通过 /proc/sys 动态修改内核参数,而无需重新编译。它是进行调优的理想入口点,避免了繁琐的编译过程。
在网络环境中,诸如net.core.rmem_max、net.core.wmem_max 和 net.ipv4.tcp_congestion_control等参数直接影响吞吐量、延迟和 TCP 连接行为。对于高流量 Web 服务器或低延迟云实例而言,合理调整缓冲区和拥塞算法至关重要。
对于内存管理,诸如vm.swappiness、vm.dirty_ratio、vm.vfs_cache_pressure 和 vm.overcommit_memory之类的参数可以控制交换空间的使用量、页面缓存的管理方式以及虚拟内存的行为。降低交换空间使用率(例如,降至 10)通常有助于防止系统过于频繁地使用交换空间,从而减少因磁盘 I/O 引起的延迟峰值。
如果您使用大型数据库或应用程序,并且这些应用程序会使用大量的共享内存,那么调整kernel.shmmax、kernel.shmall以及使用fs.file-max 和 fs.nr_open 设置的最大打开文件数至关重要。不合适的限制可能会导致瓶颈和错误,而这些错误在高负载下难以诊断。
建议先进行小幅修改,使用监控工具评估其影响,然后再将修改提交到 /etc/sysctl.conf 或 /etc/sysctl.d/ 目录。在容器化环境中,请记住许多内核参数是全局的,对主机的影响有限:不谨慎的修改可能会影响所有服务,因此将 sysctl 与 cgroups 和命名空间结合使用几乎是必须的。
编译和维护自定义内核
当您需要降低延迟、消除不必要的开销或支持特殊硬件时,编译自定义内核仍然是一个强大的工具。尽管发行版包含相当通用的内核,但在某些情况下,特定的内核至关重要。
传统的流程包括从以下位置下载代码: kernel.org 或像 xanmod 这样的打过补丁的内核树 利可力克斯并使用诸如此类的工具 make menuconfig 选择选项。将 .config 文件与构建脚本一起保存到您自己的 Git 仓库中,可以让您重现构建过程并保持版本之间的一致性。
如果您使用 Debian 或其衍生发行版,那么按照“ Debian 方式”编译内核、头文件和相关库的 .deb 软件包会非常方便。这样,您只需安装这些软件包,并通过您自己的软件仓库管理版本,即可在多台机器上部署该自定义内核。
在实际应用中,使用老旧或配置非常有限的硬件时,手动编译往往更有意义。一个典型的例子是配备 Atom CPU 和 1GB 内存的老式上网本,在这种情况下,安装一个包含大量不必要驱动程序和服务器级选项的现代通用内核,会引入你无法承受的延迟和额外的 CPU 占用。
一种常见的策略是从当前的内核配置开始(例如,从 /boot 目录复制配置文件),然后对其进行修剪或调整。您可以将抢占模型更改为“抢占式内核(低延迟桌面) ”以优先处理桌面的交互式响应,或者添加特定的 I/O 调度器(例如BFQ)作为模块,以改善在机械硬盘上的体验。
为了避免耗费大量编译时间,最好在性能更强的机器上进行编译,必要时可以使用交叉编译(例如,只需调整架构和相应的工具链,即可从 x86_64 PC 为 Atom 编译 32 位内核)。然后,只需在目标机器上安装 .deb 文件,并在 GRUB 中添加相应的启动项即可。
棘手的部分是维护:建议在 Canary Islands 节点上测试新内核,在启动管理器中设置清晰的回滚路径,并在过渡期间记录日志和指标,以检测性能或驱动程序兼容性方面的退化。
低延迟系统的抢占模型和 PREEMPT_RT 补丁
内核的抢占模型决定了正在运行的任务可以被中断多少次,以便让优先级更高的任务接管,这直接影响响应延迟。这包括标准配置选项和实时补丁。
通用内核提供多种选项:无抢占(更注重服务器吞吐量)、自愿抢占以及面向桌面系统的可抢占内核,后者优先考虑交互式应用程序的快速响应时间。调整此设置可以显著提升桌面系统、音频应用程序甚至老旧、高负载机器的性能。
当您需要更进一步时,可以使用PREEMPT 和 PREEMPT_RT 补丁,它们会修改内核的重要部分,以最大限度地减少不可抢占的部分。PREEMPT_RT 适用于最坏情况延迟(而不仅仅是平均延迟)必须非常低且可预测的系统,例如工业自动化、专业音频、电信或高频交易。
引入 PREEMPT_RT 的决定不应基于趋势,而应基于延迟和抖动的具体测量结果。首先,建议在引入 RT 树增加维护复杂性之前,充分探索调度器设置、CPU 亲和性、sysctl 以及(如果适用)动态无滴答等配置。
兼容性也必须考虑在内:某些驱动程序和子系统尚未完全适配 RT,可能需要特定版本或额外的补丁。明智的做法是制定维护计划,明确规定何时以及如何将主内核的新版本与 RT 分支集成。RT 分支虽然会定期同步,但仍然存在一定的滞后。
CPU调度调优、无滴答运行和核心隔离
除了选择抢占模型之外,您还可以通过调整 CPU 调度和内核定时器行为来微调延迟,尤其是在像 RHEL 这样的面向企业的发行版中。
例如,Red Hat Enterprise Linux 8默认配备了一个用于空闲 CPU 的无滴答内核,通过避免内核空闲时的周期性中断来降低功耗。对于对延迟敏感的工作负载,可以在一组内核上启用动态无滴答模式,这样就只有一个 CPU(“主内核”)处理大部分计时任务,而其余 CPU 则尽可能避免周期性中断。
这种配置是通过添加适当的参数来完成的。 GRUB中的内核命令行重新生成配置,然后调整关键内核线程(例如 RCU 线程或线程)的亲和性 bdi-flush以便它们能够驻留在为维护而预留的核心区域。
这种方法可以配合`isolcpus`参数使用,该参数允许将核心与普通用户空间任务隔离。在低延迟场景中,通常会预留几个核心专门用于关键应用程序,而系统的其余部分(守护进程、中断等)则由其他核心处理。
为了验证动态无滴答模式是否正常工作,可以运行简单的测试。 stress 或者编写脚本,让 CPU 保持忙碌一秒钟,然后观察结果。 计时器滴答计数器 在孤立的内核中,每秒中断次数从数千次骤降至仅一次,这表明周期性定时器已经消失。
内存和存储管理,重点关注延迟
内核管理内存和磁盘 I/O 的方式对应用程序感知到的延迟有巨大的影响,尤其是在数据库和服务中,这些数据库和服务会执行许多小的、频繁的操作。
在内存方面,降低vm.swappiness可以最大限度地减少交换空间的使用(交换空间的使用速度几乎总是比 RAM 慢得多),vm.vfs_cache_pressure可以控制系统释放 inode 和 dentry 缓存的速度,而vm.nr_hugepages允许您为数据库或 JVM 等高负载保留静态 HugePages,从而减少 TLB 开销。
在存储方面,选择 根据磁盘类型选择合适的 I/O 调度器 这至关重要。在现代固态硬盘上,通常最好使用…… none o mq-deadline而在机械磁盘和多任务系统中,为公平性而设计的算法可能更好,例如: BFQ此外,还可以使用诸如以下选项挂载文件系统: noatime y nodiratime 避免每次访问文件或目录时都进行不必要的写入。
就文件系统而言,ext4 和 XFS仍然是最常见的选择:经过良好调优的 ext4 是一个稳妥的选择,而 XFS 在高并发情况下往往具有更好的扩展性。对于要求极高的场景,将 RAID(数据库使用 RAID 10,临时暂存存储使用 RAID 0)与优秀的调度器结合使用,可以降低平均延迟,尤其能够显著降低延迟波动。
Linux 和 EC2 中的网络和内核优化,以实现低延迟
在高性能网络应用中,延迟不仅取决于硬件或距离,还取决于TCP/IP 协议栈和内核本身的配置方式。这一点在配备 ENA 接口的云实例(例如 Amazon EC2)上尤为明显。
首先,关键在于减少外部因素,例如数据包的网络跳数:使用更直接的拓扑结构、靠近后端的负载均衡器或优化的可用区,可以在数据包到达操作系统之前,以毫秒级的速度减少传输时间。
在内核中,网络配置涉及增加文件描述符(ulimit -n) ,使用net.core.rmem_max、net.core.wmem_max、net.ipv4.tcp_rmem、net.ipv4.tcp_wmem调整接收和发送缓冲区的大小,以及启用TCP 快速打开等选项以减少连接建立延迟。
在 AWS ENA 接口中,中断调节发挥着重要作用:默认情况下,驱动程序将数据包分组以减少 IRQ 的数量。 接收微秒和发送微秒如果您想将延迟降至最低,可以通过以下方式禁用此功能: ethtool -C将 rx-usecs 和 tx-usecs 设置为零可以降低延迟,但会增加中断开销,因此必须根据负载找到一个平衡点。
您还可以使用irqbalance 将 IRQ 分配到多个核心,或者禁用它并手动将中断和网络队列 (RSS/RPS) 亲和性设置为特定核心,这在超低延迟环境或使用 DPDK 并跳过内核堆栈的大部分时非常常见。
另一个需要考虑的参数是CPU的C状态:深度睡眠状态可以降低功耗,但会在核心“唤醒”时引入延迟。为了减少响应延迟,您可以限制深度睡眠状态的次数,但这会造成更高的功耗,并降低其他核心睿频加速的可用空间。每种环境都有其最佳的功耗和延迟之间的平衡点。
优化 CPU、服务和应用程序以降低延迟
除了内核本身之外,周围环境对整体延迟也有很大影响:从系统上活动的服务到每个应用程序的具体配置。
高性能服务器应该只运行 真正必要的恶魔后端机器上的蓝牙、打印或网络自动发现(CUPS、Avahi 等)等服务只会消耗 CPU、内存和 I/O 资源,却没有任何实际收益。 systemctl list-unit-files --state=enabled 禁用不必要的功能是最便宜、最有效的方法之一。
为了优先处理关键进程,您可以使用renice、chrt 和 taskset等工具。调整进程的优先级(renice)、为其分配实时调度(chrt -f 99)或将其分配到特定核心(taskset)可以减少对其他任务的干扰,从而提高数据库、VoIP、流媒体或交易服务的 CPU 使用率可预测性。
在应用层,调优与内核调优同等重要。像Nginx 或 Apache这样的 Web 服务器需要对工作进程、Keepalive 机制、缓存和压缩进行微调。像PostgreSQL 或 MySQL这样的数据库则需要审查缓冲区大小、检查点、连接池和同步写入参数,以实现低延迟和稳定的延迟。
JVM 也发挥着重要作用:选择G1GC 或 ZGC等垃圾回收器并调整堆大小可以减少暂停,这些暂停从外部表现为延迟。在虚拟化和容器化环境中,合理分配vCPU、vRAM 和 I/O 配额可以防止静默争用,而静默争用最终会导致磁盘队列无限增长或 CPU 过载。
内核和系统监控与基准测试
如果不衡量其影响,所有这些调优都毫无意义。关键在于将持续监控与可复现的性能测试相结合,以便能够用客观数据评估对内核或系统控制项的每一次更改。
要查看系统的整体状态,您可以使用诸如以下经典工具: htop、vmstat、iotop o sar当您需要更多详细信息时,就需要使用特定的内核工具,例如 perf 和 ftrace这使您可以相当准确地跟踪调度程序、中断和内部调用的行为。
在生产环境中,建议部署Prometheus、collectd 或 sysstat 等指标系统,并配备导出器来公开 CPU 计数器、I/O、磁盘和网络延迟、进程队列等信息。使用 Grafana 或类似工具可视化这些数据,有助于在最终用户注意到问题之前检测到回归或异常情况。
对于基准测试,其理念是复现实际工作负载,并比较每次更改前后的性能差异。诸如sysbench(用于 CPU 和数据库)、fio(用于磁盘)或iperf3 (用于网络)之类的工具可以帮助您构建可重复的测试场景。记录内核版本、sysctl 配置、硬件和测试参数至关重要,这样才能确保比较结果在长期使用中仍然有效。
实际上,Linux 内核优化是一个迭代过程:你需要测试一系列调整,衡量结果,保留真正有效的调整,并舍弃其余部分。通过良好的变更管理,你可以将新内核版本(例如最近几个版本在调度器、图形、电源或网络方面的改进)中的提升转化为应用程序可衡量的性能收益,无论这些应用程序部署在本地服务器、云端还是高要求的工作站上。
内核架构知识、使用 sysctl 进行微调、受控编译、选择性地使用实时补丁以及良好的指标体系相结合,使管理员或运维团队能够实现更快的响应速度、更低的延迟和更好的整体稳定性,而无需在受到任何轻微刺激时就更换硬件或损害系统安全。