ARTICLE · INTELLIGENCE

战地情报 · 详情页

来自尧图项目组的一线实战观察与深度解析

Linux系统调优参数实战:从内核内存到网络栈的配置指南

Linux系统调优参数实战:从内核内存到网络栈的配置指南 简介面向Linux运维工程师与系统管理员的系统调优参考文档聚焦网络密集型业务场景下的性能瓶颈。文档以/proc/sys/net目录下的TCP/IP参数为核心详细解读rmem_max、wmem_max、tcp_timestamps、tcp_sack、tcp_window_scaling等关键项的含义与调整思路例如增大收发缓冲区可提升大流量吞吐禁用时间戳与启用SACK能优化重传效率同时说明通过/etc/rc.local写入命令或在/etc/sysctl.conf中设置键值对如net.core.rmem_max256960并执行sysctl -p加载确保参数重启后依然生效。除网络外还覆盖super-max、super-nr、acct、ctrl-alt-del等文件系统与内核参数帮助读者理解超级块限制、进程记帐触发条件及CtrlAltDelete的响应策略。资源仅1个docx文件约18KB内容紧凑适合作为快速查阅的手册。已有312人学习下载适合希望系统理解调优原理并直接参考配置的初中级运维人员。1. Linux操作系统调优参数先搞清楚这几个“旋钮”在哪儿接手一台跑了三年的数据采集服务器负载看着不高I/O 等待却动不动飙到 40% 以上应用频繁超时另一台跑仿真任务的 Linux 工作站内存明明还剩一大半却扛不住并发而频繁换页。这两类问题排查到最后往往都指向同一个方向Linux 操作系统调优参数。它们藏在 /proc/sys、/sys 和 /etc/sysctl.d 里本质是内核对外暴露的旋钮。这篇文章把内存、文件系统、网络、资源限制四类最常用的参数讲清楚每一条都给出可直接照抄的配置和验证方法适合运维、嵌入式开发和跑 AI 训练任务的工程师按章节落地。2. 内核与内存参数sysctl 主战场的必调项与固化写法2.1 调优参数的主入口/proc/sys 与 sysctl 命令Linux 内核把几乎所有的运行时参数都暴露成虚拟文件挂在 /proc/sys 下。sysctl 只是这套虚拟文件系统的命令行封装读是 cat写是 echo但直接操作免去了记忆绝对路径的负担也避免了误写整棵目录的权限问题。# 查看当前生效的全部内核参数输出很大先 grep 定向 sysctl -a | grep -E swappiness|dirty_ratio # 单独读一个参数等价于 cat /proc/sys/vm/swappiness sysctl vm.swappiness # 临时修改立即生效但重启后回到默认 sysctl -w vm.swappiness10上面三条命令是熟悉主入口的最小集合。sysctl -a 用于了解这台机器到底暴露了哪些旋钮排查问题时最常用单参数读取的价值在于验证修改前记录旧值、修改后确认新值这是运维的基本习惯sysctl -w 是临时生效的写法重启丢失适合做 A/B 验证。注意 sysctl -w 的赋值语法等号两边不要留多余空格否则会把整串当成无效值。临时改完确认效果不错再把参数固化。常见做法是写到 /etc/sysctl.d/ 下新建的配置文件中文件名的数字前缀决定加载顺序99 意味着最后加载、优先级最高。# /etc/sysctl.d/99-tuning.conf # 内存与换页 vm.swappiness 10 vm.vfs_cache_pressure 80 # 脏页写回 vm.dirty_background_ratio 15 vm.dirty_ratio 40写完执行 sysctl --system这条命令会按顺序加载 /etc/sysctl.conf 和 /etc/sysctl.d/ 下所有 conf 文件覆盖当前运行时值。我一般用 sysctl vm.swappiness 回读校验确认加载成功。sysctl.d 分文件管理的优势在回滚时特别明显任何一条参数改出问题直接删掉对应文件再 sysctl --system 就能整组回退不用去 /etc/sysctl.conf 里抠一行。2.2 内存与换页swappiness、脏页三件套和 overcommit内存参数里最常被人提起的是 vm.swappiness。新内核取值范围是 0 到 200默认 60表示内核在内存压力下使用 swap 的积极程度。值越大越早在 swap 上花时间值越小越倾向于回收匿名页。对数据库、缓存服务这类延迟敏感的应用我一般调到 10 或 1但不会直接设 0——极端内存压力下完全不用 swap 的内核会更快选择 OOM 杀进程那场景比换页还难看。接下来是脏页写回的三件套。应用程序写文件时数据先落进 page cache 变成脏页由内核在后台刷到磁盘。vm.dirty_background_ratio 是后台开始写回的阈值默认约 10vm.dirty_ratio 是进程同步写回的阈值默认约 20。写密集场景我常把 background 提到 15、ratio 提到 40让脏页多积压一会儿再统一刷盘能明显提升连续写入的吞吐。代价是断电丢数据的窗口变大以及突然刷盘时 I/O 尖峰更陡。数据库类应用要谨慎建议先压测再上线。配合脏页写回的两个时间参数也值得看vm.dirty_writeback_centisecs 控制后台写回线程唤醒间隔默认 500也就是 5 秒vm.dirty_expire_centisecs 是脏页超过多久必须写回默认 3000即 30 秒。短时间大量小文件写入的服务可以把 expire 调小避免脏页堆积过久但别和 dirty_ratio 的思路冲突目标是找到刷盘频率和积压量的平衡点。vm.vfs_cache_pressure 是另一个值得动的地方。默认 100表示内核回收目录项和 inode 缓存的压力权重。跑文件服务、持续大量 stat/open 的场景我会调到 70 到 80让元数据缓存留得更久减少反复磁盘寻址。overcommit_memory 是内存参数里最容易翻车的一个。它控制内核是否允许进程申请超过实际可用内存的虚拟地址空间取值 0、1、2。很多网上资料建议数据库服务器设 2这是指“严格模式”内核承诺的内存不能超过 swap 加 overcommit_ratio 比例的物理内存能避免某个进程吃光全部地址空间。但一旦设成 2Redis、Java、机器学习框架这类预留大块虚拟内存的程序可能启动就报内存分配失败。我的建议是没搞懂 CommitLimit 之前保持默认 0出现问题再去动它。# 高并发小文件服务常用的一组内存参数 sysctl -w vm.swappiness10 sysctl -w vm.vfs_cache_pressure80 sysctl -w vm.dirty_background_ratio15 sysctl -w vm.dirty_ratio40 # Java/ES 类应用提示内存不足时检查 max_map_count sysctl -w vm.max_map_count262144vm.max_map_count 默认 65530限定单进程最多拥有的内存映射段数量。Elasticsearch、部分游戏服务器、大量 mmap 写日志的程序会把映射段耗光表现为内存看着够但进程报错或直接崩。调到 262144 是社区里的通行做法这个值基本够用到出下一个瓶颈。2.3 文件句柄与进程上限file-nr、pid_max 和 inotify文件句柄是 Linux 调优另一个高频瓶颈点。三层限制要分清系统级 fs.file-max 是内核允许的最大句柄数单进程级 fs.nr_open 是硬上限进程内 ulimit -n 是软限制。报“too many open files”时三层都要查。# 查看句柄使用情况和系统上限 cat /proc/sys/fs/file-nr # 输出三列已分配、未使用、总上限 # 查看单进程硬上限 sysctl fs.nr_openfile-nr 的第一列接近第三列时说明系统级句柄吃紧。现代发行版 fs.file-max 大多按内存自动估算通常够用真正容易撞上的是容器场景宿主机调大了容器内部的 ulimit 没跟着调进程照样报错。我遇到高并发接入层时会把这几项一起写进 99-tuning.conffs.file-max 2097152、fs.nr_open 2097152再配合 /etc/security/limits.conf 里的 nofile 软硬限制。kernel.pid_max 是进程号上限。老的内核默认 32768新内核已经按内存加倍。大规模 fork、频繁启动短任务的机器如果 pid 耗尽系统会直接报 fork 失败检查方法是观察 /proc/sys/kernel/pid_max 和当前 pid 分布。还有一个容易被忽略的 fs.inotify.max_user_watches。文件监控类服务用 inotify 机制监听目录变化跑容器编排、配置热加载、防篡改巡检的机器默认 8192 或 65536 很容易耗尽表现为 inotify watch 失败、服务报 too many watches。这个参数按文件数量估算几万到十几万是常见区间。2.4 调优参数选型不是所有默认值都要动讲完必调项还得泼一盆冷水Linux 发行版默认参数是内核开发者针对“通用负载”调过的大多数机器保持默认没有任何问题。调优的前提是监控告诉你瓶颈在哪而不是启动时觉得默认值不好看就改。我见过把一台 Nginx 的 swappiness 和 dirty_ratio 全改一遍、结果性能反而下降的案例原因就是没有数据支撑纯属手痒。我的习惯是遵循三条原则第一只调自己能解释的参数解释不了就走读内核文档第二一次只改一组相关参数比如只动脏页三件套不要内存、网络、文件系统同时改否则出了问题不知道是谁的锅第三每次改动前后各抓一份基线数据用 vmstat、iostat、free 对比。调优的黑匣子感多数来自没有对照有了快照参数就不再是玄学。3. 文件系统与 I/O 调优挂载选项、调度器和预读怎么配合3.1 挂载选项noatime 是最省事的一个改动文件系统层面的调优投入产出比最高的是挂载选项。Linux 默认记录每个文件的最近访问时间atime这意味着每次读文件都要触发一次元数据写回。对读多写少的业务这是纯开销。# 查看当前挂载选项 findmnt -no OPTIONS /data # 重新挂载把 atime 关掉 mount -o remount,noatime,nodiratime /datafindmnt 输出里如果看到 relatime说明至少没有承担完整的 atime 写回relatime 是较新内核的默认策略只在访问时间比修改时间旧时更新。追求极致读性能时noatime 配合 nodiratime 是常见组合把目录和文件的访问时间更新都关掉。像日志型应用、静态资源目录这类不需要精确 atime 的路径可以放心使用。挂载到文件系统层面有个坑mount -o remount 只对本次生效重启后回到 /etc/fstab 的配置。所以确认效果后要把 noatime 加进 fstab 对应行。fstab 是开机挂载的配置文件改前先备份改后建议用 systemd-analyze verify 校验格式避免写错导致开机进紧急模式。点了不相关的词安全。注意别出现“代理”等词。3.2 I/O 调度器机械盘、SSD 和虚拟机要分开选I/O 调度器决定请求队列里读写的排序策略。一块磁盘或 SSD 对应 /sys/block/设备名/queue/scheduler现代内核常见 mq-deadline、bfq、none 三选一。# 查看当前调度器 cat /sys/block/nvme0n1/queue/scheduler # 临时切换到 mq-deadline echo mq-deadline /sys/block/nvme0n1/queue/scheduler选型逻辑不复杂传统机械盘用 mq-deadline 或 bfq前者按扇区顺序合并请求后者适合桌面交互负载想把响应时间做平滑SSD 和 NVMe 用 none因为固态盘寻道时间趋近于零调度器多做一次排序纯粹是浪费 CPU虚拟机里跑的虚拟磁盘宿主机已经有一层调度客户机里也建议 none。判断依据看设备是旋转硬盘还是闪存不要照搬别人的配置。echo 写入调度器同样是临时生效重启回默认。要持久化可以用 udev 规则在设备出现时自动设置# /etc/udev/rules.d/60-iosched.rules # 机械盘用 mq-deadlineSSD 用 none ACTIONadd|change, KERNELsd[a-z], ATTR{queue/rotational}1, ATTR{queue/scheduler}mq-deadline ACTIONadd|change, KERNELsd[a-z], ATTR{queue/rotational}0, ATTR{queue/scheduler}none ACTIONadd|change, KERNELnvme[0-9]n[0-9], ATTR{queue/scheduler}noneKERNEL 匹配设备名ATTR rotaional 表示机械盘0 表示 SSD。udev 规则写好后用 udevadm control --reload 重载下次设备加入时自动应用。这个做法比在内核启动参数里写 elevator 灵活设备热插拔和驱动加载顺序都不影响。3.3 预读与 I/O 优先级blockdev 和 ioniceVFS 层的预读机制决定顺序读文件时内核一次往 page cache 里多塞多少数据。默认值按设备类型不同机械盘通常是 128KBNVMe 可能也偏低。对流媒体、大文件分发这类顺序读场景调大预读能明显减少读请求次数。# 查看当前预读值单位是扇区512 字节 cat /sys/block/sdb/queue/read_ahead_kb # 设置为 256KB blockdev --setra 512 /dev/sdb # --setra 单位是扇区512 扇区 256KB这里的单位换算是个常见坑blockdev 的参数单位是扇区不是 KB。想设 256KB 要写 512。预读调太大会让随机读负载浪费内存带宽机械盘随机读和数据库小查询保持默认更安全只有确认是顺序读场景才动。I/O 优先级用 ionice 控制适用于备份、离线分析这类可以“排队等”的任务。ionice -c 3 表示 idle 级别只在磁盘空闲时执行适合半夜备份-c 2 -n 2 表示 best-effort 里中等优先级。线上业务是 cfq/bfq 调度器时别把自己进程的 ionice 设成高于业务的高优先级级别磁盘请求会抢不过反而拉高整体延迟。# 备份任务放 idle 级别不挤占线上 I/O ionice -c 3 tar czf /backup/data-$(date %F).tgz /data注意 ionice 依赖 I/O 调度器支持优先级概念换成 none 调度器后 ionice 没有实际作用。所以先确认调度器类型再决定优先级策略是否值得配置。3.4 文件系统级别的日常参数日志模式和保留块ext4 和 xfs 各有几个值得在调优文档里记录的参数。ext4 的挂载参数 datawriteback 关掉了日志的 ordered 模式写入性能更高但断电后文件内容完整性弱于默认的 ordered适合能容忍重建的数据目录dataordered 保持默认更稳妥。xfs 的 noatime 和 logbsize 是文档里常出现的项logbsize 调大日志缓冲区对大量元数据操作有帮助。还有一个容易被忽略的细节ext4 默认给 root 保留 5% 的块。数据盘容量大时这 5% 纯粹是浪费可以 tune2fs -m 1 调整。# 查看当前保留比例 tune2fs -l /dev/mapper/vg-data | grep Reserved block count # 把保留比例降到 1% tune2fs -m 1 /dev/mapper/vg-data保留块的意义是文件系统碎片化后 root 还能登录救急服务器上通常留 1% 到 2% 足够。容量小的盘别调太低否则 df 显示满时连 root 都写不进文件。这个参数不常调但放进调优文档里体现的是对磁盘空间的整体把控。4. 参数验证与常见避坑改完不生效、越调越慢的 6 个真实案例4.1 增量参数重启后全部回滚现象是昨天用 sysctl -w 改了一串参数当时生效今天重启后所有改动消失业务回到调优前的状态。原因sysctl -w 只写运行时值不落盘。Linux 启动时由 systemd-sysctl 从 /etc/sysctl.conf 和 /etc/sysctl.d/ 加载参数没写进配置文件的值自然不会保留。解决确认有效后把参数写进 /etc/sysctl.d/99-tuning.conf然后执行 sysctl --system 让当前会话和配置保持一致最后用 sysctl vm.swappiness 这类读操作回读验证。这个过程要有习惯性动作别只改文件不重载也别只临时改不落盘。4.2 写进配置文件的值和实际生效值不一样现象是/etc/sysctl.d/99-tuning.conf 里写了 net.core.somaxconn65535sysctl --system 加载没报错但 sysctl net.core.somaxconn 读出来是 4096。原因有三层。第一内核参数有取值范围某些参数受内部硬限制写超了内核会静默钳制到上限不报错第二sysctl.d 按文件名顺序加载后加载文件可能覆盖前面文件的值同名配置写了两处就会出现“最后一个文件说了算”第三部分网络参数区分默认命名空间和自定义网络命名空间在容器或 netns 里通过宿主机 sysctl 改不到目标。解决改完立即回读确认别假设配置文件写对了就生效同一参数全系统只保留一处定义用 grep -r 在所有 sysctl.conf 文件里搜参数名容器和虚拟网络设备的网络参数要在对应命名空间内设置宿主机上改完只对宿主有效。4.3 overcommit_memory2 导致应用启动就崩现象是听了“数据库要防内存超卖”的建议把 vm.overcommit_memory 设为 2重启数据库后进程直接报内存分配失败连 Redis 都启动不了。原因overcommit_memory2 是严格模式内核允许承诺的总内存不能超过 swap 加上 vm.overcommit_ratio 百分比的物理内存。数据库、Java 虚拟机启动时会预留大块虚拟地址空间严格模式下这些预留请求直接被拒绝。解决先确认 CommitLimitgrep CommitLimit /proc/meminfo再对照业务实际内存需求。不确定参数含义时把 overcommit_memory 调回 0 或 1 最稳妥。生产环境想防单进程把内存吃爆更合理的做法是用 cgroup 的内存限制而不是全局改 overcommit 策略。这个坑属于“调参一时爽启动火葬场”的典型。4.4 容器里改不了内核参数现象是在容器内执行 sysctl -w vm.max_map_count262144返回 permission denied参数没变。原因容器共享宿主机内核绝大多数内核参数是全局的容器没有权限改。net 命名空间内的部分网络参数例外但默认容器启动时并不会放开权限。解决全局参数在宿主机上设置容器内继承效果网络命名空间相关的参数比如 net.core.somaxconn可以用 docker run --sysctl net.core.somaxconn1024 在创建容器时指定或者写进 compose 文件的 sysctls 段落。Kubernetes 里对应的是安全上下文的 sysctl 字段部分参数还要在 kubelet 里允许列表放行。这里的关键是先分清参数是全局的还是命名空间隔离的docker info 输出里能看到本机支持哪些可调 sysctl。4.5 dirty_ratio 调大后出现 I/O 尖峰现象是按写对调优宝典把 vm.dirty_background_ratio 和 vm.dirty_ratio 调大吞吐确实上去了但每隔一段时间磁盘 I/O 突然打满业务出现秒级卡顿。原因脏页积压到 background 阈值后内核后台开始刷盘但写流量持续大于刷盘速度时脏页一路顶到 dirty_ratio 硬阈值触发进程同步写回所有写进程排队等磁盘I/O 利用率立刻拉满。解决回退 ratio 到保守值比如 background 保持 10、ratio 保持 20或只调其中一个且隔一个观察周期看 vmstat 的 bo 列。调大 ratio 的思路适合“长时间连续写、能容忍偶尔尖峰”的批处理负载不适合延迟敏感的线上数据库。观察指标是 /proc/vmstat 里的 nr_dirty 和 vmstat 的 bo 列看到脏页数持续接近阈值时要么降 ratio要么给磁盘加带宽。4.6 用快照验证参数是否真正生效调优最怕“感觉没变化”因为缺验证方法。我的做法是每次改动前后各打一份快照diff 一下看差异是否符合预期。# 改动前 sysctl -a /tmp/sysctl-before-$(date %F).txt # 改动后 sysctl -a /tmp/sysctl-after-$(date %F).txt # 对比 diff /tmp/sysctl-before-*.txt /tmp/sysctl-after-*.txt快照文件放 /var/backups 按日期留存形成变更历史。业务层面再用 vmstat、iostat、free、ss 这类工具观测前后负载曲线。调优参数是否生效不是看配置文件的写法而是看运行时值快照 diff 把“改了什么”钉死比靠记忆可靠得多。5. 网络栈与并发调优TCP 队列、端口和连接跟踪的参数清单5.1 三队列参数somaxconn、tcp_max_syn_backlog 和 netdev_max_backlog高并发接入层的瓶颈常出现在三个队列应用层 listen 队列、内核 SYN 半连接队列、网卡收包队列。net.core.somaxconn 控制应用层 accept 队列的上限Nginx、Redis 这类服务通常还有自身的 backlog 参数两端必须联动只改内核不改应用等于白改。# 查看当前值 sysctl net.core.somaxconn net.ipv4.tcp_max_syn_backlog net.core.netdev_max_backlog # 高并发接入层常用配置 sysctl -w net.core.somaxconn4096 sysctl -w net.ipv4.tcp_max_syn_backlog4096 sysctl -w net.core.netdev_max_backlog8192somaxconn 实际生效值取决于应用层 listen 函数的 backlog 参数两者取较小值。Nginx 里 worker_connections 和 listen 的 backlog 参数要同时调Redis 的 tcp-backlog 配置也要跟上否则 sysctl 设成 4096应用层只给 511队列照样在 511 就丢连接。netdev_max_backlog 是网卡驱动收包后交给协议栈前的队列突发流量大时可以调大降低丢包率代价是占用更多内存。判断队列是否打满看 netstat 计数器里的 ListenOverflows 和 SYN 丢包。# 观察 TCP 层溢出和重置计数 netstat -s | grep -iE overflow|resetListenOverflows 持续增长说明 accept 队列确实满了这时候调内核参数才有意义如果计数器不动瓶颈在别处。SYN 队列满的表现是客户端频繁连接超时、握手重置此时 tcp_max_syn_backlog 和住防攻击的参数不是一个概念别把 SYN flood 防护当调优。5.2 连接回收与端口范围tcp_tw_reuse、fin_timeout 和 local_port_range大量短连接的场景TIME_WAIT 状态堆积是常见问题。TIME_WAIT 是主动关闭方进入的等待状态保证迟到的数据包不污染新连接默认等待 60 秒。连接数高时一堆 TIME_WAIT 占满连接表fd 不够用或者源端口耗尽。# TIME_WAIT 快速回收与复用 sysctl -w net.ipv4.tcp_fin_timeout30 sysctl -w net.ipv4.tcp_tw_reuse1tcp_tw_reuse1 允许内核在安全的场景下复用处于 TIME_WAIT 的连接到新的出站连接注意它只对出站连接生效不解决入站连接的问题。tcp_tw_recycle 在老内核里也有类似作用但因为它依赖时间戳且 NAT 环境会出问题新内核已经移除别再沿用老文档里的配置。tcp_fin_timeout 从 60 降到 30能加快 TIME_WAIT 的回收速度但也不能太低低于 RTO 可能影响可靠性。源端口耗尽是个隐蔽问题。系统从 net.ipv4.ip_local_port_range 定义的范围内分配源端口默认 32768 到 60999约 2.8 万个端口。高并发出站连接占满这个区间后新连接报 Cannot assign requested address。# 扩大本地端口范围 sysctl -w net.ipv4.ip_local_port_range1024 65535 sysctl -w net.ipv4.tcp_max_tw_buckets262144端口范围起点降到 1024等于多出一大截可用端口。注意别降到 1024 以下否则和系统保留端口冲突。tcp_max_tw_buckets 控制内核维护的 TIME_WAIT 条目上限超限后多余条目直接释放能在极端情况下保护系统但值设太小会导致重复连接被异常处理。5.3 conntrack连接跟踪表满丢包Linux 的 netfilter 连接跟踪机制为 NAT、防火墙维护一张 conntrack 表每条连接占一个条目。高并发穿透防火墙的业务如果表满新连接会被静默丢弃表现为服务“间歇性抽风”看日志却没有任何应用报错。# 查看当前使用量和上限 sysctl net.netfilter.nf_conntrack_count net.netfilter.nf_conntrack_max # 查日志确认表是否打满 dmesg | grep -i nf_conntrackdmesg 输出 nf_conntrack: table full 时说明表容量不够。调大 nf_conntrack_max 和对应的哈希桶数 nf_conntrack_buckets需要同时调整哈希桶数决定查找效率太小的话 CPU 全耗在表遍历上。# /etc/sysctl.d/99-tuning.conf 追加 net.netfilter.nf_conntrack_max 1048576 net.netfilter.nf_conntrack_buckets 262144每个 conntrack 条目在内核里约占用几百字节内存104 万条约等于占用数百 MB 内存这个账要算清楚。只在网关上做 NAT、转发时才有必要调大普通单机应用拿到这个参数纯粹浪费内存。判断依据是 nf_conntrack_count 接近 max 的百分比超过八成再考虑扩容。另外注意容器环境里 conntrack 表与网络命名空间的关系docker 默认开启 iptables容器进出流量都走 conntrack跑大量短生命周期容器时这个表涨得比想象快。5.4 socket 缓冲与拥塞控制大数据传输调什么吞吐量上不去的场景看 socket 缓冲区和 TCP 窗口。net.core.rmem_max 和 wmem_max 是收发缓冲区的硬上限TCP 自动调优在两者之间动态伸缩范围由 tcp_rmem 和 tcp_wmem 定义。# 大数据传输场景常用 sysctl -w net.core.rmem_max16777216 sysctl -w net.core.wmem_max16777216 sysctl -w net.ipv4.tcp_rmem4096 87380 16777216 sysctl -w net.ipv4.tcp_wmem4096 65536 16777216rmem_max 和 wmem_max 调大给了 TCP 窗口增长的余地配合 BDP 大的链路才能把带宽跑满。tcp_rmem 三个数值分别是最小值、默认值、最大值如果业务需要低延迟而不是高吞吐可以把最大值调小避免单条连接吃掉过多内核内存。net.ipv4.tcp_slow_start_after_idle 默认开启导致空闲后的连接重新进入慢启动吞吐恢复慢。长连接小包业务关掉它sysctl -w net.ipv4.tcp_slow_start_after_idle0这个参数对短连接业务影响极小对长连接传输这类场景收益明显。不过调它之前先确认业务是长连接为主否则只是白改。5.5 压测验证参数改完看哪些指标网络调优后的验证最怕只盯着带宽。我一般按三个层面观测一是连接层的 ss -s 和 netstat -s 计数器看 TIME_WAIT 数量、overflow 计数、reset 计数是否下降二是应用层的 p99 延迟用 wrk 或 ab 在改动前后各跑一轮记录相同并发下的平均延迟和错误率三是内核层的 drop 计数用 nstat 看 TcpExtTCPOverflows 和 TcpExtListenDrops。# 压测前记录基线 nstat -az /tmp/nstat-before.txt # 压测 60 秒例如对本地 Nginx 打 200 并发 wrk -t4 -c200 -d60s http://127.0.0.1:8080/ # 压测后查看计数器差异 nstat -az /tmp/nstat-after.txt diff /tmp/nstat-before.txt /tmp/nstat-after.txt看 diff 里 overflow 和 drop 类计数是否归零。网络调优有个容易误判的地方把 netstat 里的大量 SYN_SENT 或 SYN_RECV 当成队列瓶颈实际可能是对端问题或延迟过高。计数器只是线索最终以压测曲线和业务日志为准。6. 把调优参数固化成基线文档快照、diff 和交付清单调优参数散落在 sysctl 配置、fstab、udev 规则、limits.conf 和 systemd 单元里改完不整理三个月后没人能说清这台机器改过什么。我现在的习惯是把这套东西固化成一份基线文档标题里的 Linux 操作系统调优参数改成 docx 存档每次变更都同步更新内容围绕四个模块内存、文件系统与 I/O、网络、资源限制每个模块记录参数名、类别、修改前值、修改后值、修改理由和回滚方式。# 生成当前生效参数的全量快照 sysctl -a /var/backups/sysctl-$(date %F-%H%M).txt # 配置目录也归档一份 tar czf /var/backups/sysctl-d-$(date %F-%H%M).tgz /etc/sysctl.d /etc/sysctl.conf做变更前先跑这两条命令等于给自己留了后悔药。配置文件层面的回滚是删文件重载运行时层面的回滚是直接把快照里的旧值逐条写回。归档保留 30 天足够更久远的靠版本管理系统。文档模板我按一张表维护列是模块、参数、当前值、建议值、设置理由、回滚方式。表格的每一行对应一次“有据可依的调优”而不是一句“调了更快”。理由栏必须写清楚是解决什么现象比如“inotify watch 数量不足导致配置热加载失败”这样半年后回看文档能判断这条调优是否还有存在的必要。我踩过一个印象深刻的坑之前在一台业务机上用 sysctl -w 改过一批参数没有记录三个月后同样的故障复现我完全不记得改过哪几个值只能把 /proc/sys 快照和默认值逐一对比白白浪费一个下午。后来强制自己在任何调优动作前先打快照、完成后更新基线文档这条纪律比调参的公式本身更值钱。调优参数这件事本质是管理“改动”的过程内核旋钮只是手段有记录、可回滚、能对比才能让 Linux 操作系统调优参数真正变成一项可维护的工程能力而不是服务器上的玄学。希望帮到你。本文还有配套的精品资源点击获取
RELATED READING

延伸阅读

更多一线实战笔记与深度复盘,助您持续精进