网络栈全景
Linux 内核的网络数据处理路径:
网卡驱动 → SoftIRQ → Netfilter → Socket Buffer → 应用层
│ │
│ └── sk_buff 管理
└── Ring Buffer / NAPI
性能瓶颈可能出现在任何一层。调优的本质就是找到并消除这些瓶颈。
第一层:网卡与 Ring Buffer
查看网卡信息
# 查看网卡型号和驱动
ethtool -i eth0
# 查看 Ring Buffer 大小
ethtool -g eth0
# 查看网卡统计(看是否有丢包)
ethtool -S eth0 | grep -i drop
调整 Ring Buffer
# 增大 Ring Buffer(单位: descriptor 数量)
ethtool -G eth0 rx 4096 tx 4096
# 启用自适应中断
ethtool -C eth0 adaptive-rx on adaptive-tx on
# 查看当前设置
ethtool -c eth0
多队列网卡
# 查看队列数
ethtool -l eth0
# 设置队列数(等于 CPU 核心数)
ethtool -L eth0 combined 4
# 将队列绑定到 CPU
# 中断号通过 /proc/interrupts 查找
echo 2 > /proc/irq/IRQ_NUM/smp_affinity # 绑定到 CPU1
第二层:SoftIRQ 与 NAPI
SoftIRQ 处理网络收包。如果单个 CPU 核心处理不过来,就会成为瓶颈。
监控 SoftIRQ
# 查看 SoftIRQ 分布
cat /proc/softirqs | grep NET_RX
# 查看是否有 CPU 瓶颈
mpstat -P ALL 1
调整 NAPI
# 增加 NAPI 权重(让每个 SoftIRQ 处理更多包)
sysctl -w net.core.netdev_budget=600
sysctl -w net.core.netdev_budget_usecs=8000
第三层:Socket 缓冲区
核心参数
# /etc/sysctl.d/99-network-tuning.conf
# --- 接收缓冲区 ---
# 最小值、默认值、最大值(字节)
net.ipv4.tcp_rmem = 4096 87380 16777216
net.ipv4.udp_rmem_min = 8192
# --- 发送缓冲区 ---
net.ipv4.tcp_wmem = 4096 65536 16777216
net.ipv4.udp_wmem_min = 8192
# --- 全局缓冲区 ---
net.core.rmem_max = 16777216
net.core.wmem_max = 16777216
net.core.rmem_default = 1048576
net.core.wmem_default = 1048576
net.core.optmem_max = 2048
理解自动调优
Linux 内核会根据拥塞窗口自动调整 TCP 缓冲区大小。设置的 min/max 定义了自动调优的范围:
实际缓冲区 = clamp(自动调优值, min, max)
对于高带宽长距离连接(BDP 大),需要更大的缓冲区:
BDP = Bandwidth × RTT
示例: 1Gbps × 100ms = 12.5MB
验证缓冲区使用
# 查看当前连接的缓冲区使用
ss -tm
# ss 输出中的 skmem:(r0,rbX,t0,tbX) 表示接收/发送缓冲区
第四层:TCP 连接管理
连接队列
# SYN 半连接队列
net.ipv4.tcp_max_syn_backlog = 65536
# 已完成连接等待 accept 的队列
net.core.somaxconn = 65536
# 本地端口范围
net.ipv4.ip_local_port_range = 1024 65535
连接回收
# TIME_WAIT 复用
net.ipv4.tcp_tw_reuse = 1
# FIN-WAIT-2 超时(秒)
net.ipv4.tcp_fin_timeout = 15
# Keepalive 参数
net.ipv4.tcp_keepalive_time = 600 # 空闲多久开始探测
net.ipv4.tcp_keepalive_intvl = 15 # 探测间隔
net.ipv4.tcp_keepalive_probes = 5 # 探测次数
SYN Flood 防护
# 启用 SYN Cookie(SYN 队列满时启用)
net.ipv4.tcp_syncookies = 1
# SYN+ACK 重试次数
net.ipv4.tcp_synack_retries = 2
# SYN 重试次数
net.ipv4.tcp_syn_retries = 3
第五层:拥塞控制
BBR 算法
BBR(Bottleneck Bandwidth and Round-trip propagation time)是 Google 开发的拥塞控制算法,基于带宽和延迟建模,而非丢包:
# 设置 BBR 为默认算法
sysctl -w net.core.default_qdisc=fq
sysctl -w net.ipv4.tcp_congestion_control=bbr
# 永久生效
cat >> /etc/sysctl.d/99-network-tuning.conf << EOF
net.core.default_qdisc = fq
net.ipv4.tcp_congestion_control = bbr
EOF
sysctl -p /etc/sysctl.d/99-network-tuning.conf
验证 BBR 是否生效
# 查看当前拥塞控制算法
sysctl net.ipv4.tcp_congestion_control
# 查看 BBR 统计
sysctl net.ipv4.tcp_bbr
# 查看内核支持的算法
sysctl net.ipv4.tcp_available_congestion_control
BBR v2
BBR v2 改善了与基于丢包的算法(如 Cubic)的共存性:
# 如果内核支持 BBR v2
modprobe tcp_bbr2
sysctl -w net.ipv4.tcp_congestion_control=bbr2
第六层:其他优化
TCP Fast Open
允许在 SYN 报文中携带数据,减少一次 RTT:
# 服务端启用 TFO
net.ipv4.tcp_fastopen = 3
# 服务端 TFO 队列长度
net.ipv4.tcp_fastopen_key = random
MTU 发现
# 启用路径 MTU 发现
net.ipv4.ip_no_pmtu_disc = 0
# 查看路径 MTU
ip route get 8.8.8.8
ECN(显式拥塞通知)
# 启用 ECN
net.ipv4.tcp_ecn = 1
监控工具集
# 实时监控连接状态
watch -n1 'ss -ant | awk "{print \$1}" | sort | uniq -c | sort -rn'
# 网络流量监控
iftop -i eth0
# 连接追踪表
conntrack -L -o extended | head -20
# 内核网络统计
nstat -az | grep -i tcp
# 完整的网络栈监控脚本
sar -n DEV 1
调优检查清单
| 参数 | 默认值 | 推荐值 | 说明 |
|---|---|---|---|
tcp_rmem | 4096 131072 | 4096 87380 16777216 | TCP 接收缓冲区 |
tcp_wmem | 4096 16384 | 4096 65536 16777216 | TCP 发送缓冲区 |
somaxconn | 128 | 65536 | 监听队列 |
tcp_max_syn_backlog | 256 | 65536 | SYN 队列 |
tcp_tw_reuse | 0 | 1 | TIME_WAIT 复用 |
tcp_fin_timeout | 60 | 15 | FIN 超时 |
default_qdisc | pfifo_fast | fq | 队列调度 |
congestion_control | cubic | bbr | 拥塞控制 |
总结
网络调优不是堆参数,而是理解每一层的工作机制,根据实际场景做出针对性调整。先监控找到瓶颈,再调优验证效果。