
简介一份面向Linux运维及系统管理人员的调优参数速查文档专注解决网络密集型环境下的TCP/IP内核性能问题。文档系统梳理了/proc/sys/net/目录下的关键参数rmem_max与wmem_max分别控制TCP收发缓冲区上限调大后可提升大流量场景吞吐tcp_timestamps用于RTT计算但会占用包头12字节可按需关闭tcp_sack通过选择性确认优化重传tcp_window_scaling支持超过64K的窗口提升高带宽利用率。同时延伸至super-max、acct、ctrl-alt-del等文件系统与内核调优点帮助全面理解Linux调优体系。内容以1个docx文件交付包体仅18KB轻量便携目前已有312人学习下载。文档不仅解释参数含义还给出通过/etc/sysctl.conf写入并执行sysctl -p使配置持久生效的完整示例并提醒调优前进行基准测试与持续监控适合在实际服务器优化时随时查阅。1. 拿到Linux操作系统调优参数文档先想清楚要调哪一层拿到一份《Linux操作系统调优参数》文档最常见的翻车方式就是照着目录往下抄sysctl.conf里塞了上百行重启之后数据库连接池起不来、入口网关直接超时最后还得一行行回退。我在网上翻linux常用命令大全时也见过不少这类清单问题不在参数本身而在于调优参数是内核行为开关每个开关背后对应的是内存、文件系统、网络栈里某个具体机制。不知道自己在调哪一层参数写得越多越危险。这份文档真正有用的部分是告诉你开关在哪、怎么改、怎么验证。它适合刚接手Linux系统、想让性能不再“凭感觉”的新手也适合线上出问题时回头查参数依据的运维。2. 调优参数的三大地盘内存、文件、网络先定位再动手2.1 先分地盘vm_* 管内存、fs_* 管文件、net_* 管连接Linux内核参数有上千个但按前缀就能分出地盘。vm_* 管内存换页、脏页回写和缓存回收fs_* 管文件句柄、目录项缓存、异步IO请求net_* 管TCP/IP协议栈里各个队列、超时和端口分配kernel_* 则是一些全局行为开关比如进程调度、NUMA策略和崩溃转储行为。排障时先判断问题属于哪一块再进入对应前缀的参数里去查效率完全不一样。参数前缀对应子系统典型故障表现高频排查参数vm.*内存管理free有富余但系统卡、频繁换页swappiness、dirty_ratio、dirty_background_ratio、vfs_cache_pressurefs.*文件系统进程报too many open files、文件监听数量超限file-max、inotify.max_user_instances、aio-max-nrnet.*网络协议栈连接建不上、TIME_WAIT堆积、端口耗尽ip_local_port_range、tcp_tw_reuse、somaxconn、tcp_max_syn_backlogkernel.*全局调度行为虚拟机偶发停顿、core dump行为异常numa_balancing、core_pattern举个例子Java服务报Too many open files第一反应不是去查磁盘而是先看ulimit -n进程级限制和fs.file-max系统级上限。如果你连参数该归哪个域都不清楚就只能去搜linux命令大全然后拿别人的一套参数往自己机器上贴。我见过不少机器就是这么被调坏的load average从2调到8最后连SSH都摇摇晃晃。2.2 默认参数为什么保守通用配置不等于匹配负载Linux发行版的默认参数目标是在各种硬件、各种负载下都能跑起来而不是让你的业务跑得最快。默认vm.swappiness60意味着内存压力一上来系统就愿意把一些冷页换到swap去。这里面有合理考量换出冷页可以腾出页缓存给热数据但如果你的机器是台数据库换页造成的延迟抖动就是不可接受的。默认net.core.somaxconn也不大因为普通服务的并发到达率没那么高。这不是内核不行而是它不知道你拿这台机器干什么。调优的本质是把“通用策略”改成“匹配你负载的策略”。所以动手之前先给机器分类定位这台机器是跑数据库还是做Web入口网关还是当桌面开发机用数据库最怕换页和突发刷盘网络服务最怕队列溢出和端口耗尽桌面机最怕莫名其妙的卡顿和掉帧。三类场景要改的参数集合差别很大甚至互相矛盾。网上很多教程喜欢拿一套“参数调优三件套”通吃所有机器我在实际环境里也看到过不少翻车案例参数本身是对的但它只是适合别人的负载。2.3 参数怎么读怎么写/proc/sys、sysctl 与持久化配置内核参数的本质是一个虚拟文件系统。/proc/sys/vm/swappiness这个文件里存着一个整数cat它等价于sysctl vm.swappiness往里写值等价于sysctl -w vm.swappiness10。两条通路操作的是同一个内核状态区别只是sysctl命令帮忙做了语法检查和输入校验。修改方式分两种运行时修改和持久化修改。运行时修改用sysctl -w或者直接写/proc/sys/下的文件立刻生效重启丢失持久化修改需要把配置写进/etc/sysctl.conf或/etc/sysctl.d/下的.conf文件再执行sysctl --system旧发行版是sysctl -p。我的习惯是先在运行时改跑上两天确认没有副作用再落盘到独立的配置文件里。这样哪天出问题把这个文件删掉就能回到改动前的状态等于给自己留了颗后悔药。查看当前值建议用sysctl而不是cat它对不同架构和发行版的路径差异处理得更好。当你在一台刚装的CentOS、Ubuntu或是麒麟这类国产Linux发行版上操作时这套接口几乎完全一致。旧版本里sysctl -a可以列全部参数输出几千行通常要配合grep过滤。如果某个参数名敲sysctl查不到先确认对应的内核模块是否加载尤其是net.netfilter.*这类和防火墙状态相关的参数。参数不存在和参数为0是两回事排查时别混淆。2.4 改参数前先回答三个问题负载类型、瓶颈方向、目标指标第一个问题这台机器现在的负载是什么用top或vmstat看三分钟是CPU跑满、内存换页、磁盘await飘高还是连接数往上顶。负载类型决定你该动哪个参数域。第二个问题瓶颈在哪一层数据库连接慢可能是网络队列入队慢也可能是应用层backlog小还可能是文件句柄不够导致accept失败不定位直接调参等于盲人摸象。第三个问题你改完后拿什么指标验证是连接建立耗时、是TPS、还是页面响应时间。没有目标指标调参就变成了玄学。我也踩过类似的坑。早年间给一台物理机做性能优化没记录基线就改了一批参数业务方说“好像好点了”结果两周后又说“好像又不行了”。没有基线数据回滚都不知道先回哪个最后只能重装系统收场。所以现在养成的习惯是改之前先sysctl -a存快照改完再存一次diff出来看着改了什么产品心里才有底。3. 核心参数逐个落地sysctl 命令、配置文件与必调项3.1 vm.swappiness换页倾向三档值怎么选vm.swappiness取值范围是0到100默认60。值越大内核越倾向于把冷页换到swap来释放内存值越小越倾向于回收页缓存而不是换页。很多人把它理解成“swap使用的百分比”这是个经典误解它只是回收策略的倾向权重。决定效果的是系统内存压力和页缓存质量不是这个数字本身。# 查看当前换页倾向 cat /proc/sys/vm/swappiness # 临时改为10重启失效先跑一两天观察 sysctl -w vm.swappiness10 # 用vmstat观察换页是否仍然频繁间隔2秒采5次 vmstat 2 5vmstat输出里重点看si和so两列分别表示从swap换入和换出的数据量。如果这两列长期非零说明系统确实存在换页压力如果本来就是0那改swappiness对当前瓶颈几乎没用不如把精力放到其他参数上。这也是我经常跟同事说的一句话先让数据告诉你瓶颈在哪而不是直接改参数。三档经验值供参考数据库机器建议改到1到10留少量换页空间兜底桌面开发机建议10到20交互流畅和内存利用率兼顾普通Web服务可以先保持默认60等观察一段时间再决定要不要动。尽量不要设成0原因在下一章的避坑实录里细说。顺带一提新版内核里swappiness0的行为更接近“非常不情愿换页”但老版本里设0在某些场景下反而容易触发OOM不同内核版本行为有差异要查文档确认。3.2 fs.file-max 与 fs.inotify文件句柄和监听上限扩容文件句柄问题的高频报错就两种进程报Too many open files或者某些服务报watch limit reached。前者是句柄数上限不够后者是inotify文件监听数量超了。容器场景和IDE开发机上尤其常见VSCode、日志采集器、Docker都会大量占用inotify实例。# 查看系统级文件句柄使用情况三列分别是已分配、未使用、系统上限 cat /proc/sys/fs/file-nr # 查看当前用户进程级文件句柄上限 ulimit -n # 临时调大系统级上限 sysctl -w fs.file-max2000000 # 临时调大inotify监听上限 sysctl -w fs.inotify.max_user_instances1024 sysctl -w fs.inotify.max_user_watches1048576file-nr的第一列是已分配的文件句柄数第三列是上限已分配长期超过上限的70%就该考虑扩容了。inotify报错时dmesg或者应用日志里会看到ENOSPC: System limit for number of file watchers reached直接把max_user_instances和max_user_watches一起调大就行。注意max_user_watches是按用户统计的多用户共同使用一台开发机时这几个值要按用户数量留足余量。具体调到多大不是拍脑袋。一个简单算法先数一下这台机器上大概会同时打开多少个文件、多少线程然后乘以1.5到2的缓冲系数。默认的fs.file-max通常够普通桌面和轻量服务用跑数据库或者大规模容器集群时再考虑调大。改完后可以用以下命令确认当前实时消耗避免把上限调大后实际没用到还占着内存。# 实时查看当前文件句柄消耗 sysctl fs.file-nr3.3 net.ipv4 的三个高频参数tw 复用、端口范围、监听队列网络参数里误用率最高的就是TIME_WAIT相关的几个。TIME_WAIT是TCP四次挥手后主动关闭方要等待2MSL的状态用来保证旧报文不会污染新连接。高并发短连接场景下TIME_WAIT数量会积压ss -s里可能看到几万个。不少方案说“调小tcp_fin_timeout就行”这是误导tcp_fin_timeout控制的是FIN_WAIT_2的时长不是TIME_WAIT的时长改了影响有限。# 查看当前连接状态分布关注TIME-WAIT和ESTAB的数量 ss -s # 开启TIME_WAIT复用仅对出站连接生效 sysctl -w net.ipv4.tcp_tw_reuse1 # 扩大本地端口范围避免出站连接端口耗尽 sysctl -w net.ipv4.ip_local_port_range1024 65535 # 调大accept队列上限 sysctl -w net.core.somaxconn8192 sysctl -w net.ipv4.tcp_max_syn_backlog8192tcp_tw_reuse的作用是让内核在安全条件下复用处于TIME_WAIT状态的连接特别适合从本机大量发起出站连接的场景比如网关转发、HTTP客户端、gRPC调用方。端口范围决定了本机最多能同时发起多少个出站连接ip_local_port_range默认通常是32768到60999如果并发出站连接接近这个区间上限日志里会看到Cannot assign requested address这时候再把端口范围扩到1024到65535是合理的。somaxconn是accept队列的上限它和应用程序listen时的backlog参数取最小值。换句话说内核一侧somaxconn改到8192但应用listen还写死128那实际队列长度还是128。改内核参数的同时必须把应用到层backlog也一起调整两类参数是一套组合不是二选一。另外提一句tcp_tw_recycle这个参数在新内核里已经被移除了老内核里开启后在多级网关场景下会引发连接超时后面的避坑章节再展开讲。3.4 把参数写入 /etc/sysctl.d从临时验证到落盘成文运行时修改只能算验证手段参数确认有效后要落盘。我习惯在/etc/sysctl.d/下单独建一个99-tuning.conf文件和发行版默认配置分开避免升级系统时被覆盖或产生冲突。文件名数字前缀代表加载顺序99意味着最后加载覆盖前面文件的同名设置。# 创建独立调优配置文件 vim /etc/sysctl.d/99-tuning.conf # 文件内容示例 vm.swappiness 10 fs.file-max 2000000 fs.inotify.max_user_instances 1024 fs.inotify.max_user_watches 1048576 net.core.somaxconn 8192 net.ipv4.tcp_tw_reuse 1 net.ipv4.ip_local_port_range 1024 65535 net.ipv4.tcp_fin_timeout 30 # 加载并应用全部配置 sysctl --system # 确认关键参数已经生效 sysctl vm.swappiness fs.file-max net.core.somaxconn net.ipv4.tcp_tw_reusesysctl --system会按/etc/sysctl.d/目录下的文件名顺序加载配置同时也会处理/etc/sysctl.conf。加载完成后用sysctl逐一确认防止参数名拼错被静默忽略。注意配置文件里的格式是key value等号两边空格与否没严格要求但值类型必须匹配数值参数不能写成字符串否则加载会报错。把配置放到独立文件还有个好处出问题时可以快速对比是哪个文件的哪一行引入的。我在生产环境里遇到过几次“重启后某个参数失效”的情况最后定位到是云平台初始化脚本覆盖了/etc/sysctl.conf但/etc/sysctl.d/下的文件它不动。从此之后自定义参数一律放99-tuning.conf这个习惯帮我省掉了很多重复填坑时间。4. 调优参数避坑实录五个真实问题的现象、原因与修复4.1 swappiness0 之后内存不足时进程被 OOM Killer 杀掉现象一台数据库机器为了“不让它碰swap”管理员把vm.swappiness设成0。运行几天后半夜低峰期数据库进程直接消失dmesg里能看到OOM Killer的击杀记录但当时内存其实还有不少空闲。原因vm.swappiness0并不是“禁用swap”而是让内核回收内存时优先回收文件页缓存。当页缓存被回收得差不多、内存还是不够时系统仍然需要换出匿名页一旦swap空间几乎没有可写的数据或者回收来不及就只能触发OOM Killer找进程开刀。数据库机器上最容易被杀的就是占用内存最多的那个进程也就是数据库本身。解决把swappiness改回1到10之间的值保留少量换页空间作为缓冲。这里真正的阈值不是0而是“低到让匿名页几乎不参与回收”的程度。改完后用vmstat观察si/so两列确认换页量已经压下来即可不用追求绝对的0。4.2 somaxconn 调大了连接还是排队失败现象按教程把net.core.somaxconn改成8192压测时并发一上来客户端还是大量连接超时服务端日志里全是accept队列溢出的记录。原因TCP的accept队列长度取的是应用listen时传入backlog和内核somaxconn两者的较小值。只改内核一侧应用层没配合队列长度一点都没变。比如nginx的listen指令可以显式指定backlogredis有tcp-backlog配置项Tomcat有acceptCount这些应用层参数不改内核改成多大都白搭。解决两层一起改。内核somaxconn和tcp_max_syn_backlog调大同时把应用的backlog也调到一个匹配的值比如redis的tcp-backlog设为511以上nginx的listen加backlog8192。改完用ss -ltn看监听端口的Send-Q和Recv-QSend-Q是配置的队列大小Recv-Q是当前积压量两者接近时说明队列还是不够继续同步调。4.3 sysctl 配置落盘后重启时加载报错导致网络异常现象某台机器在/etc/sysctl.conf里追加了一批参数重启后sysctl服务加载失败部分网络参数没生效SSH连接变得很慢业务端口半天起不来。原因配置文件里写了不存在的参数名或者类型不匹配。sysctl --system在加载时遇到错误参数不会直接失败退出而是跳过后续处理或报错中断导致文件里后面的参数全部没加载。重启后sysctl服务也不会自动帮你排错错误只在启动日志里留一行记录。解决落盘之前先把每一条配置原样复制到命令行用sysctl -w试一遍确认参数存在且类型正确。再执行sysctl --system验证加载无报错最后sysctl按参数名逐一复核。养成这个习惯之后我在配置文件上踩坑的次数几乎降到了零。4.4 tcp_tw_recycle 让多级网关后面的客户端连接全部超时现象为了清理TIME_WAIT在服务器上开启net.ipv4.tcp_tw_recycle1结果部分内网用户反馈连接反复超时抓包看是SYN包发了没人理。原因tcp_tw_recycle依赖TCP时间戳机制来快速回收连接它要求同一源IP的报文时间戳严格递增。在有多级网关、负载均衡转发的情况下不同客户端经过网关后源IP相同但时间戳彼此独立且可能回退内核会把时间戳回退的包当成旧包直接丢弃连接自然建不起来。这个场景的翻车率极高加上新版内核已经把这个参数移除继续使用毫无意义。解决不碰tcp_tw_recycle改用tcp_tw_reuse加合理的连接治理策略。如果担心TIME_WAIT积压过多可以配合调大端口范围、减少不必要的短连接、在应用侧启用连接池来降低TIME_WAIT产生的速度。先用ss -s看实际数量如果TIME_WAIT数量在几万个但内存和连接表现正常就不需要额外干预。4.5 调完参数感觉“变快了”但没人能说清楚哪里快现象某次性能优化后业务方反馈“好像好点了”但问具体哪项指标变好了答不上来一周后性能回落想回滚也不知道该回滚哪条参数。原因调参前没有留存基线调参后没有采集对比指标。多个参数一起改出了问题无法排除是哪一条引入的。参数调优最忌讳的就是“凭感觉改、凭感觉验”今天觉得这个值好就改一下明天觉得那个值妙又动一下最后系统状态完全失控。解决调参前执行sysctl -a /tmp/sysctl.before快照调参后存一份sysctl.after用diff看实际变化。每次只改一个方向的参数组改完用vmstat、iostat、ss -s采集15分钟以上的指标和改动前的基线对比。保存操作记录写明每一条参数为什么改、希望解决什么问题。这样两周后回看每一条改动都有据可查能精确回滚。5. 按负载场景组合参数数据库、Web 入口、桌面机各给一组5.1 数据库机器以“少换页、平稳刷盘”为目标数据库进程对内存延迟高度敏感一次换页就可能让一条慢查询从20毫秒变成200毫秒。而且数据库有自己的Buffer Pool文件页缓存对它的收益有限所以内存回收策略要偏向“少换页”。脏页回写参数也要注意默认的dirty_ratio和dirty_background_ratio比较大脏页积压到一定程度会一次性大量刷盘造成磁盘IO尖峰这在数据库机器上是不能接受的。# 99-db-tuning.conf数据库专用 vm.swappiness 10 vm.dirty_background_ratio 5 vm.dirty_ratio 10 vm.vfs_cache_pressure 50 fs.aio-max-nr 1048576dirty_background_ratio设为5表示脏页达到内存的5%时后台开始异步刷盘dirty_ratio设为10表示脏页达到10%时写进程会被阻塞强制刷盘。这两个值要结合内存大小和磁盘能力看内存大的机器可以适当提高百分比否则频繁触发后台刷盘也会给磁盘增加负担。改完后用iostat -x 1 5观察util和await如果await明显压下来了说明刷盘节奏更平滑了。vfs_cache_pressure设为50让内核更倾向于保留目录项和inode缓存对数据库这种频繁打开文件的场景有收益。fs.aio-max-nr是异步IO请求数的上限MySQL开启native AIO、PostgreSQL使用libaio时要注意这个值是否够用不够的话错误日志会直接提示。5.2 Web 入口/API 网关以“队列够大、端口够用”为目标入口网关是典型的短连接高并发场景连接建立速度直接决定响应延迟。这类机器要关注的不是换页而是TCP连接处理链条上的各个环节accept队列够不够大syn队列能不能扛突刺出站连接会不会把端口耗尽文件句柄够不够用。它自己还要作为客户端去访问下游服务所以出站连接治理同样重要。# 99-web-tuning.conf网关入口专用 net.core.somaxconn 8192 net.ipv4.tcp_max_syn_backlog 8192 net.ipv4.ip_local_port_range 1024 65535 fs.file-max 5000000 fs.inotify.max_user_instances 1024 net.ipv4.tcp_fin_timeout 30ip_local_port_range扩到65535以后本地最多可用的出站端口是6万多个这对绝大多数Web网关足够了。但端口是多内存占用也跟着涨每个socket都有收发缓冲区在并发峰值时这部分内存不可忽略。用ss -s观察TIME-WAIT和ESTAB数量确认端口使用率没有长期超过90%。如果前面还有防火墙或者conntrack模块dmesg里出现nf_conntrack: table full, dropping packet时需要调大net.netfilter.nf_conntrack_max同时可以把net.netfilter.nf_conntrack_tcp_timeout_established从默认的几百秒缩短到几百秒以内让连接状态更快释放。这个参数在容器环境里尤其容易触发注意先确认nf_conntrack模块确实加载了再调整。5.3 桌面/开发机以“减少卡顿、保留缓存”为目标桌面机和服务器最大的差别在于它的负载是突发的、交互式的。打开一个IDE瞬间要读几百个文件切换窗口又可能触发内存回收。默认参数在服务器上没感觉在桌面场景就表现为“用着用着突然卡一下”。这种卡顿多数是页缓存回收和NUMA迁移引起的调整方向是让内核更舍不得丢弃目录项缓存并减少不必要的自动迁移。# 99-desktop-tuning.conf桌面/开发机专用 vm.swappiness 10 vm.vfs_cache_pressure 50 kernel.numa_balancing 0kernel.numa_balancing默认开启时内核会根据访问统计周期性地迁移内存页和进程到更合适的NUMA节点。对桌面机和单路虚拟机来说这种迁移带来的好处微乎其微反而可能造成偶发停顿关掉后体验更平稳。但如果在物理机上跑的是对NUMA拓扑敏感的计算任务比如大规模数据库或多线程压测这个值需要保留默认或单独考虑不能一刀切。桌面发行版上这套参数同样适用包括麒麟、统信UOS这些国产Linux桌面系统参数接口没有差别。桌面机动态调整比较频繁建议也走/etc/sysctl.d/独立文件避免系统更新时被覆盖。改完后用systemd-analyze看开机时间或者正常用两天体感明显顺畅就说明参数方向对了。6. 调优效果的验证方法用对比数据替代“感觉变快了”6.1 留存基线快照用 diff 说话参数调优最怕没有基线。我每次动手前会先把整份内核参数拍个快照保存到带时间戳的文件里改动后再存一份用diff把实际变化的部分拉出来。这条命令已经成了我处理性能问题的固定开场。TS$(date %Y%m%d%H%M) sysctl -a /tmp/sysctl.before.$TS # ... 修改参数 ... sysctl -a /tmp/sysctl.after.$TS diff /tmp/sysctl.before.$TS /tmp/sysctl.after.$TS | grep ^[]diff输出里带号的是改动前值号的是改动后值。这个文件建议保留到变更周期结束和业务指标放在一起形成完整的变更记录。回滚时直接把参数恢复成before文件里的值即可不用去回忆“当时到底改没改过这个参数”。6.2 用参数调优三件套确认瓶颈方向判断瓶颈方向时我一般用参数调优三件套atop、btop和cpufetch。atop擅长录制历史负载数据负载高的时候先录一段事后慢慢回放btop交互直观CPU、内存、磁盘、网络各项一目了然适合快速定位当前瓶颈cpufetch能看到CPU型号和微架构判断参数是否匹配当前硬件特性。# 安装三件套Debian/Ubuntu 系用 aptRHEL 系用 dnf apt install atop btop cpufetch # atop 后台录制10分钟间隔10秒一次 atop -w /tmp/atop.record 30 10 # 回放查看负载情况 atop -r /tmp/atop.record看负载时有个原则先看是不是瓶颈再看瓶颈在哪一层。CPU核心跑满优先查调度和热点磁盘await飘高优先查IO队列和刷盘策略网络连接异常优先查TIME_WAIT、丢包和队列溢出。瓶颈定位错了参数改得再对也白搭。6.3 业务指标才是最终裁判系统指标是过程量业务指标才是结果量。验证调优效果时要挑一个和业务直接挂钩的指标做前后对比接口P99延迟、数据库TPS、网关的每秒新建连接数、压测下的最大并发数。至少采集前后各15分钟数据对比才有参考价值。系统指标好看了、业务指标没变化说明调优方向不对业务指标改善了、系统指标也合理这才是一次完整有效的调优。我现在每次调参前先存基线快照调完记录业务指标变化再定期回头审视哪些参数真正有效。这套习惯帮我避免了很多无效改动也让每一次调优都有据可查而不是靠玄学和手感。希望帮到你。本文还有配套的精品资源点击获取