内核参数调优
总结
- 内存:Redis/ES 设
vm.overcommit_memory=1,数据库设vm.swappiness=10,ES 必调vm.max_map_count - 网络:高并发必调
somaxconn、tcp_max_syn_backlog、tcp_tw_reuse、ip_local_port_range - 文件:高并发必调
fs.file-max和 ulimitnofile - 调优原则:一次改几个、先测试环境、做好备份和监控
1. 怎么查当前参数?
1.1 基本查询
# 查询单个参数
sysctl vm.swappiness
cat /proc/sys/vm/swappiness
# 查看所有内核参数
sysctl -a
# 查看配置文件
cat /etc/sysctl.conf
# 查看当前 ulimit 限制
ulimit -a
ulimit -n # 查看文件描述符限制
1.2 高级查询
# 查询特定类别的参数
sysctl -a | grep "^vm\." # 内存相关
sysctl -a | grep "^net\." # 网络相关
sysctl -a | grep "^fs\." # 文件系统相关
# 查看参数说明
sysctl -d vm.swappiness
2. 内存相关参数
| 参数名 | 参数说明 | 推荐值 | 什么时候调 |
|---|---|---|---|
| vm.overcommit_memory | 0:严格检查,内存不足拒绝分配 1:允许所有内存分配请求 2:允许分配不超过 swap+RAM×overcommit_ratio% |
1 | Redis、Elasticsearch 这类内存密集型应用建议设为 1 |
| vm.swappiness | 0:尽量不用 swap 100:积极用 swap 60:默认值(偏高) |
10 | 数据库、中间件建议 0-10,避免性能抖动 |
| vm.max_map_count | 进程可拥有的内存映射区域数量 | 655360 | Elasticsearch 必须调,默认 65530 不够用 |
| vm.dirty_ratio | 脏页占总内存百分比,达到后阻塞写入 | 10-20 | 默认 20-40 太高,会导致 IO 突发卡顿 |
| vm.dirty_background_ratio | 后台刷盘触发阈值 | 5 | 默认 10,降低可减少 IO 延迟峰值 |
| vm.dirty_expire_centisecs | 脏页存活时间(百分之一秒) | 3000 | 默认 3000(30秒),可适当降低 |
| vm.dirty_writeback_centisecs | 后台刷盘线程唤醒间隔 | 500 | 默认 500(5秒),IO 密集可降低 |
| vm.vfs_cache_pressure | 控制内核回收内存缓存的倾向 | 50-100 | 默认100,降低可保留更多缓存 |
| vm.min_free_kbytes | 系统保留的最小空闲内存(KB) | 物理内存的1-3% | 防止内存不足导致系统卡顿 |
3. 网络相关参数
| 参数名 | 参数说明 | 推荐值 | 什么时候调 |
|---|---|---|---|
| net.core.somaxconn | socket 监听队列最大长度 | 32768 | 高并发服务必调,默认 128 太小 |
| net.ipv4.tcp_max_syn_backlog | SYN 队列长度 | 8192 | 防止 SYN flood,默认 1024 不够 |
| net.core.netdev_max_backlog | 网卡接收队列长度 | 16384 | 高流量场景需调大,默认 1000 |
| net.ipv4.tcp_fin_timeout | FIN_WAIT_2 超时时间(秒) | 30 | 默认 60,缩短可快速回收连接 |
| net.ipv4.tcp_tw_reuse | 允许 TIME_WAIT 复用 | 1 | 高并发必开,加速连接复用 |
| net.ipv4.tcp_keepalive_time | TCP keepalive 探测间隔(秒) | 600 | 默认 7200 太长,建议 10 分钟 |
| net.ipv4.ip_local_port_range | 本地端口范围 | 10000 65535 | 默认范围小,高并发需扩大 |
| net.ipv4.tcp_max_tw_buckets | TIME_WAIT 连接数上限 | 36000 | 防止 TIME_WAIT 太多占资源 |
| net.core.rmem_max | 套接字接收缓冲区最大值 | 134217728 | 高带宽网络需调大 |
| net.core.wmem_max | 套接字发送缓冲区最大值 | 134217728 | 高带宽网络需调大 |
| net.ipv4.tcp_rmem | TCP 接收缓冲区 | 4096 87380 134217728 | 根据网络环境调 |
| net.ipv4.tcp_wmem | TCP 发送缓冲区 | 4096 65536 134217728 | 根据网络环境调 |
| net.ipv4.tcp_slow_start_after_idle | 空闲后是否启用慢启动 | 0 | 设为0可提高长连接性能 |
4. 文件系统相关参数
| 参数名 | 参数说明 | 推荐值 | 什么时候调 |
|---|---|---|---|
| fs.file-max | 系统级最大文件句柄数 | 2097152 | 默认值偏小,高并发必调 |
| fs.inotify.max_user_watches | 用户可监控的文件数量 | 524288 | 开发环境、容器环境常需调大 |
| fs.aio-max-nr | 异步 IO 最大请求数 | 1048576 | 数据库(比如 MySQL)需要较大值 |
| fs.nr_open | 单个进程最大文件句柄数 | 1048576 | 配合 ulimit 用 |
5. 进程相关参数
| 参数名 | 参数说明 | 推荐值 | 什么时候调 |
|---|---|---|---|
| kernel.pid_max | 系统最大进程 ID | 4194304 | 容器环境、高并发场景需调大 |
| kernel.threads-max | 系统最大线程数 | 根据内存调 | 查看 cat /proc/sys/kernel/threads-max |
| kernel.sem | 信号量参数 | 250 32000 32 128 | 数据库应用需调大 |
6. 调度器相关参数
| 参数名 | 参数说明 | 推荐值 | 什么时候调 |
|---|---|---|---|
| kernel.sched_min_granularity_ns | 最小调度粒度 | 10000000 | CPU 密集型应用可适当减小 |
| kernel.sched_latency_ns | 调度延迟 | 18000000 | 交互式应用可适当减小 |
| kernel.sched_wakeup_granularity_ns | 唤醒粒度 | 15000000 | 延迟敏感应用可减小 |
7. ulimit 限制(用户级)
# 查看当前限制
ulimit -a
# 查看具体进程的限制
cat /proc/<PID>/limits
| 参数 | 查询命令 | 说明 | 推荐值 | 在哪配置 |
|---|---|---|---|---|
| nofile | ulimit -n |
单进程最大文件描述符 | 1000000 | /etc/security/limits.conf |
| nproc | ulimit -u |
单用户最大进程数 | 65535 | /etc/security/limits.conf |
| core | ulimit -c |
core dump 文件大小 | unlimited | 调试时开启 |
| memlock | ulimit -l |
最大锁定内存 | unlimited | 数据库应用建议设为 unlimited |
8. 什么时候需要调优?
8.1 系统级检查
# 1. 检查是否出现 "too many open files"
dmesg | grep -i "too many open files"
# 2. 查看当前文件句柄使用情况
cat /proc/sys/fs/file-nr
# 输出:已分配 已使用 最大值
# 3. 查看 TCP 连接状态统计
ss -s
netstat -n | awk '/^tcp/ {++S[$NF]} END {for(a in S) print a, S[a]}'
# 4. 查看 TIME_WAIT 连接数
ss -ant | grep TIME_WAIT | wc -l
# 5. 查看内存和 swap 使用
free -h
vmstat 1 5
# 6. 查看脏页情况
cat /proc/meminfo | grep Dirty
# 7. 查看网络队列丢包
netstat -s | grep -i "listen queue"
cat /proc/net/netstat | grep TcpExt
# 8. 查看系统负载
uptime
cat /proc/loadavg
# 9. 查看 CPU 使用率
top -n 1 | grep "Cpu(s)"
8.2 应用级检查
# 查看特定进程的资源使用
pidstat -p <PID> 1 5
# 查看进程的线程数
ps -eLf | grep <process_name> | wc -l
# 查看进程的内存映射
cat /proc/<PID>/maps | wc -l
# 查看进程的文件描述符使用
ls /proc/<PID>/fd | wc -l
8.3 常见问题信号
碰到这些情况就得调了:
- 文件句柄不够:报 "too many open files" → 调 fs.file-max 和 ulimit
- TIME_WAIT 太多:TIME_WAIT 连接数过万 → 调 tcp_tw_reuse、tcp_fin_timeout
- 频繁 swap:应用老是 swap → 调 vm.swappiness
- Elasticsearch 起不来:调 vm.max_map_count
- 网络连接超时、丢包:调 somaxconn、tcp_max_syn_backlog
- IO 性能抖动:调 vm.dirty_ratio
- 端口用完了:本地端口范围不够 → 调 ip_local_port_range
- 信号量不足:数据库启动失败 → 调 kernel.sem
9. 一键优化脚本
#!/bin/bash
# Linux 内核参数一键优化脚本
# 备份原配置
cp /etc/sysctl.conf /etc/sysctl.conf.bak.$(date +%F_%T)
# 内存优化
cat >> /etc/sysctl.conf << EOF
# 内存管理
vm.overcommit_memory = 1
vm.swappiness = 10
vm.max_map_count = 655360
vm.dirty_ratio = 15
vm.dirty_background_ratio = 5
vm.vfs_cache_pressure = 50
vm.min_free_kbytes = 65536
# 网络优化
net.core.somaxconn = 32768
net.core.netdev_max_backlog = 16384
net.ipv4.tcp_max_syn_backlog = 8192
net.ipv4.tcp_fin_timeout = 30
net.ipv4.tcp_tw_reuse = 1
net.ipv4.tcp_keepalive_time = 600
net.ipv4.ip_local_port_range = 10000 65535
net.ipv4.tcp_max_tw_buckets = 36000
net.core.rmem_max = 134217728
net.core.wmem_max = 134217728
net.ipv4.tcp_rmem = 4096 87380 134217728
net.ipv4.tcp_wmem = 4096 65536 134217728
net.ipv4.tcp_slow_start_after_idle = 0
# 文件系统
fs.file-max = 2097152
fs.inotify.max_user_watches = 524288
fs.aio-max-nr = 1048576
fs.nr_open = 1048576
# 进程和调度
kernel.pid_max = 4194304
kernel.sem = 250 32000 32 128
EOF
# 应用配置
sysctl -p
# ulimit 配置
cat >> /etc/security/limits.conf << EOF
* soft nofile 1000000
* hard nofile 1000000
* soft nproc 65535
* hard nproc 65535
* soft memlock unlimited
* hard memlock unlimited
* soft core unlimited
* hard core unlimited
EOF
# 对于 systemd 服务,还需配置
mkdir -p /etc/systemd/system.conf.d/
cat > /etc/systemd/system.conf.d/limits.conf << EOF
[Manager]
DefaultLimitNOFILE=1000000
DefaultLimitNPROC=65535
EOF
systemctl daemon-reexec
echo "内核参数优化完成,部分配置需重新登录或重启生效"
echo "建议执行 'sysctl -p' 确认配置已生效"
10. 怎么验证配置生效了?
# 验证 sysctl 参数
sysctl vm.swappiness vm.max_map_count net.core.somaxconn
# 验证 ulimit(需重新登录)
ulimit -n
ulimit -u
# 查看进程实际限制
cat /proc/$(pgrep -f your_app)/limits
# 验证特定服务限制
systemctl show <service_name> | grep LimitNOFILE
11. 调优要注意什么?
11.1 基本原则
- 一次别改太多:每次只调几个参数,看看效果再继续
- 做基准测试:调优前后都测一下,看看到底提升了多少
- 盯着监控:建立监控,及时发现调优带来的问题
- 记录下来:把调优过程记下来,方便以后排查问题
11.2 别踩坑
- 先备份:调优前一定要备份原始配置
- 先测试:别直接在生产环境改,先在测试环境试试
- 准备回滚:万一出问题,得能快速回滚
- 看关键指标:盯着 CPU、内存、IO、网络这些指标
11.3 不同场景怎么调?
- 容器环境:要考虑容器资源限制和宿主机参数
- 高并发服务:重点看网络队列、文件句柄、端口范围
- 数据库应用:重点看内存映射、信号量、异步 IO
- 实时系统:重点看调度延迟、中断处理、内存分配