Linux内核参数调优避坑指南

描述

一、概述

1.1 背景介绍

线上问题一来,很多人第一反应是改 sysctl。连接慢改 somaxconn,内存紧张改 swappiness,磁盘抖动改 dirty_ratio,网卡丢包改各种 net.core.*。参数不是不能改,问题是很多改法只在某个场景下成立,一旦脱离上下文,最容易把局部最优改成全局事故。

这篇文章只讲一个原则:先明确问题在哪一层,再动对应参数。如果还没确认是网络、调度、内存、回写还是连接队列问题,先别碰 sysctl。参数调优最大的坑不是“改了没效果”,而是“短期看起来有效,后面把故障放大了”。

1.2 技术特点

不追求参数大全:只讲生产里最容易被误改、最容易造成副作用的项。

强调适用前提:每个参数都给“什么时候该看、什么时候别动”。

覆盖回滚与验证:参数改前备份、改后验证、异常时如何回退。

1.3 适用场景

场景一:业务刚上线,想做基础内核参数基线。

场景二:线上出现 backlog、swap、回写卡顿、丢包、conntrack 压力,准备做针对性调优。

场景三:团队里经常直接复制网上的 sysctl.conf,需要一份能落地的避坑清单。

1.4 环境要求

组件 版本要求 说明
操作系统 Ubuntu 20.04+ 、Debian 11+、CentOS 7、Rocky Linux 8/9 不同内核参数是否存在会有差异
权限 root 修改 sysctl 需要 root
配套工具 sysstat 、ss、conntrack-tools、ethtool、procps-ng 调优前后需要验证
变更流程 有维护窗口 关键参数别在业务高峰直接改

二、详细步骤

2.1 准备工作

2.1.1 系统检查

 

cat /etc/os-release
uname -r
sysctl -a 2>/dev/null | head -20
ss -s
free -h
vmstat 1 5

 

2.1.2 安装依赖

Ubuntu / Debian:

 

sudo apt update
sudo apt install -y sysstat conntrack ethtool procps iproute2

 

CentOS / Rocky / RHEL:

 

sudo yum install -y sysstat conntrack-tools ethtool procps-ng iproute

 

2.1.3 先备份当前参数

 

sudo mkdir -p /srv/ops/sysctl-backup
sudo sysctl -a 2>/dev/null | sort > /srv/ops/sysctl-backup/sysctl-$(date +%F-%H%M%S).txt
sysctl net.core.somaxconn net.ipv4.tcp_max_syn_backlog vm.swappiness vm.dirty_ratio vm.dirty_background_ratio

 

2.2 核心配置

2.2.1 第一步:先定义生产基线

 

# 文件路径:/etc/sysctl.d/99-prod-baseline.conf
net.core.somaxconn = 4096
net.ipv4.tcp_max_syn_backlog = 4096
net.ipv4.ip_local_port_range = 10240 65000
net.netfilter.nf_conntrack_max = 262144
vm.swappiness = 10
vm.dirty_background_ratio = 5
vm.dirty_ratio = 20
fs.file-max = 2097152
kernel.pid_max = 4194304

 

这些值不是通用真理,只是一个更稳的起点。真正上线前,还得结合连接数、磁盘吞吐、内存大小和业务模型验证。

2.2.2 第二步:准备回滚和验证脚本

 

# 文件路径:prometheus/rules/linux-sysctl-risk.yml
groups:
  - name: linux-sysctl-risk
    rules:
      - alert: NodeConntrackUsageHigh
        expr: node_nf_conntrack_entries / node_nf_conntrack_entries_limit > 0.8
        for: 5m
        labels:
          severity: warning

      - alert: NodeSwapActivityHigh
        expr: rate(node_vmstat_pswpin[5m]) + rate(node_vmstat_pswpout[5m]) > 100
        for: 3m
        labels:
          severity: warning

      - alert: NodeDiskWritebackPressure
        expr: node_memory_Dirty_bytes / node_memory_MemTotal_bytes > 0.1
        for: 5m
        labels:
          severity: warning

 

2.2.3 第三步:按问题类型动参数

网络连接积压时先看:

 

ss -lnt
ss -s
sysctl net.core.somaxconn net.ipv4.tcp_max_syn_backlog

 

内存和 swap 时先看:

 

free -h
vmstat 1 10
sysctl vm.swappiness vm.overcommit_memory

 

磁盘回写时先看:

 

cat /proc/meminfo | egrep 'Dirty|Writeback'
sysctl vm.dirty_ratio vm.dirty_background_ratio

 

2.3 启动和验证

2.3.1 启动服务

 

sudo sysctl --system
sudo systemctl restart systemd-sysctl
sudo systemctl status systemd-sysctl --no-pager

 

2.3.2 功能验证

 

sysctl net.core.somaxconn net.ipv4.tcp_max_syn_backlog vm.swappiness vm.dirty_ratio vm.dirty_background_ratio
ss -s
free -h
cat /proc/meminfo | egrep 'Dirty|Writeback'

 

三、示例代码和配置

3.1 完整配置示例

3.1.1 主配置文件

 

# 文件路径:/etc/sysctl.d/99-prod-baseline.conf
net.core.somaxconn = 4096
net.ipv4.tcp_max_syn_backlog = 4096
net.ipv4.ip_local_port_range = 10240 65000
net.netfilter.nf_conntrack_max = 262144
vm.swappiness = 10
vm.dirty_background_ratio = 5
vm.dirty_ratio = 20
fs.file-max = 2097152

 

3.1.2 辅助脚本

 

#!/usr/bin/env bash
set -euo pipefail

BACKUP_DIR="/srv/ops/sysctl-backup"
mkdir -p "$BACKUP_DIR"

STAMP="$(date +%F-%H%M%S)"
BACKUP_FILE="$BACKUP_DIR/sysctl-$STAMP.txt"
sysctl -a 2>/dev/null | sort > "$BACKUP_FILE"

echo "backup saved to $BACKUP_FILE"
echo "current key values:"
sysctl net.core.somaxconn net.ipv4.tcp_max_syn_backlog net.netfilter.nf_conntrack_max vm.swappiness vm.dirty_ratio vm.dirty_background_ratio

 

3.2 实际应用案例

案例一:把 vm.dirty_ratio 调太高,结果把数据库写抖了

场景描述:为了追求顺序写吞吐,某台数据库主机把 vm.dirty_ratio 从默认值调到 40。峰值时延明显抖动,业务间歇性超时。

实现代码

 

cat /proc/meminfo | egrep 'Dirty|Writeback'
iostat -xz 1 10
sysctl vm.dirty_ratio vm.dirty_background_ratio

 

运行结果

 

Dirty:         7348224 kB
Writeback:      612384 kB

 

脏页堆太多,前台线程被迫参与同步回写,结果 RT 被直接拖高。回滚到:

 

sudo sysctl -w vm.dirty_background_ratio=5
sudo sysctl -w vm.dirty_ratio=20

 

案例二:盲目把 vm.swappiness=1,结果低峰期都回收不动缓存

场景描述:某缓存节点为了“绝不 swap”,一刀切把所有机器都改成 vm.swappiness=1。短期看 swap 下降了,但低峰期页缓存回收变差,磁盘读放大更严重。

实现步骤

看内存和 swap

 

free -h
vmstat 1 10

 

看业务 RT 与 cache

 

cat /proc/meminfo | egrep 'Cached|MemAvailable|Swap'

 

回到更稳的值并观察

 

sudo sysctl -w vm.swappiness=10

 

案例三:盲目调大 nf_conntrack_max,结果内存先被连接跟踪表吃掉

场景描述:某入口层机器连接数暴涨,团队第一反应是把 nf_conntrack_max 从 262144 直接拉到 2097152。连接告警短暂消失,但主机内存持续升高。

实现步骤

看 conntrack 使用率

 

conntrack -S
cat /proc/sys/net/netfilter/nf_conntrack_count
sysctl net.netfilter.nf_conntrack_max

 

看内存和 slab

 

free -h
slabtop -o | head -20

 

对比业务连接模型

 

ss -s

 

运行结果

 

nf_conntrack_count: 1380247
nf_conntrack_max:   2097152

 

根因不是“表太小”,而是短连接和异常重试把连接跟踪表撑大了。直接扩表只是把问题从“连接失败”换成“内存膨胀”。处理动作:

优先治理短连接和异常重试

按峰值连接数重新估算表大小

在合理范围内调大 nf_conntrack_max,不是无限放大

这类参数调整必须把内存成本一起算进去,不然入口没先挂,节点先被拖死。

四、最佳实践和注意事项

4.1 最佳实践

4.1.1 性能优化

优化点一:参数只在有证据时改。somaxconn 不会修复应用 accept 太慢,swappiness 也不会修复内存泄漏。

优化点二:改参数前留快照,改参数后留验证数据,至少保留 ss -s、free -h、iostat、核心 sysctl 输出。

优化点三:基线配置走配置管理,别让每台机器都手工改。

4.1.2 安全加固

安全措施一:生产参数文件落到 /etc/sysctl.d/,用配置管理系统统一发版。

安全措施二:禁止直接复制网络上“万能优化参数大全”。

安全措施三:变更窗口内保留回滚脚本和备份文件。

4.1.3 高可用配置

HA 方案一:参数分层管理,网络基线、内存基线、容器节点基线分开。

HA 方案二:把 sysctl 变更纳入 CMDB 或 Git 仓库审计。

备份策略:每次参数变更前自动导出完整 sysctl -a。

4.2 注意事项

4.2.1 配置注意事项

 警告:老文章里经常出现的 net.ipv4.tcp_tw_recycle 早就不适合现代环境。看到这类配置先删,不要照抄。

 somaxconn 只决定内核层监听队列上限,应用本身 backlog 太小同样会限制住

 nf_conntrack_max 调大前,先算内存成本

 dirty_ratio 调太高,经常会把“吞吐更大”换成“长尾更差”

4.2.2 常见错误

错误现象 原因分析 解决方案
改了 somaxconn 仍然丢连接 应用监听 backlog 没改、accept 太慢 同时看应用参数和 listen queue
调低 swappiness 后内存仍紧张 根因是泄漏或 limit 太小 先查内存根因
调大 nf_conntrack_max 后主机更吃内存 conntrack 表本身占内存 先算表项成本和峰值连接数

4.2.3 兼容性问题

版本兼容:参数在不同内核版本下是否存在、默认值是多少都可能不同。

平台兼容:容器节点、数据库节点、网关节点不适合共用一套激进参数。

组件依赖:应用层 backlog、连接池、线程模型、磁盘基线会直接影响参数效果。

五、故障排查和监控

5.1 故障排查

5.1.1 日志查看

 

sudo journalctl -u systemd-sysctl --since "1 hour ago"
sudo dmesg -T | egrep -i 'conntrack|memory|oom|tcp|nf_'

 

5.1.2 常见问题排查

问题一:SYN backlog 看起来不够,怎么确认

 

ss -lnt
netstat -s | egrep -i 'listen|SYN'
sysctl net.core.somaxconn net.ipv4.tcp_max_syn_backlog

 

解决方案:先看 listen queue 是否真的满,再决定调 somaxconn 和 tcp_max_syn_backlog。

问题二:调完 swappiness 后还是频繁换页

 

free -h
vmstat 1 10
ps -eo pid,cmd,%mem,rss --sort=-rss | head -20

 

解决方案:根因通常是内存不足或泄漏,不是参数本身。

问题三:conntrack 表总满

症状:入口层连接多、NAT 多,偶发建立连接失败

排查

 

conntrack -S
sysctl net.netfilter.nf_conntrack_max
cat /proc/sys/net/netfilter/nf_conntrack_count

 

解决:先优化连接生命周期,再考虑调表大小

5.1.3 调试模式

 

sysctl -a 2>/dev/null | egrep 'somaxconn|swappiness|dirty_ratio|nf_conntrack'

 

5.2 性能监控

5.2.1 关键指标监控

 

ss -s
free -h
cat /proc/meminfo | egrep 'Dirty|Writeback'
conntrack -S

 

5.2.2 监控指标说明

指标名称 正常范围 告警阈值 说明
conntrack 使用率 < 70% > 80%  持续 5m 高了先查连接模型
swap 活跃度 ≈ 0 > 100 pages/s  持续 3m 先查内存根因
脏页比例 < 5% > 10%  持续 5m 写回压力正在积累
listen drop 0 持续增长 监听队列或应用 accept 有问题

5.2.3 监控告警配置

 

groups:
  - name: linux-sysctl-risk
    rules:
      - alert: NodeConntrackUsageHigh
        expr: node_nf_conntrack_entries / node_nf_conntrack_entries_limit > 0.8
        for: 5m
      - alert: NodeSwapActivityHigh
        expr: rate(node_vmstat_pswpin[5m]) + rate(node_vmstat_pswpout[5m]) > 100
        for: 3m
      - alert: NodeDiskWritebackPressure
        expr: node_memory_Dirty_bytes / node_memory_MemTotal_bytes > 0.1
        for: 5m

 

5.3 备份与恢复

5.3.1 备份策略

 

#!/usr/bin/env bash
set -euo pipefail
mkdir -p /srv/ops/sysctl-backup
sysctl -a 2>/dev/null | sort > /srv/ops/sysctl-backup/sysctl-$(date +%F-%H%M%S).txt

 

5.3.2 恢复流程

确认要回滚的版本:ls -1 /srv/ops/sysctl-backup | tail -5

恢复配置文件:sudo cp /srv/ops/sysctl-backup/99-prod-baseline.conf.bak /etc/sysctl.d/99-prod-baseline.conf

重新加载:sudo sysctl --system

验证:sysctl net.core.somaxconn vm.swappiness vm.dirty_ratio

六、总结

6.1 技术要点回顾

 sysctl 不是救火按钮,必须先做问题定性

 dirty_ratio、swappiness、nf_conntrack_max 都有明显副作用

参数要配合业务模型、资源基线和监控一起看

任何变更都要能回滚

6.2 进阶学习方向

Linux 内核网络栈参数

内存回收和写回机制

Kubernetes 节点 sysctl 管理

6.3 参考资料

Linux kernel sysctl 文档 - 内核参数官方说明

Linux proc 文件系统文档 - /proc 观测入口

Prometheus Alerting Rules - 告警规则语法

附录

A. 命令速查表

 

sysctl -a 2>/dev/null | sort                    # 导出当前参数
sysctl net.core.somaxconn vm.swappiness         # 查看关键参数
ss -s                                           # 看连接状态
conntrack -S                                    # 看 conntrack 使用情况
cat /proc/meminfo | egrep 'Dirty|Writeback'     # 看回写压力

 

B. 配置参数详解

net.core.somaxconn:监听 socket backlog 上限

net.ipv4.tcp_max_syn_backlog:半连接队列大小

vm.swappiness:匿名页与页缓存回收倾向

vm.dirty_ratio:前台同步刷脏页触发阈值

C. 术语表

术语 英文 解释
半连接队列 SYN backlog 握手未完成前的等待队列
脏页 Dirty Pages 已修改但尚未写回磁盘的页
连接跟踪 Conntrack Linux 内核连接状态跟踪表
过量提交 Overcommit 内核对内存承诺的分配策略

打开APP阅读更多精彩内容
声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉

全部0条评论

快来发表一下你的评论吧 !

×
20
完善资料,
赚取积分