Linux 内核参数调整与性能优化

1次阅读

vm.swappiness=0 不禁用 swap,仅降低主动换出倾向;禁用需 swapoff -a 并移除 fstab 中 swap 条目。

Linux 内核参数调整与性能优化

为什么 vm.swappiness 设成 0 并不等于禁用 swap

linux 内核不会因为 vm.swappiness=0 就彻底跳过 swap;它只是大幅降低内核主动换出匿名页的倾向,但 OOM killer 触发前、内存严重不足时,仍可能把部分匿名页写入 swap。真正想禁用 swap,得先关掉所有 swap 分区或文件:swapoff -a,再确保 /etc/fstab 中没有 swap 类型挂载项。

常见错误现象:调了 vm.swappiness=0free -h 仍显示 Swap: 行非零,误以为参数没生效——其实只是 swap 设备还挂着,参数只影响策略,不控制设备启停。

  • vm.swappiness 取值范围是 0–100,0 不代表“关闭”,而是“仅在内存耗尽且无法回收时才考虑 swap”
  • 容器环境(如 docker)中,宿主机的 vm.swappiness 仍会影响容器内进程的换页行为,除非容器启动时显式传了 --memory-swappiness=0
  • 某些云厂商默认启用 swapfile(比如 ubuntu 20.04+ 的 /swap.img),光改 sysctl 不够,必须确认 swap 实际已卸载

net.ipv4.tcp_tw_reuse 在高并发短连接场景下怎么设才安全

这个参数允许 TIME_WAIT 状态的 socket 被快速复用于新的 outbound 连接(前提是时间戳递增),对缓解端口耗尽很有效,但仅适用于客户端角色明确的场景——比如 Web 服务作为上游调用其他 API,而不是被大量外部请求直连的入口服务。

容易踩的坑:在负载均衡后端或反向代理(如 nginx)上盲目开启 net.ipv4.tcp_tw_reuse=1,反而可能因 TIME_WAIT 复用导致新连接收到旧连接残留的 RST 或乱序包,尤其当上游服务重启或网络路径变化时。

  • 必须配合 net.ipv4.tcp_timestamps=1 才能生效(默认开启,但有些嵌入式或定制内核会关)
  • 对 server 端(即监听端口接收连接的一方)无效,tcp_tw_reuse 只作用于 local port 发起的 outbound 连接
  • 若用的是 net.ipv4.tcp_fin_timeout 缩短 TIME_WAIT 持续时间,注意该值不能低于 60 秒,否则违反 TCP RFC,可能引发连接失败

调整 fs.file-max 后为什么 ulimit -n 还是没变

fs.file-max 是系统级最大文件描述符总数,而 ulimit -n 控制的是单个进程的 soft/hard limit,两者完全独立。改了前者,后者默认仍走 shell 启动时继承的值(通常是 1024 或 4096),不自动同步。

典型使用场景:运行 elasticsearchkafka 这类 Java 服务时,常看到 “Too many open files” 错误,查 cat /proc/sys/fs/file-max 发现远大于当前用量,问题其实出在进程自己的 limit 上。

  • 临时生效:启动前在 shell 中执行 ulimit -n 65536,但只对当前 shell 及其子进程有效
  • 永久生效需分两步:改 /etc/security/limits.conf(如 * soft nofile 65536),再确保 PAM 的 pam_limits.so 已启用(检查 /etc/pam.d/common-session
  • systemd 服务还要额外配 LimitNOFILE=65536 在 service 文件里,否则 limits.conf 对它无效

修改内核参数后要不要重启系统

绝大多数 /proc/sys/ 下的参数支持运行时修改,用 sysctl -w 或直接写 /proc/sys/xxx 即可立即生效,无需重启。但有三类例外必须重启或至少重启对应子系统:

  • 涉及内存管理底层结构的,比如 vm.max_map_count 改小后,已存在的大内存映射不会立刻释放,新 mmap 请求才会受控;但若要彻底清理旧状态,需重启相关进程
  • 网络协议初始化参数(如 net.core.somaxconn)在内核启动时读取一次,运行时修改虽能生效,但某些老版本内核(
  • 硬件驱动绑定的参数(如 kernel.numa_balancing)在 NUMA 节点初始化后锁定,运行时开关可能不生效,必须重启

最常被忽略的是:修改 /etc/sysctl.conf 后忘记执行 sysctl -p,或者用了 sysctl --system 却没意识到它会按顺序加载多个配置文件(/etc/sysctl.d/*.conf 优先级高于 /etc/sysctl.conf),结果实际生效的是别的文件里的旧值。

text=ZqhQzanResources