一、概述
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 | |
| | |
| 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
运行结果:
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 常见错误
| | |
|---|
| 应用监听 backlog 没改、accept 太慢 | |
| | |
调大 nf_conntrack_max 后主机更吃内存 | | |
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 表总满
排查:
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 监控指标说明
| | | |
|---|
| < 70% | > 80% | |
| ≈ 0 | > 100 pages/s | |
| < 5% | > 10% | |
| 0 | | |
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 技术要点回顾
- ✅
dirty_ratio、swappiness、nf_conntrack_max 都有明显副作用
6.2 进阶学习方向
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. 术语表