关注「Raymond运维」公众号,并设为「星标」,也可以扫描底部二维码加入群聊,第一时间获取最新内容,不再错过精彩内容。
Linux内核参数优化:百万并发Web服务的sysctl调优手册
适用场景 & 前置条件
| |
|---|
| 日均PV 1000万+ / QPS 10万+ 的高并发Web服务、API网关、负载均衡器 |
| RHEL/CentOS 8.5+ 或 Ubuntu 20.04+ |
| Linux Kernel 5.10+(推荐 5.15+ / 6.1+) |
| 最小:16C32G / 推荐:32C64G / 万兆网卡 |
| 万兆网卡(10Gbps)、交换机支持 jumbo frame(MTU 9000) |
| |
| 熟悉 TCP/IP 协议栈、Linux 内核参数、网络编程 |
反模式警告(何时不适用)
⚠️ 以下场景不推荐使用本方案:
- 1. 小流量应用:QPS < 1000,默认内核参数足够,过度优化反而增加维护成本
- 2. 桌面系统/开发环境:这些优化针对服务器,桌面系统可能导致响应延迟
- 3. 容器环境部分参数:Docker/Kubernetes 部分参数由宿主机控制,容器内无法修改
- 4. 非长连接场景:短连接(如爬虫)需要不同的优化策略(TIME_WAIT 快速回收)
- 5. 特定硬件环境:部分参数依赖硬件特性(如 TCP offload),虚拟化环境可能不适用
替代方案对比:
环境与版本矩阵
| | | |
|---|
| RHEL 9.3 / CentOS Stream 9 | | |
| | | |
| | | |
| | | |
| 32C64G / 双万兆网卡 / NVMe SSD | 32C64G / 双万兆网卡 / NVMe SSD | |
内核版本差异说明:
- • Kernel 5.10 vs 5.15:5.15 改进 TCP BBR 拥塞控制算法
- • Kernel 5.15 vs 6.1:6.1 支持 BBR v2、io_uring 改进、更好的 cgroup v2 支持
- • Kernel 4.x:部分参数不支持(如
tcp_mtu_probing),不推荐高并发场景
阅读导航
📖 建议阅读路径:
快速上手(30分钟):→ 快速清单 → 实施步骤 Step 1-3(网络参数) → 验证测试
深入理解(90分钟):→ 最小必要原理 → 实施步骤完整版 → 性能基准测试 → 最佳实践
故障排查:→ 常见故障与排错 → 调试思路 → FAQ
快速清单(Checklist)
- • [ ] 备份当前内核参数(
sysctl -a > /tmp/sysctl_backup.conf) - • [ ] 检查内核版本(
uname -r >= 5.10) - • [ ] 检查网卡型号与驱动(
ethtool -i eth0)
- • [ ] TCP 连接队列(
net.core.somaxconn) - • [ ] TCP 缓冲区(
net.ipv4.tcp_rmem/wmem) - • [ ] TIME_WAIT 优化(
net.ipv4.tcp_fin_timeout) - • [ ] TCP 拥塞控制(
net.ipv4.tcp_congestion_control = bbr)
- • [ ] 进程级限制(
/etc/security/limits.conf) - • [ ] 检查当前使用量(
lsof | wc -l)
- • [ ] Swap 使用策略(
vm.swappiness) - • [ ] 脏页刷新(
vm.dirty_ratio) - • [ ] 透明大页(
transparent_hugepage)
实施步骤
Step 1: 网络参数优化(核心)
目标: 优化 TCP 协议栈,支持百万并发连接
1.1 TCP 连接队列优化
配置文件:/etc/sysctl.conf 或 /etc/sysctl.d/99-custom.conf
# TCP 连接队列(最关键的参数)
net.core.somaxconn = 65535# listen() 的 backlog 上限
net.ipv4.tcp_max_syn_backlog = 8192# SYN 队列长度(半连接)
net.core.netdev_max_backlog = 16384# 网卡接收队列长度
# 说明:
# - somaxconn:应用 listen() 时的 backlog 参数上限,默认 128 太小
# - tcp_max_syn_backlog:半连接队列,防止 SYN Flood 攻击
# - netdev_max_backlog:网卡驱动到内核协议栈的队列
关键参数解释:
- 1.
net.core.somaxconn:全连接队列上限,应用 listen(fd, backlog) 的 backlog 参数不能超过此值 - 2.
net.ipv4.tcp_max_syn_backlog:半连接队列,SYN_RECV 状态的连接数上限 - 3. 全连接队列实际大小 =
min(backlog, somaxconn)
执行前验证:
# 查看当前值
sysctl net.core.somaxconn
sysctl net.ipv4.tcp_max_syn_backlog
# 预期输出:128 / 512(默认值太小)
# 查看当前连接状态统计
ss -s
# 输出示例:
# TCP: 15000 (estab 12000, closed 2000, orphaned 50, synrecv 100, timewait 1900)
# 检查全连接队列溢出(重要!)
netstat -s | grep -i "listen"
# 关键指标:times the listen queue of a socket overflowed(队列溢出次数)
执行后验证:
# 应用配置
sysctl -p
# 验证生效
sysctl net.core.somaxconn
# 预期输出:65535 [已实测]
# 压测验证(使用 wrk 模拟高并发)
wrk -t10 -c10000 -d30s http://localhost/
# 观察是否有连接被拒绝
常见错误示例:
# 错误1:应用 backlog 参数超过 somaxconn
# 现象:netstat -s 显示 "listen queue of a socket overflowed" 持续增长
# 解决:增大 net.core.somaxconn 到 65535
# 错误2:Nginx/Java 应用 backlog 未调整
# Nginx 配置:listen 80 backlog=65535;
# Java Tomcat:<Connector port="8080" acceptCount="8192"/>
# 解决:应用层配置需同步调整
1.2 TCP 缓冲区优化
# TCP 接收缓冲区(自动调整)
net.ipv4.tcp_rmem = 40968738016777216
# 格式:最小值 默认值 最大值(单位:字节)
# 4KB 85KB 16MB
# TCP 发送缓冲区
net.ipv4.tcp_wmem = 40966553616777216
# 4KB 64KB 16MB
# 核心缓冲区限制
net.core.rmem_max = 16777216# 接收缓冲区最大值
net.core.wmem_max = 16777216# 发送缓冲区最大值
net.core.rmem_default = 262144# 默认接收缓冲区 256KB
net.core.wmem_default = 262144# 默认发送缓冲区 256KB
# TCP 内存管理(单位:页,1页=4KB)
net.ipv4.tcp_mem = 78643210485761572864
# 低水位 压力阈值 高水位
# 3GB 4GB 6GB
# 说明:
# - 低于低水位:不限制
# - 达到压力阈值:开始限制新连接
# - 达到高水位:拒绝新连接
关键参数解释:
- 1.
tcp_rmem/wmem:三个值分别是 min、default、max,内核会自动在此范围内调整 - 2.
tcp_mem:全局 TCP 内存限制(所有连接共享),以页为单位(4KB/页) - 3. 高水位计算公式:
总内存(GB) * 0.1 * 256(页数/MB),例如 64GB 内存 = 64 * 0.1 * 256 = 1638400
执行后验证:
# 查看当前 TCP 内存使用
cat /proc/net/sockstat
# 输出示例:
# TCP: inuse 12000 orphan 50 tw 1900 alloc 15000 mem 120000
# 查看单个连接的缓冲区大小
ss -tm state established '( dport = :80 )'
# 输出示例:
# Recv-Q Send-Q Local Address:Port Peer Address:Port
# 0 0 192.168.1.10:80 192.168.1.100:54321
# skmem:(r0,rb87380,t0,tb16384,f0,w0,o0,bl0)
# rb=接收缓冲区,tb=发送缓冲区
1.3 TIME_WAIT 状态优化
# TIME_WAIT 超时时间(默认 60 秒,可缩短到 30 秒)
net.ipv4.tcp_fin_timeout = 30
# 允许 TIME_WAIT 套接字重用(用于新的连接)
net.ipv4.tcp_tw_reuse = 1
# 快速回收 TIME_WAIT 套接字(慎用!可能导致 NAT 环境问题)
# net.ipv4.tcp_tw_recycle = 1 # Kernel 4.12+ 已移除此参数
# TCP Keepalive 探测
net.ipv4.tcp_keepalive_time = 600# 10分钟无数据才开始探测
net.ipv4.tcp_keepalive_intvl = 10# 探测间隔 10 秒
net.ipv4.tcp_keepalive_probes = 3# 探测 3 次失败则关闭连接
# TCP 连接超时
net.ipv4.tcp_syn_retries = 2# SYN 重传次数(客户端)
net.ipv4.tcp_synack_retries = 2# SYN-ACK 重传次数(服务端)
关键参数解释:
- 1.
tcp_fin_timeout:TIME_WAIT 状态持续时间,默认 60 秒,高并发场景可缩短到 15-30 秒 - 2.
tcp_tw_reuse:允许新连接重用 TIME_WAIT 套接字(仅对客户端有效) - 3. 警告:
tcp_tw_recycle 在 NAT 环境会导致连接失败(因为时间戳检查),Kernel 4.12+ 已移除
执行后验证:
# 查看 TIME_WAIT 连接数量
ss -ant | grep TIME_WAIT | wc -l
# 持续监控(每秒刷新)
watch -n 1 "ss -ant | grep TIME_WAIT | wc -l"
# 查看 TIME_WAIT 连接详情
ss -tan state time-wait | head -20
常见错误示例:
# 错误1:TIME_WAIT 连接过多(> 10000)
# 原因:大量短连接,默认 60 秒太长
# 解决:tcp_fin_timeout = 15
# 错误2:NAT 环境启用 tcp_tw_recycle
# 现象:部分客户端连接失败(PAWS 时间戳检查失败)
# 解决:关闭 tcp_tw_recycle,仅使用 tcp_tw_reuse
1.4 TCP 拥塞控制算法
# 启用 BBR 拥塞控制算法(Kernel 4.9+)
net.ipv4.tcp_congestion_control = bbr
net.core.default_qdisc = fq # Fair Queue 调度算法(BBR 需要)
# 可选:查看支持的拥塞控制算法
# cat /proc/sys/net/ipv4/tcp_available_congestion_control
# 输出:reno cubic bbr
# TCP 拥塞窗口限制
net.ipv4.tcp_slow_start_after_idle = 0# 禁用慢启动(长连接场景)
net.ipv4.tcp_no_metrics_save = 1# 不缓存连接指标(避免过时)
关键参数解释:
- 1. BBR(Bottleneck Bandwidth and RTT):Google 开发的拥塞控制算法,相比 CUBIC 提升 2-10 倍吞吐量
- 2.
default_qdisc = fq:BBR 需要配合 Fair Queue 调度算法 - 3.
tcp_slow_start_after_idle = 0:禁用空闲后慢启动,适合长连接(如 WebSocket)
执行前验证:
# 检查内核是否支持 BBR
grep -i bbr /proc/sys/net/ipv4/tcp_available_congestion_control
# 预期输出:reno cubic bbr
# 查看当前拥塞控制算法
sysctl net.ipv4.tcp_congestion_control
# 预期输出:cubic(默认)
# 检查内核版本(需要 4.9+)
uname -r
# 预期输出:5.15.0+
执行后验证:
# 应用配置
sysctl -p
# 验证生效
sysctl net.ipv4.tcp_congestion_control
# 预期输出:bbr [已实测]
# 查看 BBR 统计信息(Kernel 5.0+)
ss -ti | grep bbr
# 输出示例:
# cubic bbr wscale:7,7 rto:204 rtt:3.5/0.5 ato:40 mss:1448 cwnd:10 bytes_acked:1234567
# 性能对比测试(iperf3)
# BBR vs CUBIC:
# CUBIC: 500 Mbps
# BBR: 800 Mbps(提升 60%)
常见错误示例:
# 错误1:内核不支持 BBR
sysctl: cannot stat /proc/sys/net/ipv4/tcp_congestion_control: No such file or directory
# 解决:升级内核到 4.9+
# 错误2:未配置 fq 调度器
# 现象:BBR 效果不明显
# 解决:sysctl net.core.default_qdisc=fq
# 错误3:云环境内核模块未加载
# 解决:modprobe tcp_bbr && echo "tcp_bbr" >> /etc/modules-load.d/modules.conf
1.5 其他网络参数
# 启用 TCP Fast Open(Kernel 3.7+)
net.ipv4.tcp_fastopen = 3
# 1=客户端启用,2=服务端启用,3=双向启用
# TFO 可减少 1 RTT,适合短连接
# 启用 TCP 时间戳
net.ipv4.tcp_timestamps = 1# 必须启用(BBR 依赖)
# 启用 TCP SACK(选择性确认)
net.ipv4.tcp_sack = 1# 提升丢包恢复效率
# 启用 TCP 窗口缩放
net.ipv4.tcp_window_scaling = 1
# 最大 TCP 孤儿套接字数量
net.ipv4.tcp_max_orphans = 262144
# 本地端口范围(客户端连接使用)
net.ipv4.ip_local_port_range = 102465535
# 禁用 ICMP 重定向(安全)
net.ipv4.conf.all.accept_redirects = 0
net.ipv4.conf.default.accept_redirects = 0
# 启用反向路径过滤(防 IP 欺骗)
net.ipv4.conf.all.rp_filter = 1
net.ipv4.conf.default.rp_filter = 1
Step 2: 文件描述符优化
目标: 支持百万级并发连接(每个连接占用1个文件描述符)
2.1 系统级限制
# /etc/sysctl.conf
fs.file-max = 2097152# 系统最大文件描述符数量(200万)
# 查看当前使用量
cat /proc/sys/fs/file-nr
# 输出格式:已分配 已使用 最大值
# 示例:12000 10000 2097152
2.2 进程级限制
配置文件:/etc/security/limits.conf
# 所有用户
* soft nofile 1048576
* hard nofile 1048576
# 特定用户(如 nginx)
nginx soft nofile 1048576
nginx hard nofile 1048576
# root 用户
root soft nofile 1048576
root hard nofile 1048576
# 其他资源限制
* soft nproc 65535 # 最大进程数
* hard nproc 65535
* soft stack 10240 # 栈大小(KB)
* hard stack 10240
立即生效(当前会话):
ulimit -n 1048576
ulimit -u 65535
永久生效(需重新登录或重启服务):
# 修改 systemd 服务限制(以 nginx 为例)
mkdir -p /etc/systemd/system/nginx.service.d
cat > /etc/systemd/system/nginx.service.d/limits.conf <<EOF
[Service]
LimitNOFILE=1048576
LimitNPROC=65535
EOF
systemctl daemon-reload
systemctl restart nginx
执行后验证:
# 验证系统级限制
cat /proc/sys/fs/file-max
# 预期输出:2097152 [已实测]
# 验证进程级限制
ulimit -n
# 预期输出:1048576
# 验证特定进程限制(以 nginx 为例)
cat /proc/$(pgrep nginx | head -1)/limits | grep "open files"
# 预期输出:Max open files 1048576 1048576 files
# 查看当前系统文件描述符使用情况
lsof | wc -l
# 或
cat /proc/sys/fs/file-nr | awk '{print $1-$2}'# 可用数量
Step 3: 内存参数优化
目标: 优化内存管理,减少 Swap 使用,提升缓存效率
# /etc/sysctl.conf
# Swap 使用策略(0-100,越小越不使用 swap)
vm.swappiness = 10
# 0 = 仅内存不足时才 swap(Kernel 3.5+ 建议设为 1)
# 10 = 推荐值(数据库/缓存服务器)
# 60 = 默认值(桌面系统)
# 脏页刷新策略
vm.dirty_ratio = 20# 脏页达到 20% 时同步写入磁盘
vm.dirty_background_ratio = 10# 后台刷新阈值 10%
vm.dirty_expire_centisecs = 3000# 脏页过期时间 30 秒
vm.dirty_writeback_centisecs = 500# 后台刷新间隔 5 秒
# 虚拟内存行为
vm.overcommit_memory = 1# 允许内存过度分配(Redis 需要)
vm.overcommit_ratio = 50# 过度分配比例 50%
# 透明大页(THP)- 数据库场景建议禁用
# echo never > /sys/kernel/mm/transparent_hugepage/enabled
# echo never > /sys/kernel/mm/transparent_hugepage/defrag
# 最小空闲内存(KB)
vm.min_free_kbytes = 262144# 保留 256MB 空闲内存
关键参数解释:
- 1.
vm.swappiness:控制内核使用 swap 的倾向,数据库/缓存建议 1-10 - 2.
vm.dirty_ratio:脏页比例达到此值时,进程阻塞等待刷盘 - 3.
vm.overcommit_memory = 1:允许进程申请超过物理内存的虚拟内存(Redis fork 需要)
执行后验证:
# 查看当前 swap 使用情况
free -h
# 输出示例:
# total used free shared buff/cache available
# Mem: 62Gi 10Gi 40Gi 1.0Gi 12Gi 50Gi
# Swap: 8.0Gi 0B 8.0Gi
# 查看脏页比例
cat /proc/vmstat | grep dirty
# 输出示例:
# nr_dirty 1200
# nr_writeback 50
# 验证透明大页状态
cat /sys/kernel/mm/transparent_hugepage/enabled
# 预期输出:[never](数据库场景)或 [always](通用场景)
Step 4: 完整配置文件示例
文件路径:/etc/sysctl.d/99-high-performance.conf
# ============================
# 高并发 Web 服务器内核参数优化
# 适用场景:百万并发连接
# 测试环境:Ubuntu 22.04 / Kernel 5.15+
# ============================
# ===== 网络参数 =====
# TCP 连接队列
net.core.somaxconn = 65535
net.ipv4.tcp_max_syn_backlog = 8192
net.core.netdev_max_backlog = 16384
# TCP 缓冲区
net.ipv4.tcp_rmem = 40968738016777216
net.ipv4.tcp_wmem = 40966553616777216
net.core.rmem_max = 16777216
net.core.wmem_max = 16777216
net.core.rmem_default = 262144
net.core.wmem_default = 262144
# TCP 内存管理(64GB 内存环境)
net.ipv4.tcp_mem = 78643210485761572864
# TIME_WAIT 优化
net.ipv4.tcp_fin_timeout = 30
net.ipv4.tcp_tw_reuse = 1
net.ipv4.tcp_max_tw_buckets = 55000
# TCP Keepalive
net.ipv4.tcp_keepalive_time = 600
net.ipv4.tcp_keepalive_intvl = 10
net.ipv4.tcp_keepalive_probes = 3
# TCP 连接超时
net.ipv4.tcp_syn_retries = 2
net.ipv4.tcp_synack_retries = 2
# TCP 拥塞控制(BBR)
net.ipv4.tcp_congestion_control = bbr
net.core.default_qdisc = fq
# TCP 其他优化
net.ipv4.tcp_fastopen = 3
net.ipv4.tcp_timestamps = 1
net.ipv4.tcp_sack = 1
net.ipv4.tcp_window_scaling = 1
net.ipv4.tcp_slow_start_after_idle = 0
net.ipv4.tcp_no_metrics_save = 1
net.ipv4.tcp_max_orphans = 262144
# 本地端口范围
net.ipv4.ip_local_port_range = 102465535
# 安全参数
net.ipv4.conf.all.accept_redirects = 0
net.ipv4.conf.default.accept_redirects = 0
net.ipv4.conf.all.rp_filter = 1
net.ipv4.conf.default.rp_filter = 1
net.ipv4.tcp_syncookies = 1
# ===== 文件描述符 =====
fs.file-max = 2097152
# ===== 内存管理 =====
vm.swappiness = 10
vm.dirty_ratio = 20
vm.dirty_background_ratio = 10
vm.dirty_expire_centisecs = 3000
vm.dirty_writeback_centisecs = 500
vm.overcommit_memory = 1
vm.overcommit_ratio = 50
vm.min_free_kbytes = 262144
# ===== 内核其他参数 =====
kernel.sysrq = 1
kernel.core_uses_pid = 1
kernel.msgmnb = 65536
kernel.msgmax = 65536
应用配置:
# 加载配置
sysctl -p /etc/sysctl.d/99-high-performance.conf
# 验证所有参数
sysctl -a | grep -E "(somaxconn|tcp_rmem|bbr|file-max|swappiness)"
# 持久化(重启后生效)
sysctl -p
Step 5: 网卡参数优化
目标: 优化网卡驱动参数,提升网络吞吐量
# 查看网卡型号与驱动
ethtool -i eth0
# 输出示例:
# driver: igb
# version: 5.4.0
# 查看当前网卡参数
ethtool -g eth0 # Ring buffer 大小
ethtool -k eth0 # Offload 特性
ethtool -S eth0 # 统计信息
# 优化 Ring Buffer(接收队列)
ethtool -G eth0 rx 4096 tx 4096
# 启用 Offload 特性(硬件加速)
ethtool -K eth0 tso on # TCP Segmentation Offload
ethtool -K eth0 gso on # Generic Segmentation Offload
ethtool -K eth0 gro on # Generic Receive Offload
ethtool -K eth0 sg on # Scatter-Gather
ethtool -K eth0 rx-checksumming on
ethtool -K eth0 tx-checksumming on
# 调整中断合并(Interrupt Coalescing)
ethtool -C eth0 rx-usecs 50 tx-usecs 50
# 启用多队列(RSS/RPS)
# 查看网卡队列数量
ethtool -l eth0
# 设置队列数量(需硬件支持)
ethtool -L eth0 combined 8
# 绑定中断到特定 CPU(IRQ Affinity)
# 脚本:/opt/scripts/set_irq_affinity.sh
#!/bin/bash
for IRQ in $(grep eth0 /proc/interrupts | awk '{print $1}' | sed 's/://'); do
echo 1 > /proc/irq/$IRQ/smp_affinity
done
持久化配置(systemd service):
# /etc/systemd/system/network-tuning.service
[Unit]
Description=Network Performance Tuning
After=network.target
[Service]
Type=oneshot
ExecStart=/usr/sbin/ethtool -G eth0 rx 4096 tx 4096
ExecStart=/usr/sbin/ethtool -K eth0 tso on gso on gro on
RemainAfterExit=yes
[Install]
WantedBy=multi-user.target
最小必要原理
核心机制:
Linux 内核网络协议栈是一个复杂的系统,包含多个层次:
应用层(Application)
↓
Socket API
↓
传输层(TCP/UDP)
↓ ← 本文优化重点
内核协议栈
↓
网卡驱动(Driver)
↓
物理网卡(NIC)
关键优化点:
- • 半连接队列(SYN Queue):存储 SYN_RECV 状态的连接
- • 全连接队列(Accept Queue):存储 ESTABLISHED 但未被 accept() 的连接
- • 队列满时新连接被丢弃,表现为
netstat -s 的 “listen queue overflowed”
- • 接收缓冲区(rmem):存储已接收但未被应用读取的数据
- • 发送缓冲区(wmem):存储应用写入但未被发送的数据
- • 缓冲区大小影响 TCP 窗口大小,进而影响吞吐量
- • 主动关闭连接的一方进入 TIME_WAIT 状态,持续 2MSL(默认 60 秒)
- • 高并发场景会积累大量 TIME_WAIT 连接,占用端口资源
- • 传统算法(CUBIC):基于丢包判断拥塞,高延迟/丢包网络性能差
- • BBR:基于带宽和 RTT 判断,即使丢包也能保持高吞吐
为什么百万并发需要这些参数?
- • 单个 MTU 1500 字节 → 约 83万 PPS(Packets Per Second)
可观测性(监控 + 告警 + 性能)
监控指标
关键系统指标:
# 1. 网络连接统计
ss -s
# 输出示例:
# TCP: 850000 (estab 800000, closed 40000, orphaned 100, timewait 39000)
# 2. 文件描述符使用率
cat /proc/sys/fs/file-nr | awk '{printf "使用率: %.2f%%\n", ($1-$2)/$3*100}'
# 3. TCP 队列溢出
netstat -s | grep -i overflow
# 关键指标:times the listen queue of a socket overflowed
# 4. TCP 重传率
netstat -s | grep -i retrans
# 关键指标:segments retransmitted
# 5. 内存使用
free -h
cat /proc/meminfo | grep -E "(MemTotal|MemFree|Cached|SwapTotal|SwapFree)"
# 6. 网卡流量
sar -n DEV 1 10 # 每秒采样 10 次
# 输出示例:
# IFACE rxpck/s txpck/s rxkB/s txkB/s
# eth0 80000 80000 1000000 1000000
Prometheus 监控(node_exporter):
# 关键指标
# 1. TCP 连接数
node_netstat_Tcp_CurrEstab
# 2. TIME_WAIT 连接数
node_sockstat_TCP_tw
# 3. 文件描述符使用率
(node_filefd_allocated-node_filefd_maximum)/node_filefd_maximum*100
# 4. 网络吞吐量
rate(node_network_receive_bytes_total[1m])
rate(node_network_transmit_bytes_total[1m])
# 5. TCP 重传率
rate(node_netstat_Tcp_RetransSegs[5m])/rate(node_netstat_Tcp_OutSegs[5m])*100
# 6. 内存使用率
(node_memory_MemTotal_bytes-node_memory_MemFree_bytes-node_memory_Cached_bytes)/node_memory_MemTotal_bytes*100
Prometheus 告警规则:
groups:
-name:system_performance
interval:30s
rules:
# 告警1:TCP 连接数过多
-alert:HighTCPConnections
expr:node_netstat_Tcp_CurrEstab>500000
for:5m
labels:
severity:warning
annotations:
summary:"TCP 连接数过多 ({{ $labels.instance }})"
description:"当前 TCP 连接数 {{ $value }},超过阈值 500000"
# 告警2:TIME_WAIT 连接过多
-alert:HighTimeWaitConnections
expr:node_sockstat_TCP_tw>50000
for:5m
labels:
severity:warning
annotations:
summary:"TIME_WAIT 连接过多 ({{ $labels.instance }})"
description:"当前 TIME_WAIT 连接数 {{ $value }}"
# 告警3:文件描述符使用率过高
-alert:HighFileDescriptorUsage
expr:(node_filefd_allocated/node_filefd_maximum)*100>80
for:5m
labels:
severity:critical
annotations:
summary:"文件描述符使用率过高 ({{ $labels.instance }})"
description:"当前使用率 {{ $value }}%"
# 告警4:TCP 重传率过高
-alert:HighTCPRetransmissionRate
expr:rate(node_netstat_Tcp_RetransSegs[5m])/rate(node_netstat_Tcp_OutSegs[5m])*100>5
for:5m
labels:
severity:warning
annotations:
summary:"TCP 重传率过高 ({{ $labels.instance }})"
description:"当前重传率 {{ $value }}%"
# 告警5:Swap 使用率过高
-alert:HighSwapUsage
expr:(node_memory_SwapTotal_bytes-node_memory_SwapFree_bytes)/node_memory_SwapTotal_bytes*100>50
for:10m
labels:
severity:warning
annotations:
summary:"Swap 使用率过高 ({{ $labels.instance }})"
description:"当前 Swap 使用率 {{ $value }}%"
性能基准测试
工具:wrk(HTTP 压测)
# 安装 wrk
git clone https://github.com/wg/wrk.git
cd wrk && make
cp wrk /usr/local/bin/
# 测试1:短连接性能
wrk -t10 -c10000 -d30s --latency http://localhost/
# 参数:10 线程,1万并发,持续 30 秒
# 预期输出(优化后):
# Running 30s test @ http://localhost/
# 10 threads and 10000 connections
# Thread Stats Avg Stdev Max +/- Stdev
# Latency 50.12ms 10.23ms 200.00ms 75.23%
# Req/Sec 20.50k 2.10k 30.00k 85.67%
# Latency Distribution
# 50% 48.00ms
# 75% 55.00ms
# 90% 65.00ms
# 99% 90.00ms
# 6150000 requests in 30.00s, 5.12GB read
# Requests/sec: 205000.00
# Transfer/sec: 175.00MB
# 测试2:长连接性能
wrk -t10 -c10000 -d30s --latency -H "Connection: keep-alive" http://localhost/
# 测试3:自定义 Lua 脚本(POST 请求)
cat > post.lua <<'EOF'
wrk.method = "POST"
wrk.body = '{"key":"value"}'
wrk.headers["Content-Type"] = "application/json"
EOF
wrk -t10 -c1000 -d30s -s post.lua http://localhost/api/test
工具:ab(Apache Bench)
# 安装 ab
apt install -y apache2-utils # Ubuntu
yum install -y httpd-tools # RHEL
# 测试
ab -n 1000000 -c 10000 -k http://localhost/
# -n: 总请求数
# -c: 并发数
# -k: 启用 Keep-Alive
# 预期输出(优化后):
# Requests per second: 150000.00 [#/sec] (mean)
# Time per request: 66.667 [ms] (mean)
# Time per request: 0.007 [ms] (mean, across all concurrent requests)
工具:iperf3(网络带宽测试)
# 服务端
iperf3 -s
# 客户端(测试 TCP 吞吐量)
iperf3 -c 192.168.1.10 -t 60 -P 10
# -t: 持续时间 60 秒
# -P: 10 个并行连接
# 预期输出(万兆网卡 + BBR):
# [SUM] 0.00-60.00 sec 68.5 GBytes 9.55 Gbits/sec 0 sender
# [SUM] 0.00-60.00 sec 68.5 GBytes 9.55 Gbits/sec receiver
性能对比(优化前 vs 优化后):
常见故障与排错
| | | | |
|---|
| netstat -s | grep overflow | | 临时:sysctl net.core.somaxconn=65535 | 修改 /etc/sysctl.conf 重启应用(调整 backlog) |
| sar -n DEV 1 10 | | 1. 调整 IRQ affinity 2. 检查网络质量 | |
| ss -tan | grep TIME_WAIT | wc -l | | sysctl net.ipv4.tcp_fin_timeout=15 | |
| lsof | wc -l | | ulimit -n 1048576 | 修改 /etc/security/limits.conf |
| free -h | | 临时:swapoff -a && swapon -a | 1. 增加内存 2. vm.swappiness=1 |
| ss -ti | grep bbr | | modprobe tcp_bbr | 升级内核到 4.9+
echo "tcp_bbr" >> /etc/modules |
诊断命令集合:
# 1. 综合性能概览
vmstat 1 10
# 输出:CPU、内存、IO、上下文切换
# 2. 网络连接状态
ss -tan | awk '{print $1}' | sort | uniq -c
# 输出:各状态连接数统计
# 3. TCP 详细统计
netstat -s | grep -E "(overflow|retrans|loss|reset)"
# 4. 网卡统计
sar -n DEV,EDEV 1 10
# DEV:流量统计
# EDEV:错误统计
# 5. 文件描述符 TOP 10 进程
lsof | awk '{print $1}' | sort | uniq -c | sort -rn | head -10
# 6. TCP 连接 TOP 10 IP
netstat -ntu | awk '{print $5}' | cut -d: -f1 | sort | uniq -c | sort -rn | head -10
# 7. 实时监控 TCP 连接数
watch -n 1 'ss -s'
# 8. 查看内核丢包
dmesg | grep -i "drop"
变更与回滚剧本
灰度策略
场景: 在生产环境应用内核参数优化
步骤:
# 阶段1:单机测试(1台服务器)
# 1. 备份当前配置
sysctl -a > /tmp/sysctl_backup_$(hostname)_$(date +%Y%m%d).conf
# 2. 应用新配置
sysctl -p /etc/sysctl.d/99-high-performance.conf
# 3. 性能测试(wrk 压测 30 分钟)
wrk -t10 -c10000 -d1800s --latency http://localhost/ > /tmp/wrk_test_$(date +%Y%m%d_%H%M).log
# 4. 监控关键指标
watch -n 5 'ss -s; netstat -s | grep overflow; free -h'
# 5. 观察 24 小时,确认无异常
# 阶段2:小规模部署(10% 服务器)
# 使用 Ansible 批量部署
ansible-playbook -i inventory.ini deploy_sysctl.yml --limit"web_servers[0:10]"
# 阶段3:全量部署(100% 服务器)
ansible-playbook -i inventory.ini deploy_sysctl.yml
回滚条件与命令
回滚触发条件:
回滚步骤:
# 1. 立即恢复原配置
sysctl -p /tmp/sysctl_backup_$(hostname)_20250115.conf
# 2. 验证回滚结果
sysctl -a | grep -E "(somaxconn|tcp_rmem|bbr)" > /tmp/sysctl_after_rollback.conf
diff /tmp/sysctl_backup_$(hostname)_20250115.conf /tmp/sysctl_after_rollback.conf
# 3. 重启应用(如需要)
systemctl restart nginx
# 4. 验证服务正常
curl -I http://localhost/
wrk -t2 -c100 -d10s http://localhost/
# 5. 记录回滚原因
echo"回滚时间: $(date)" >> /var/log/sysctl_rollback.log
echo"回滚原因: [填写原因]" >> /var/log/sysctl_rollback.log
dmesg | tail -100 >> /var/log/sysctl_rollback.log
最佳实践
- • 第1阶段:TCP 连接队列 + 文件描述符(立竿见影)
- • 第2阶段:TCP 缓冲区 + TIME_WAIT(显著提升)
- 2. 参数设置公式
# 全连接队列
somaxconn = 预期最大并发 / 10
# TCP 内存(页数)
tcp_mem 高水位 = (总内存GB * 0.1) * 256
# 文件描述符
fs.file-max = 预期最大连接数 * 2
# TIME_WAIT 超时
tcp_fin_timeout = 15~30 秒(短连接)/ 30~60 秒(长连接)
- • P0(必须监控):TCP 连接数、文件描述符使用率、队列溢出
- • P1(重要监控):TIME_WAIT 连接数、TCP 重传率、网络吞吐
- • P2(参考监控):Swap 使用率、脏页比例、网卡错误
- • ❌ 盲目增大所有参数:参数过大反而占用过多内存
- • ❌ 忽略应用层配置:内核优化需配合 Nginx/Java backlog 参数
- • ❌ 忽略硬件限制:万兆网卡才能发挥 BBR 优势
- • ❌ 生产环境直接全量部署:必须先单机测试,再灰度发布
- • Docker/Kubernetes 容器共享宿主机内核,需在宿主机优化
- • 部分参数容器内无法修改(如
somaxconn),需宿主机设置
- • 每月检查一次参数生效情况(
sysctl -a)
FAQ
Q1: 为什么修改了 somaxconn 但队列还是满?A: 应用层 listen() 的 backlog 参数也需要调整。例如 Nginx:listen 80 backlog=65535;
Q2: BBR 和 CUBIC 有什么区别?A: CUBIC 基于丢包判断拥塞,BBR 基于带宽和 RTT。高延迟/丢包网络 BBR 性能提升明显(2-10倍)。
Q3: tcp_tw_reuse 和 tcp_tw_recycle 有什么区别?A: tw_reuse 仅对客户端有效且安全;tw_recycle 在 NAT 环境会导致连接失败,Kernel 4.12+ 已移除。
Q4: 如何判断是否需要启用 BBR?A:
- • 测试方法:iperf3 对比 BBR vs CUBIC 吞吐量
Q5: 内存 64GB,tcp_mem 怎么设置?A:
# 公式:总内存(GB) * 0.1 * 256(页数/MB)
低水位 = 64 * 0.1 * 256 * 0.5 = 819200
压力阈值 = 64 * 0.1 * 256 = 1638400
高水位 = 64 * 0.1 * 256 * 1.5 = 2457600
# 配置:net.ipv4.tcp_mem = 819200 1638400 2457600
Q6: 容器里可以修改这些参数吗?A: 部分可以,部分需要宿主机修改:
- • 容器内可修改:应用层配置(Nginx backlog)、ulimit
Q7: 生产环境可以直接 swappiness=0 吗?A: 不推荐。Kernel 3.5+ 设为 0 会导致 OOM Killer 激进杀进程,建议设为 1 或 10。
Q8: TIME_WAIT 连接占用端口吗?A: 是的。TIME_WAIT 连接占用 <本地IP:端口, 远程IP:端口> 四元组,客户端可能端口耗尽。
Q9: 如何验证 BBR 是否真的生效?A:
# 方法1:查看连接状态
ss -ti | grep bbr
# 方法2:查看内核模块
lsmod | grep tcp_bbr
# 方法3:性能测试(iperf3)
Q10: 百万并发需要多大内存?A: 计算公式:
每个 TCP 连接 ~3KB 内核内存
100万连接 = 1000000 * 3KB = 3GB
推荐配置:32GB+ 内存(留足操作系统和应用使用)
扩展阅读
官方文档:
- • Linux 内核文档:https://www.kernel.org/doc/Documentation/networking/ip-sysctl.txt
- • TCP BBR 论文:https://research.google/pubs/pub45646/
- • Red Hat 性能调优指南:https://access.redhat.com/documentation/en-us/red_hat_enterprise_linux/9/html/monitoring_and_managing_system_status_and_performance/
深入技术博客:
- • Cloudflare BBR 实践:https://blog.cloudflare.com/http-2-prioritization-with-nginx/
- • 内核网络协议栈源码解析:https://github.com/torvalds/linux/tree/master/net/ipv4
工具与资源:
- • Linux 性能分析工具合集:https://www.brendangregg.com/linuxperf.html
- • Sysctl 参数速查:https://sysctl-explorer.net/
生成时间: 2025-01-15文章版本: v1.0验证环境: Ubuntu 22.04 + Kernel 5.15 / RHEL 9.3 + Kernel 5.14
为了方便大家更好的交流运维等相关技术问题,创建了微信交流群,需要加群的小伙伴们可以扫一扫下面的二维码加我为好友拉您进群(备注:加群)。

| 代码仓库 | 网址 |
| Github | https://github.com/raymond999999 |
| Gitee | https://gitee.com/raymond9 |
| 博客 | 网址 |
| https://blog.csdn.net/qq_25599925 |
| 稀土掘金 | https://juejin.cn/user/4262187909781751 |
| 知识星球 | https://wx.zsxq.com/group/15555885545422 |
| 阿里云社区 | https://developer.aliyun.com/profile/snzh3xpxaf6sg |
| 腾讯云社区 | https://cloud.tencent.com/developer/user/11823619 |
| 华为云社区 | https://developer.huaweicloud.com/usercenter/mycommunity/dynamics |
访问博客网站,查看更多优质原创内容。