简介一份面向Linux系统管理员与运维工程师的《Linux操作系统调优参数》文档重点解决网络密集型场景下的TCP/IP性能调优问题。内容围绕/proc/sys/net目录中的核心参数展开rmem_max与wmem_max用于调整TCP收发缓冲区上限避免高负载时丢包tcp_timestamps控制包头时间戳关闭可节省12字节开销tcp_sack开启后允许接收方告知发送方哪些数据已到达减少无效重传tcp_window_scaling让窗口突破64K限制提升高速网络带宽利用率。文档同时指出/proc下的修改重启后失效并对比/etc/sysctl.conf键值写入与/etc/rc.local命令写入两种持久化方法。此外还补充了文件系统超级块数量、进程记账开关、CtrlAltDelete响应策略等内核与文件系统调优项便于形成完整排查思路。压缩包包含1个docx文档整体大小仅18KB结构清晰适合初中级运维人员系统学习。已有312人学习下载每个参数均给出缺省值与调整建议可帮助读者避开常见配置误区提升服务器网络吞吐与稳定性。1. Linux操作系统调优参数到底在调什么默认配置为什么不够用拿到一台新服务器装完系统直接上线大部分场景能跑但扛不住压力。数据库延迟升高、应用频繁超时、网络连接数上不去排到最后往往是内核参数在拖后腿。Linux 默认参数偏向通用性内核会为各种场景取一个平均值而不是为你的业务取最优值。操作系统调优参数就是把这些默认值按业务模型重新设定改的是内核在内存、文件系统、网络栈、进程调度这几个方向上的行为阈值。这篇文章只讲一件事哪些参数值得动、怎么改是对的、改完怎么验证。适合正在做 Linux 运维、应用部署或嵌入式 Linux 项目的人尤其是被线上问题逼着去翻/etc/sysctl.conf却不知道改什么的那个阶段。看完你能照着参数表一条条核对知道每条改下去会有什么后果也知道翻车了怎么恢复。2. 用 sysctl 落地内核调优查询、临时生效与永久生效的完整链路2.1 先看一眼当前参数sysctl 查询与输出解读调优的第一步不是改是先知道当前值。sysctl -a能列出全部内核参数但输出太大实际排查时按模块过滤更高效。查询单个参数用sysctl 参数名查询一类参数用通配符注意通配符要加引号防止被 shell 展开。# 查看单个参数当前值 sysctl vm.swappiness # 查看所有内存相关参数 sysctl -a | grep ^vm\. # 查看所有网络相关参数用引号防止*被shell展开 sysctl -a | grep ^net\. | head -50sysctl vm.swappiness直接输出vm.swappiness 60这个 60 表示内核在回收内存时对匿名内存的偏好程度数值越大越倾向于用 swap越小越倾向于回收文件缓存。grep ^vm\.会把所有 vm 前缀的参数列出来包括vm.dirty_ratio、vm.min_free_kbytes这些后面要重点讲的。看到输出后先记下原始值这是你调优后对比的基线也是改错了要恢复的“后悔药”。2.2 修改参数的三条路径sysctl 命令、/proc 文件与配置文件改内核参数有三条路sysctl -w临时改、直接写/proc/sys/下的对应文件、写入/etc/sysctl.conf永久改。三条路效果一样区别只在生效范围和重启后是否保留。临时改的命令如下# 临时把 swappiness 改成 10立即生效重启后恢复默认 sysctl -w vm.swappiness10 # 等价写法直接写 proc 文件系统 echo 10 /proc/sys/vm/swappiness # 永久生效写入配置文件 echo vm.swappiness 10 /etc/sysctl.conf # 用 -p 重新加载配置文件不需要重启 sysctl -psysctl -w适合线上快速验证改完立刻生效但重启就丢。echo 10 /proc/sys/vm/swappiness是更底层的操作方式sysctl -w内部就是写这个文件两者等价。写入/etc/sysctl.conf后要用sysctl -p重载否则配置要等下次重启才生效。这里有个坑如果你用echo追加配置先确认文件结尾有没有换行符否则新参数可能和旧参数挤在同一行导致语法解析失败。2.3 让参数在重启后仍然生效配置文件语法与加载顺序/etc/sysctl.conf的语法极简一行一个参数格式是参数名 值。#开头是注释。系统启动时systemd-sysctl服务会读取这个文件以及/etc/sysctl.d/目录下的所有.conf文件。加载顺序有优先级后者覆盖前者。# 推荐做法不直接改 /etc/sysctl.conf而是放到独立文件里 cat /etc/sysctl.d/99-custom-tuning.conf EOF vm.swappiness 10 vm.dirty_ratio 20 vm.dirty_background_ratio 5 net.ipv4.ip_local_port_range 1024 65535 EOF # 立即加载所有配置 sysctl --system放到/etc/sysctl.d/下的独立文件有两个好处一是升级系统时不会和发行版的默认配置冲突二是多个参数分文件存放排查时能一眼看出哪组配置是做什么的。文件名前的数字是加载顺序数值小的先加载数值大的后加载一般用99-开头确保最后加载覆盖默认值。sysctl --system按顺序加载所有配置比sysctl -p更彻底。3. 内存与文件系统swap、脏页回写与挂载参数怎么配3.1 swap 与内存水位vm.swappiness 和 vm.min_free_kbytes 的配合swap 调优是内存方向最容易翻车的点。vm.swappiness的默认值 60 对桌面系统合理对数据库服务器和 Java 应用偏高。很多运维上来就直接改成 0认为“禁用 swap 性能最好”结果往往适得其反。改成 0 意味着内核在内存压力下不会主动回收匿名页面当内存耗尽时直接触发 OOM killer把进程杀掉。偏保守的做法是改成 1 到 10让内核在极端情况下有缓冲余地。# 适合数据库/Java 应用的服务器的常见配置 vm.swappiness 10 # 预留足够的内核内存水位 vm.min_free_kbytes 1048576 # 开启内存超量使用策略允许一定程度的内存复用 vm.overcommit_memory 1vm.min_free_kbytes的作用是预留一部分空闲内存给内核自身的中断处理、内存回收等关键路径使用设置过小会导致内核在内存紧张时无法及时回收触发直接 reclaim 造成应用卡顿。这个值建议设为物理内存的 0.5% 到 1%大内存机器取一个下限值就行1GB 的预留对大多数服务器足够。vm.overcommit_memory 1是告诉内核允许 overcommit这个值要看业务场景Redis 的maxmemory设置和 Java 的堆大小如果没控制好开启 overcommit 会加剧 OOM 风险保守的选 0。3.2 脏页回写vm.dirty_ratio 与 vm.dirty_background_ratio 的取舍脏页是内存里被修改但还没写回磁盘的文件数据。内核有两个阈值控制回写时机vm.dirty_background_ratio是后台回写的起点达到这个比例时内核会异步地刷脏页不阻塞应用vm.dirty_ratio是同步回写的起点达到这个比例时发起写入的进程会被阻塞直到脏页降到阈值以下。默认值分别是 10 和 20对普通服务器合理但高并发写入场景需要改。# 高并发写入场景如消息队列、日志采集 vm.dirty_background_ratio 5 vm.dirty_ratio 15 # 大内存机器另一种做法用绝对字节数替代百分比 vm.dirty_background_bytes 1073741824 vm.dirty_bytes 2147483648把dirty_background_ratio调低让内核更早开始后台回写避免脏页积压到dirty_ratio触发同步回写从而减少应用写入延迟抖动。这里的取舍很直接太早回写磁盘 IO 频繁波动太晚回写内存压力大。大内存机器用百分比计算会得到一个很大的阈值比如 256GB 内存的机器dirty_ratio的 20% 是 51GB这意味着脏页要积到 51GB 才触发同步回写明显不合理。这种场景改用dirty_background_bytes和dirty_bytes设一个固定值更可控。3.3 文件系统挂载参数noatime 与 barrier 的顺序问题文件系统层面的调优参数不在 sysctl 里而在/etc/fstab的挂载选项里。最常用的两个是noatime和barrier。noatime关闭文件访问时间更新能显著减少读操作产生的写 IO对大多数服务器都值得开。barrier是日志文件系统保证元数据一致性的机制默认开启某些性能调优指南会建议关掉它但在断电掉电场景下这是拿数据安全换性能线上环境不要关。# /etc/fstab 中的挂载选项示例 # 原配置 UUIDxxxx /data ext4 defaults 0 2 # 加 noatime 的配置 UUIDxxxx /data ext4 defaults,noatime 0 2 # 改完重新挂载不重启系统 mount -o remount /data注意mount -o remount只重新挂载指定挂载点有多个挂载点时不能省略挂载点参数。noatime适合大多数业务但如果你的应用需要读取 atime 来做某些功能比如判断文件是否被读过的备份策略就不能加。还有一个容易忽略的坑nodiratime只关闭目录的 atime 更新noatime会同时关闭文件和目录的二选一的话直接选noatime。4. 网络栈与进程调度TCP 缓冲区、端口范围与 CFS 带宽控制4.1 TCP 读写缓冲区的自动调整net.ipv4.tcp_rmem 与 tcp_wmemTCP 连接的性能瓶颈经常在缓冲区大小上。缓冲区太小会限制单连接吞吐太大会浪费内存。Linux 2.6 以后支持自动调整tcp_rmem和tcp_wmem的三组数字分别表示最小值、默认值、最大值。问题在于默认值在跨地域大带宽链路上偏低需要手动调大。# 适合高带宽、长肥网络的 TCP 缓冲区配置 net.ipv4.tcp_rmem 4096 87380 16777216 net.ipv4.tcp_wmem 4096 65536 16777216 # 关闭自动调优带来的缓冲收缩让大缓冲保持稳定 net.ipv4.tcp_moderate_rcvbuf 0 # 增加 socket 接收队列长度 net.core.rmem_max 16777216 net.core.wmem_max 16777216这里的关键是tcp_rmem的三组值第一组是最小值 4KB第二组是默认值 87380第三组是最大值 16MB。应用通过setsockopt设置 SO_RCVBUF 时内核会在这个区间内做折中。net.core.rmem_max和wmem_max是全局的上限如果只调了tcp_rmem没调net.core.rmem_max那调大后的值会被全局上限截断白改。关闭tcp_moderate_rcvbuf的意思是不要再让内核根据当前链路状况自动收紧接收缓冲这个对吞吐敏感的业务有用代价是内存占用上升。4.2 本地端口耗尽问题net.ipv4.ip_local_port_range 与 TIME_WAIT 复用高并发短连接场景下本地端口耗尽比 CPU 跑满更先到来。每一条 TCP 连接都要占用一个本地端口源端口默认的ip_local_port_range是32768 60999一共只有 28000 多个端口可用。当连接以每秒几千个的速度建立和关闭端口在 TIME_WAIT 状态要等 60 秒才能复用这期间新连接找不到可用端口报错是Cannot assign requested address。# 扩大本地端口范围 net.ipv4.ip_local_port_range 1024 65535 # 允许回收 TIME_WAIT 状态的连接新内核已默认开启 net.ipv4.tcp_tw_reuse 1 # 缩短 TIME_WAIT 时间到 15 秒 net.ipv4.tcp_fin_timeout 15 # 加大全连接队列长度 net.core.somaxconn 4096tcp_tw_reuse只对客户端侧生效它允许内核在分配新连接时复用 TIME_WAIT 状态的端口前提是时间戳字段满足条件即在 RST 之外不会导致历史数据串包。tcp_fin_timeout默认 60 秒调短到 15 秒能加快 TIME_WAIT 回收。这两个配合使用能大幅缓解短连接场景的端口压力但对被动连接的服务端来说TIME_WAIT 复用收益有限更要靠扩大端口范围和调整somaxconn来扛并发。4.3 进程调度CPU 亲和性、nice 值与 CFS 带宽限制CPU 调度参数不是 sysctl 能完全覆盖的涉及sched_setaffinity、nice值和 cgroup 的 CFS 带宽控制。Linux 默认的 CFS 调度器对每个进程尽力而为但线上经常出现某个进程吃满多核 CPU拖累同一宿主上的其他进程。常见做法是用 cgroup 限制进程组的 CPU 使用上限。# 用 cgroup v2 限制进程组 CPU 使用率最多用 2 个核 mkdir /sys/fs/cgroup/limited-app echo 200000 1000000 /sys/fs/cgroup/limited-app/cpu.max echo $PID /sys/fs/cgroup/limited-app/cgroup.procscpu.max文件接受两个数字第一个是 CPU 配额单位是微秒第二个是周期长度单位是微秒。200000 1000000表示在 1 秒周期内最多运行 0.2 秒的 CPU 时间相当于单核的 20%不是两核。要让进程最多用 2 个核应该写2000000 1000000。这个写法比taskset固定 CPU 亲和性更灵活——前者的上限和业务流量挂钩后者只是把进程钉在某个物理核上如果那个核上还有别的进程并不能保证独占。5. 调优参数踩坑指南改错后的现象、原因与恢复方法5.1 把 swappiness 改成 0容器 OOM 反而变频繁了现象某台宿主机跑着十几个 Docker 容器内存 128GB一开始把vm.swappiness从 60 改成 0以为内存不会被 swap 拖慢。结果运行一段时间后容器频繁被 OOM killer 杀掉但宿主机的 swap 几乎没被用过。原因swappiness 0意味着内核在内存压力下不会主动把匿名页面换出到 swap而是优先回收文件缓存。当文件缓存被回收殆尽内存压力仍然存在时内核只能触发 OOM killer 选一个进程杀掉。容器内应用的内存并没有被换出到 swap而是直接被终止了。解决把vm.swappiness调回 1 到 10 之间的值让内核在极端情况下有换出匿名页的余地。血泪经验是swap 不是性能杀手真正的问题在于你的应用是否有持续的内存增长如果应用有内存泄漏swappiness怎么调都救不了先修应用。5.2 调大 tcp_mem 后内核报错或直接翻车现象在 64GB 内存的机器上按网上某篇教程把net.ipv4.tcp_mem的三组值改成了524288 1048576 2097152执行sysctl -p后网络连接大量断开再执行任何网络操作都超时。原因tcp_mem的单位是页page不是字节。在 64 位系统上一页是 4KB2097152页等于 8GB这个值本身没超限但三组值的含义是“低于最小值时内核不主动回收 TCP 内存介于中间值时开始加压回收超过最大值时拒绝分配内存”。改完没检查内存总量TCP 内存的上限把系统内存吃完了。解决先用sysctl net.ipv4.tcp_mem查当前值getconf PAGESIZE确认页大小然后按实际物理内存折算。四舍五入直接设成总内存的 1/4、1/2、3/4换算成页数再写。改完用sysctl -p加载后立即观察free -m和dmesg有没有内存分配失败记录。5.3 修改文件描述符上限后 SSH 登录异常现象为了让高并发应用读取更多连接把fs.file-max改成了 2000000重启后通过网络 SSH 登录服务器登录后执行任何命令都提示Too many open files。原因fs.file-max是全局文件描述符上限但系统启动时 systemd 还会为每个服务设置LimitNOFILESSH 服务的 session 级限制默认是 1024所以登录后打开文件数超过 1024 就报错。全局上限改成 2000000 只影响全局计数会话层面被服务配置卡死了。解决修改/etc/security/limits.conf里的nofile软硬限制同时确认/etc/ssh/sshd_config里有UsePAM yes如果 PAM 没启用limits.conf 的配置不会生效。另外Redis、Nginx 这类常驻进程改完系统级file-max还要在各自配置里调worker_rlimit_nofile或maxclients只改内核参数是不够的。5.4 /etc/sysctl.conf 写错导致内核参数加载失败现象在/etc/sysctl.conf里加了一行net.ipv4.tcp_rmem 4096 87380只写了两个值执行sysctl -p直接报错没用-p的情况下重启后系统网络异常。原因tcp_rmem必须要有三个值少一个内核无法解析报错信息会写明参数名但如果你用echo 追加旧文件和追加的内容在同一个文件里出错时很难定位是哪一行。解决所有参数修改统一放进/etc/sysctl.d/下的独立文件文件名按优先级编号修改后先执行sysctl -p /etc/sysctl.d/99-custom-tuning.conf单独验证确认无误再sysctl --system加载全局。如果已经改错并且重启过进入救援模式或单用户模式删除出错文件再加载备份。6. 用压测验证调优是否真的有效一个带参数的复现流程调优参数改完不是终点要验证改了之后真的有效果而不是只把数值改了图个心安。我的习惯是先采集基线再压测再对比最后用dmesg确认内核没有抱怨。# 1. 采集基线内存、CPU、网络连接数 vmstat 1 10 sar -n TCP 1 10 ss -s # 2. 用 stress-ng 压内存和 CPU stress-ng --vm 4 --vm-bytes 80% --vm-keep --timeout 60s # 3. 用 ab 压短连接测试端口范围调优效果 ab -n 50000 -c 200 -k http://localhost:8080/healthvmstat 1 10每秒采样一次连采 10 次观察si和so两列有没有持续的 swap 换入换出以及cs上下文切换是否异常。sar -n TCP看active/s和passive/s这两个值对应主动连接和被动连接建立速率能直接看出连接建立有没有被卡住。stress-ng --vm 4指用 4 个线程做内存分配压力测试--vm-bytes 80%让每个线程分配 80% 的可用内存这是验证swappiness和 OOM 行为最直接的方式。压测时盯着dmesg如果内核触发过 OOM killer 或内存分配失败会有明确记录。压测验证的一个常用技巧是加长观察窗口。短压 1 分钟往往测不出参数差异我通常会跑 10 分钟以上的压力测试期间用vmstat 1持续写入日志文件压测结束后对比调优前后的system call耗时曲线。曲线有下降说明调优有效曲线反而上升赶紧回滚参数再查原因。参数调优从来不是一次到位的活边界值是在反复压测里试出来的。我自己的习惯是每次调优只动一组参数验证通过再动下一组。多组参数一起改效果好了不知道是谁的功劳坏了不知道是谁的锅回滚都不知道回滚谁。这套流程陪我从单机服务一路走到集群节点希望帮到你按同样的路径安全落地。本文还有配套的精品资源点击获取