惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

P
Privacy & Cybersecurity Law Blog
OSCHINA 社区最新新闻
OSCHINA 社区最新新闻
D
Docker
V
V2EX
GbyAI
GbyAI
Apple Machine Learning Research
Apple Machine Learning Research
博客园 - Franky
Jina AI
Jina AI
奇客Solidot–传递最新科技情报
奇客Solidot–传递最新科技情报
I
InfoQ
博客园 - 司徒正美
雷峰网
雷峰网
F
Full Disclosure
S
SegmentFault 最新的问题
大猫的无限游戏
大猫的无限游戏
博客园 - 叶小钗
让小产品的独立变现更简单 - ezindie.com
让小产品的独立变现更简单 - ezindie.com
IT之家
IT之家
MongoDB | Blog
MongoDB | Blog
D
DataBreaches.Net
M
MIT News - Artificial intelligence
V
Visual Studio Blog
H
Help Net Security
月光博客
月光博客
博客园 - 三生石上(FineUI控件)
博客园_首页
O
OpenAI News
人人都是产品经理
人人都是产品经理
freeCodeCamp Programming Tutorials: Python, JavaScript, Git & More
Attack and Defense Labs
Attack and Defense Labs
Blog — PlanetScale
Blog — PlanetScale
爱范儿
爱范儿
罗磊的独立博客
P
Palo Alto Networks Blog
Application and Cybersecurity Blog
Application and Cybersecurity Blog
博客园 - 聂微东
Last Week in AI
Last Week in AI
Threat Intelligence Blog | Flashpoint
Threat Intelligence Blog | Flashpoint
L
Lohrmann on Cybersecurity
N
News and Events Feed by Topic
有赞技术团队
有赞技术团队
The Register - Security
The Register - Security
S
Security @ Cisco Blogs
cs.AI updates on arXiv.org
cs.AI updates on arXiv.org
酷 壳 – CoolShell
酷 壳 – CoolShell
AWS News Blog
AWS News Blog
D
Darknet – Hacking Tools, Hacker News & Cyber Security
L
LINUX DO - 最新话题
Hacker News - Newest:
Hacker News - Newest: "LLM"
T
Threat Research - Cisco Blogs

土法炼钢兴趣小组的算法知识备份

国密算法与国密 TLS 系列索引 【系统架构设计】架构质量属性:不只是"高可用高性能" 【系统架构设计百科】告警策略:如何避免"狼来了" 【系统架构设计】CQRS:读写分离的架构哲学 【系统架构设计】空间架构:极端扩展场景的解法 【系统架构设计】微服务架构深度审视:优势、代价与适用边界 【系统架构设计】扩展性原理:水平、垂直与对角扩展 【系统架构设计】无状态设计:扩展的第一步也是最难的一步 【系统架构设计】缓存架构:从本地到分布式的多级缓存体系 【系统架构设计】管道与过滤器:Unix 哲学的架构表达 【系统架构设计】复杂性管理:架构的核心战场 【系统架构设计】消息队列架构:异步解耦的设计与陷阱 【系统架构设计】CDN 架构:全球加速的设计原理 【系统架构设计】连接池设计:被忽视的性能杀手 【系统架构设计】弹性设计模式:熔断器、舱壁与超时 【系统架构设计】高可用设计模式:冗余、故障转移与仲裁 【系统架构设计】容量规划:从拍脑袋到数据驱动 【系统架构设计】数据库扩展:分库分表的工程实践与替代方案 【系统架构设计】SLO 工程:可靠性的量化管理 【系统架构设计】性能建模:用数学思维分析系统瓶颈 【系统架构设计】混沌工程:主动验证系统的韧性 【系统架构设计】零拷贝与内存映射:数据搬运的极致优化 【系统架构设计】线程模型:从 thread-per-request 到协程 【系统架构设计】容灾架构:多活与灾备设计 【系统架构设计】数据库性能模式:索引、查询与连接管理 【系统架构设计】数据建模:从关系范式到文档模型的真实权衡 【系统架构设计】吞吐量优化:批处理、流水线与并发模型 【系统架构设计】流处理架构:从批处理到实时的范式迁移 【系统架构设计】搜索引擎架构:倒排索引之上的系统设计 【系统架构设计】时序数据架构:监控与 IoT 的存储设计 【系统架构设计】数据迁移与版本化:在线不停机的数据演进 【系统架构设计】数据湖与数据仓库:分析架构的演进路线 【系统架构设计】API 网关设计:入口层的职责边界 【系统架构设计】应用层数据一致性模式:在正确性与性能之间走钢丝 【系统架构设计】多模数据库选型:Polyglot Persistence 的工程实践 【系统架构设计】服务发现与注册:动态拓扑的基础设施 【系统架构设计】配置管理架构:从配置文件到配置中心 【系统架构设计】全链路压测:大规模系统的性能验证 【系统架构设计】幂等性设计:分布式环境下的安全重试 【系统架构设计】契约测试与 Schema 演进:服务间的信任协议 【系统架构设计】长连接与推送架构:WebSocket、SSE 与 MQTT 【系统架构设计】延迟分析:从 P50 到 P999 的全链路追踪 【系统架构设计百科】DDD 战术模式:聚合、实体与值对象 【系统架构设计百科】防腐层与开放主机服务:系统集成的 DDD 方案 【系统架构设计百科】领域事件与事件风暴:从业务到架构的桥梁 【系统架构设计百科】CQRS + Event Sourcing 完整实战:从领域建模到部署 【系统架构设计百科】DDD 与微服务:用领域模型划分服务边界 【系统架构设计】DDD 战略设计:限界上下文与上下文映射 【系统架构设计百科】认证架构:从 Session 到 JWT 到 OIDC 【系统架构设计】API 设计哲学:REST vs GraphQL vs gRPC 的真实权衡 排序算法专题:从 TimSort 到并行排序 【密码学百科】国密算法体系:SM2/SM3/SM4/SM9 全景解读 【密码学百科】承诺方案:Pedersen 承诺、向量承诺与多项式承诺 【密码学百科】不经意传输与隐私信息检索:OT、OT 扩展与 PIR 【密码学百科】门限密码学:门限签名、门限解密与分布式密钥生成 完美哈希:从理论到 gperf 实践 【密码学百科】安全多方计算:从 Yao 的混淆电路到实用 MPC 【密码学百科】同态加密:从 Paillier 到全同态加密(FHE) 【密码学百科】零知识证明系统:zk-SNARKs、zk-STARKs 与 Bulletproofs 【密码学百科】概率论与密码分析:生日攻击、差分分析与线性分析 【密码学百科】计算复杂性与归约:密码安全性证明的基石 【密码学百科】秘密共享:Shamir 方案、VSS 与安全多方计算入口 【密码学百科】椭圆曲线代数:Weierstrass 方程、点群运算与曲线选择 【密码学百科】离散对数与配对密码学:从 DLP 到 BLS 签名 【密码学百科】格密码数学基础:SVP、LWE 与格基约化 【密码学百科】抽象代数:群、环、域的密码学视角 【密码学百科】有限域算术:GF(2^n) 运算与在 AES/ECC 中的应用 【密码学百科】数论进阶:二次剩余、椭圆曲线上的 Weil 配对 【密码学百科】密码学简史:从凯撒密码到量子时代 【密码学百科】威胁模型与安全目标:CIA 三要素之外 【密码学百科】Kerckhoffs 原则与现代密码设计哲学 【密码学百科】随机性:密码学的基石 【密码学百科】信息论入门:熵、完美保密与 Shannon 定理 【密码学百科】分组密码原理:Feistel 网络与 SPN 结构 【密码学百科】AES 逐步拆解:SubBytes 到 MixColumns 的数学 【密码学百科】分组密码工作模式全览:ECB/CBC/CTR/OFB/CFB 【密码学百科】流密码:RC4 的兴衰与 ChaCha20 的崛起 【密码学百科】密码学哈希函数:MD5→SHA-2→SHA-3 的进化之路 【密码学百科】MAC 与 HMAC:消息认证的正确姿势 【密码学百科】认证加密(AEAD):GCM、ChaCha20-Poly1305 与 OCB 【密码学百科】密钥派生函数:HKDF、PBKDF2、Argon2 与密码存储 【密码学百科】公钥密码的数论基础:模运算、群、原根 【密码学百科】RSA 从原理到攻击:教科书 RSA 为什么不安全 【密码学百科】Diffie-Hellman 密钥交换与离散对数问题 【密码学百科】椭圆曲线密码学(ECC):从几何直觉到点群运算 【密码学百科】数字签名:ECDSA、EdDSA 与 Schnorr 签名 【密码学百科】现代密钥交换:X25519、ECDHE 与前向保密 【密码学百科】混合加密与 KEM/DEM 范式:ECIES 与 HPKE 【密码学百科】填充方案:PKCS#1 v1.5、OAEP 与 PSS 【密码学百科】TLS 协议全解析:从握手到 0-RTT 【密码学百科】PKI 与数字证书:信任链的构建与崩塌 【密码学百科】密码认证协议:从 SRP 到 OPAQUE 【密码学百科】零知识证明入门:如何证明你知道而不泄露 【密码学百科】安全信道构造:Noise 协议框架与 Signal 协议 【密码学百科】密钥管理工程:HSM、KMS 与密钥生命周期 【密码学百科】侧信道攻击:从时序攻击到功耗分析 【密码学百科】密码学实现陷阱:三层漏洞分类、审计工具链与系统性预防 密码敏捷性:如何设计可升级的密码系统 【密码学百科】OpenSSL/BoringSSL 架构剖析:ENGINE、Provider 与 FIPS 模块 排序基准测试:用数据说话
【Linux 网络子系统深度拆解】内核网络调优方法论:从基准测试到生产验证
2025-07-25 · via 土法炼钢兴趣小组的算法知识备份

网络调优是一门需要方法论支撑的工程实践。盲目修改 sysctl 参数不仅可能无效,还可能引入新问题——例如,增大 TCP 接收缓冲区可能缓解吞吐不足,却在高并发场景下耗尽内存触发 OOM。本文建立一套系统化的调优框架:先用基准测试建立性能基线,再通过可观测工具定位瓶颈层次,然后针对性地调整参数,最后通过 A/B 对比验证效果。每个 sysctl 参数都会对应到内核源码中的数据结构,让你理解”为什么这样调”。

Linux 内核网络调优方法论

一、调优方法论框架

1.1 调优的四个阶段

阶段一:基线测量
    ↓ 建立当前性能数据(吞吐、延迟、丢包率、CPU 使用率)
阶段二:瓶颈定位
    ↓ 通过可观测工具确定瓶颈在哪一层
阶段三:参数调整
    ↓ 针对瓶颈层次修改相应参数
阶段四:效果验证
    → 对比调优前后的性能数据,确认改善且无副作用

1.2 性能瓶颈的层次模型

网络性能瓶颈按从底层到上层可分为:

层次 瓶颈表现 诊断方法 调优手段
硬件/驱动 ring buffer 溢出、中断不均衡 ethtool -S/proc/interrupts ring buffer 大小、RSS、中断亲和
软中断 softirq 延迟、CPU 跑满 mpstat、bpftrace softirq NAPI budget、RPS/RFS、CPU 隔离
IP/路由 路由查找慢、分片超时 perf topip route 路由缓存、ECMP、PMTU
TCP/UDP 重传率高、窗口受限 ss -tinstat TCP 缓冲区、拥塞控制、TFO
Socket 接收缓冲区满、backlog 溢出 ss -lntpnstat SO_RCVBUFsomaxconnbacklog
应用 系统调用频繁、epoll 效率低 straceperf record io_uringSO_BUSY_POLL、批处理

1.3 调优原则

  1. 一次只改一个参数:否则无法判断哪个改动产生了效果
  2. 测量驱动,不猜测:每次调整前后都要有量化数据
  3. 理解副作用:增大缓冲区会增加内存消耗,增大 backlog 会增加延迟
  4. 区分场景:吞吐优化和延迟优化的方向往往相反
  5. 记录每次变更:包括参数值、测量数据、内核版本

二、基准测试工具与方法

2.1 iperf3:吞吐量基准

# 服务端
iperf3 -s

# TCP 吞吐测试(10 秒,8 并行流)
iperf3 -c <server> -t 10 -P 8

# UDP 吞吐测试(指定带宽)
iperf3 -c <server> -u -b 10G -t 10

# 反向测试(服务端发送)
iperf3 -c <server> -R -t 10

# 关键指标:Bandwidth、Retr(重传次数)、Cwnd

2.2 netperf:延迟基准

# 安装
apt install netperf

# TCP 请求/响应延迟(RR = Request/Response)
netperf -H <server> -t TCP_RR -l 30 -- -r 1,1

# TCP 流延迟(CRR = Connect/Request/Response,含建连)
netperf -H <server> -t TCP_CRR -l 30

# UDP 请求/响应延迟
netperf -H <server> -t UDP_RR -l 30

# 关键指标:Transaction Rate(次/秒)、延迟 = 1/Rate

2.3 基线数据收集脚本

#!/bin/bash
# baseline.sh - 收集网络性能基线数据
OUTDIR="baseline-$(date +%Y%m%d-%H%M%S)"
mkdir -p "$OUTDIR"

# 系统信息
uname -r > "$OUTDIR/kernel.txt"
cat /proc/cpuinfo | grep 'model name' | head -1 >> "$OUTDIR/kernel.txt"
nproc >> "$OUTDIR/kernel.txt"
numactl -H > "$OUTDIR/numa.txt" 2>/dev/null

# 网卡信息
for dev in $(ls /sys/class/net/ | grep -v lo); do
    ethtool -i "$dev" > "$OUTDIR/ethtool-$dev.txt" 2>/dev/null
    ethtool -g "$dev" >> "$OUTDIR/ethtool-$dev.txt" 2>/dev/null
    ethtool -l "$dev" >> "$OUTDIR/ethtool-$dev.txt" 2>/dev/null
    ethtool -c "$dev" >> "$OUTDIR/ethtool-$dev.txt" 2>/dev/null
done

# 当前 sysctl
sysctl -a 2>/dev/null | grep -E '^net\.(core|ipv4)\.' > "$OUTDIR/sysctl.txt"

# 中断分布
cat /proc/interrupts > "$OUTDIR/interrupts.txt"

# TCP/UDP 统计快照
nstat -az > "$OUTDIR/nstat.txt"

echo "基线数据已保存到 $OUTDIR/"

2.4 环境隔离要点

  • 关闭超线程干扰:调优测试时用 isolcpus 隔离测试核
  • 固定 CPU 频率cpupower frequency-set -g performance 避免变频干扰
  • 网络隔离:使用专用网段,避免背景流量
  • 多次测试取中位数:至少 5 次,取 P50 作为基准

三、硬件与驱动层调优

3.1 Ring Buffer 大小

网卡的 ring buffer 决定了驱动可以暂存多少待处理的包。当 CPU 处理不过来时,新包会因 ring buffer 满而被丢弃(ethtool -S 中的 rx_missed_errors)。

# 查看当前和最大 ring buffer 大小
ethtool -g eth0
# Ring parameters for eth0:
# Pre-set maximums:
# RX:     4096
# Current hardware settings:
# RX:     256

# 增大 ring buffer
ethtool -G eth0 rx 4096 tx 4096

内核对应struct net_deviceethtool_ops->get_ringparam / set_ringparam

副作用:ring buffer 越大,包在 buffer 中等待的时间越长,尾延迟会增加。吞吐场景适合增大,延迟敏感场景需要权衡。

3.2 中断合并(Interrupt Coalescing)

中断合并控制网卡累积多少包或等待多长时间后才触发一次中断:

# 查看当前中断合并参数
ethtool -c eth0

# 调整(微秒)
ethtool -C eth0 rx-usecs 50 rx-frames 64

# 自适应模式(推荐作为起点)
ethtool -C eth0 adaptive-rx on adaptive-tx on

内核对应struct ethtool_coalesceinclude/linux/ethtool.h)。

权衡

参数方向 效果 适合场景
增大 rx-usecs 减少中断次数,提高吞吐 批量数据传输
减小 rx-usecs 降低中断延迟 延迟敏感(交易系统)
adaptive-rx on 自动根据负载调整 通用场景

RSS(Receive Side Scaling)将不同的流分配到不同的网卡队列和 CPU 核心:

# 查看网卡队列数
ethtool -l eth0

# 设置队列数(通常等于 CPU 核心数)
ethtool -L eth0 combined 16

# 查看 RSS hash 配置
ethtool -x eth0

# 设置 RSS hash key 和 indirection table
ethtool -X eth0 equal 16

# 手动设置中断亲和(将队列 N 的中断绑定到 CPU N)
for i in $(seq 0 15); do
    IRQ=$(grep "eth0-$i" /proc/interrupts | awk '{print $1}' | tr -d ':')
    [ -n "$IRQ" ] && echo $i > /proc/irq/$IRQ/smp_affinity_list
done

内核对应

  • struct net_devicenum_rx_queues / num_tx_queues
  • RSS hash 通过 netdev_rss_key 和 indirection table 实现
  • 中断亲和通过 irq_set_affinity_hint() 设置

最佳实践:使用 irqbalance 服务自动平衡,或在延迟敏感场景手动绑定,配合 isolcpus 避免业务线程与中断处理竞争同一个核心。

3.4 NUMA 拓扑感知

在多 NUMA 节点的服务器上,网卡通常连接到特定的 NUMA 节点:

# 查看网卡所在的 NUMA 节点
cat /sys/class/net/eth0/device/numa_node

# 查看 NUMA 拓扑
numactl -H

# 将应用绑定到网卡所在的 NUMA 节点
numactl --cpunodebind=0 --membind=0 ./my_server

原则:让处理网络包的 CPU 和应用进程都在网卡所在的 NUMA 节点上,避免跨 NUMA 内存访问。跨 NUMA 访问的延迟惩罚通常在 40-100 ns,高频场景下累积影响显著。

四、软中断与 NAPI 调优

4.1 NAPI Budget

NAPI 的 budget 参数控制每次 poll 调用最多处理多少个包:

# 查看当前值
sysctl net.core.netdev_budget          # 默认 300
sysctl net.core.netdev_budget_usecs    # 默认 2000(微秒)

# 增大(高吞吐场景)
sysctl -w net.core.netdev_budget=600
sysctl -w net.core.netdev_budget_usecs=4000

内核对应include/linux/netdevice.h):

#define NAPI_POLL_WEIGHT 64    /* 单个 NAPI 实例每次 poll 的默认 weight */

netdev_budget 是一次 net_rx_action() 软中断中所有 NAPI 实例总共可处理的包数。netdev_budget_usecs 是时间上限。

副作用:budget 越大,单次软中断占用 CPU 越久,可能影响其他任务的调度延迟。

4.2 RPS/RFS

当网卡硬件队列数少于 CPU 核心数时,软件 RPS(Receive Packet Steering)可以将包分发到多个 CPU:

# 启用 RPS(将 CPU 0-7 作为处理核心)
echo ff > /sys/class/net/eth0/queues/rx-0/rps_cpus

# RFS 流表大小
echo 32768 > /proc/sys/net/core/rps_sock_flow_entries
echo 4096 > /sys/class/net/eth0/queues/rx-0/rps_flow_cnt

何时使用 RPS

  • 网卡硬件队列数少于 CPU 核心数
  • 无法使用 RSS 的虚拟网卡(如 virtio 只有 1 个队列)
  • 需要将中断处理和协议栈处理分到不同的 CPU

何时不使用 RPS

  • 网卡已有足够的硬件队列且 RSS 工作正常
  • RPS 引入的 IPI(Inter-Processor Interrupt)开销大于收益

4.3 backlog 队列

netdev_max_backlog 控制每个 CPU 的 input_pkt_queue 最大长度:

# 查看当前值
sysctl net.core.netdev_max_backlog    # 默认 1000

# 高包率场景(如 10 Gbps DNS 服务器)
sysctl -w net.core.netdev_max_backlog=5000

内核对应include/linux/netdevice.h):

extern int netdev_max_backlog;    /* per-CPU backlog 队列上限 */

超过此限制的包会被丢弃,drop_reasonCPU_BACKLOG

4.4 Busy Polling

对于延迟敏感的应用,busy polling 让应用在 socket 读取时直接轮询网卡,跳过中断和软中断:

# 全局启用
sysctl -w net.core.busy_read=50       # 轮询 50 微秒
sysctl -w net.core.busy_poll=50       # select/poll/epoll 轮询 50 微秒

# 或应用层设置
# setsockopt(fd, SOL_SOCKET, SO_BUSY_POLL, &timeout, sizeof(timeout));

副作用:busy polling 会持续消耗 CPU,适合延迟优先、CPU 资源充裕的场景。

五、TCP 参数调优

5.1 缓冲区参数

TCP 缓冲区是影响吞吐量的核心参数,对应内核中 struct netns_ipv4sysctl_tcp_rmem[3]sysctl_tcp_wmem[3]

# TCP 接收缓冲区 [最小值, 默认值, 最大值](字节)
sysctl net.ipv4.tcp_rmem
# 默认:4096 131072 6291456

# TCP 发送缓冲区
sysctl net.ipv4.tcp_wmem
# 默认:4096 16384 4194304

# 高带宽长延迟(BDP 优化)
# BDP = 带宽 × RTT = 10Gbps × 10ms = 12.5 MB
sysctl -w net.ipv4.tcp_rmem="4096 131072 16777216"
sysctl -w net.ipv4.tcp_wmem="4096 65536 16777216"

# 全局 socket 缓冲区上限
sysctl -w net.core.rmem_max=16777216
sysctl -w net.core.wmem_max=16777216

内核对应include/net/netns/ipv4.h:59,73):

int sysctl_tcp_wmem[3];    /* TX 热路径,[min, default, max] */
int sysctl_tcp_rmem[3];    /* RX 热路径,[min, default, max] */

自动调优:当 net.ipv4.tcp_moderate_rcvbuf=1(默认开启)时,内核会根据连接的实际 BDP 自动调整接收缓冲区大小,最大不超过 tcp_rmem[2]

5.2 连接管理参数

# SYN 队列长度(半连接队列)
sysctl -w net.ipv4.tcp_max_syn_backlog=8192

# Accept 队列长度上限
sysctl -w net.core.somaxconn=65535
# 注意:实际 backlog = min(somaxconn, listen() 的 backlog 参数)

# SYN Cookie(防 SYN Flood)
sysctl -w net.ipv4.tcp_syncookies=1    # 默认已开启

# TIME_WAIT 复用
sysctl -w net.ipv4.tcp_tw_reuse=1

# FIN 超时(加速 FIN_WAIT_2 回收)
sysctl -w net.ipv4.tcp_fin_timeout=15  # 默认 60

内核对应include/net/netns/ipv4.h):

sysctl 内核字段 默认值
tcp_max_syn_backlog sysctl_max_syn_backlog 128(低配)/ 1024(高配)
somaxconn netns_core.sysctl_somaxconn 4096
tcp_tw_reuse sysctl_tcp_tw_reuse 2(仅 loopback)
tcp_fin_timeout sysctl_tcp_fin_timeout 60
tcp_syncookies sysctl_tcp_syncookies 1

5.3 拥塞控制

# 查看可用的拥塞控制算法
sysctl net.ipv4.tcp_available_congestion_control

# 查看/设置当前算法
sysctl net.ipv4.tcp_congestion_control=bbr

# 加载 BBR 模块
modprobe tcp_bbr

# BBR 需要 fq qdisc 配合
tc qdisc replace dev eth0 root fq

内核对应include/net/netns/ipv4.h:200):

const struct tcp_congestion_ops __rcu *tcp_congestion_control;

算法选择指南

算法 特点 适合场景
cubic 基于丢包,Linux 默认 低延迟、低丢包网络
bbr 基于带宽和 RTT 模型 高延迟、有随机丢包的广域网
bbr2 BBR 改进,更公平 与 cubic 共存的场景
dctcp 基于 ECN 标记 数据中心内部

5.4 TCP Fast Open

# 启用 TFO(客户端+服务端)
sysctl -w net.ipv4.tcp_fastopen=3
# 0=禁用, 1=客户端, 2=服务端, 3=两者

# 应用层需配合 TCP_FASTOPEN socket option

内核对应include/net/netns/ipv4.h:199):

int sysctl_tcp_fastopen;

5.5 Keepalive 参数

# 空闲多久开始发送 keepalive 探测
sysctl -w net.ipv4.tcp_keepalive_time=600     # 默认 7200 秒

# 探测间隔
sysctl -w net.ipv4.tcp_keepalive_intvl=30     # 默认 75 秒

# 探测次数(超过后断开)
sysctl -w net.ipv4.tcp_keepalive_probes=5     # 默认 9

内核对应include/net/netns/ipv4.h:153-155):

int sysctl_tcp_keepalive_time;
int sysctl_tcp_keepalive_intvl;
u8 sysctl_tcp_keepalive_probes;

六、UDP 与通用 Socket 调优

6.1 UDP 缓冲区

# UDP 接收/发送缓冲区最小值
sysctl net.ipv4.udp_rmem_min    # 默认 4096
sysctl net.ipv4.udp_wmem_min    # 默认 4096

# 通过全局 socket 缓冲区上限控制
sysctl -w net.core.rmem_default=262144
sysctl -w net.core.rmem_max=16777216
sysctl -w net.core.wmem_default=262144
sysctl -w net.core.wmem_max=16777216

内核对应include/net/netns/ipv4.h:213-214):

int sysctl_udp_wmem_min;
int sysctl_udp_rmem_min;

6.2 optmem_max

optmem_max 控制每个 socket 辅助缓冲区(如 cmsg、socket filter)的最大大小:

sysctl -w net.core.optmem_max=81920    # 默认 20480

内核对应include/net/netns/core.h:16):

int sysctl_optmem_max;

在使用 recvmmsg() 或大量 socket option 时可能需要增大。

七、qdisc 调优

7.1 默认 qdisc 选择

# 查看当前默认 qdisc
sysctl net.core.default_qdisc

# 高吞吐场景
sysctl -w net.core.default_qdisc=fq_codel

# 配合 BBR 使用
sysctl -w net.core.default_qdisc=fq

# 查看当前 qdisc 状态
tc -s qdisc show dev eth0

7.2 fq_codel 参数

fq_codel 结合了公平队列和受控延迟,是大多数场景的最佳选择:

# 查看 fq_codel 参数
tc qdisc show dev eth0

# 自定义配置
tc qdisc replace dev eth0 root fq_codel \
    limit 10240 \       # 队列总包数上限
    target 5ms \        # 目标延迟
    interval 100ms \    # 测量窗口
    ecn                 # 启用 ECN 标记

7.3 txqueuelen

txqueuelen 是网络设备的默认发送队列长度:

# 查看当前值
ip link show eth0 | grep qlen

# 增大(高吞吐场景)
ip link set dev eth0 txqueuelen 10000

八、内存管理调优

8.1 TCP 内存限制

TCP 全局内存由三级限制控制:

# TCP 全局内存限制 [低水位, 压力水位, 高水位](页面数)
sysctl net.ipv4.tcp_mem
# 默认根据系统内存自动计算

# 示例:128 GB 内存服务器
sysctl -w net.ipv4.tcp_mem="786432 1048576 1572864"
# 低水位 = 3 GB, 压力水位 = 4 GB, 高水位 = 6 GB

三级含义

  • 低水位以下:TCP 正常分配内存
  • 低水位~压力水位:TCP 进入”内存压力”状态,sk_under_memory_pressure() 返回 true,开始限制缓冲区增长
  • 压力水位以上:TCP 拒绝新的内存分配,可能丢弃 OFO 队列中的包

8.2 UDP 内存限制

sysctl net.ipv4.udp_mem
# 同样是 [低水位, 压力水位, 高水位](页面数)

8.3 socket 级内存

# 单个 socket 接收/发送缓冲区
# 受 net.core.rmem_max 和 net.core.wmem_max 限制
# 应用层通过 setsockopt(SO_RCVBUF/SO_SNDBUF) 设置
# 或通过 setsockopt(SO_RCVBUFFORCE/SO_SNDBUFFORCE) 突破限制(需 CAP_NET_ADMIN)

内核对应include/net/sock.h:415,431):

int sk_rcvbuf;    /* 接收缓冲区大小(字节) */
int sk_sndbuf;    /* 发送缓冲区大小(字节) */

九、场景化调优配置

9.1 高吞吐场景(大文件传输、流媒体)

# 增大缓冲区
sysctl -w net.ipv4.tcp_rmem="4096 524288 16777216"
sysctl -w net.ipv4.tcp_wmem="4096 524288 16777216"
sysctl -w net.core.rmem_max=16777216
sysctl -w net.core.wmem_max=16777216

# 使用 BBR + fq
sysctl -w net.ipv4.tcp_congestion_control=bbr
sysctl -w net.core.default_qdisc=fq

# 增大 ring buffer 和队列
ethtool -G eth0 rx 4096 tx 4096
ip link set dev eth0 txqueuelen 10000

# 启用 TSO/GSO
ethtool -K eth0 tso on gso on gro on

# NAPI budget
sysctl -w net.core.netdev_budget=600

9.2 低延迟场景(交易系统、游戏服务器)

# 小缓冲区减少队列延迟
sysctl -w net.ipv4.tcp_rmem="4096 65536 4194304"
sysctl -w net.ipv4.tcp_wmem="4096 65536 4194304"

# Busy polling
sysctl -w net.core.busy_read=50
sysctl -w net.core.busy_poll=50

# 禁用 Nagle 算法(应用层设置 TCP_NODELAY)
# 减小中断合并延迟
ethtool -C eth0 rx-usecs 0 tx-usecs 0

# 小 ring buffer 减少排队
ethtool -G eth0 rx 512

# CPU 隔离 + 手动中断绑定
# 将网卡中断绑定到特定核心,应用绑定到相邻核心

9.3 高并发短连接(Web 服务器、API 网关)

# 增大连接队列
sysctl -w net.core.somaxconn=65535
sysctl -w net.ipv4.tcp_max_syn_backlog=65535

# 加速 TIME_WAIT 回收
sysctl -w net.ipv4.tcp_tw_reuse=1
sysctl -w net.ipv4.tcp_fin_timeout=15

# 扩大端口范围
sysctl -w net.ipv4.ip_local_port_range="1024 65535"

# 启用 TFO
sysctl -w net.ipv4.tcp_fastopen=3

# SYN Cookie
sysctl -w net.ipv4.tcp_syncookies=1

# 减少 SYN/SYNACK 重试次数
sysctl -w net.ipv4.tcp_syn_retries=2
sysctl -w net.ipv4.tcp_synack_retries=2

9.4 数据中心内部(East-West 流量)

# DCTCP 拥塞控制
modprobe tcp_dctcp
sysctl -w net.ipv4.tcp_congestion_control=dctcp
sysctl -w net.ipv4.tcp_ecn=1

# fq_codel + ECN
tc qdisc replace dev eth0 root fq_codel ecn

# 关闭慢启动重启
sysctl -w net.ipv4.tcp_slow_start_after_idle=0

# 早期解复用
sysctl -w net.ipv4.tcp_early_demux=1
sysctl -w net.ipv4.udp_early_demux=1

十、调优验证与生产部署

10.1 A/B 对比方法

# 步骤一:基线测量
./baseline.sh
iperf3 -c server -t 60 -P 8 -J > baseline-iperf.json
netperf -H server -t TCP_RR -l 60 > baseline-rr.txt

# 步骤二:应用调优参数
sysctl -p /etc/sysctl.d/90-network-tuning.conf

# 步骤三:调优后测量
./baseline.sh
iperf3 -c server -t 60 -P 8 -J > tuned-iperf.json
netperf -H server -t TCP_RR -l 60 > tuned-rr.txt

# 步骤四:对比
# 吞吐变化、延迟变化、重传率变化、CPU 使用率变化

10.2 持久化配置

# 创建 sysctl 配置文件
cat > /etc/sysctl.d/90-network-tuning.conf << 'EOF'
# TCP 缓冲区
net.ipv4.tcp_rmem = 4096 524288 16777216
net.ipv4.tcp_wmem = 4096 524288 16777216
net.core.rmem_max = 16777216
net.core.wmem_max = 16777216

# 连接管理
net.core.somaxconn = 65535
net.ipv4.tcp_max_syn_backlog = 65535
net.ipv4.tcp_tw_reuse = 1
net.ipv4.tcp_fin_timeout = 15

# 拥塞控制
net.ipv4.tcp_congestion_control = bbr
net.core.default_qdisc = fq

# 端口范围
net.ipv4.ip_local_port_range = 1024 65535
EOF

# 应用
sysctl -p /etc/sysctl.d/90-network-tuning.conf

10.3 监控告警

调优后需要持续监控关键指标:

# 周期性采集关键指标(写入 Prometheus/Grafana)
while true; do
    # TCP 重传率
    nstat -az TcpRetransSegs TcpOutSegs 2>/dev/null

    # 丢包计数
    nstat -az TcpExtListenDrops TcpExtListenOverflows 2>/dev/null

    # socket 缓冲区溢出
    nstat -az UdpRcvbufErrors UdpSndbufErrors 2>/dev/null

    # softirq 时间
    cat /proc/softirqs | grep NET_RX

    sleep 10
done

10.4 回滚预案

生产环境调优务必准备回滚方案:

# 保存当前配置
sysctl -a 2>/dev/null | grep -E '^net\.' > /tmp/sysctl-backup.conf

# 出问题时回滚
sysctl -p /tmp/sysctl-backup.conf

# 对于 ethtool 参数,需要记录原始值
ethtool -g eth0 > /tmp/ethtool-ring-backup.txt
ethtool -c eth0 > /tmp/ethtool-coalesce-backup.txt

十一、关键 sysctl 参数速查表

参数 默认值 内核字段 影响
net.core.rmem_max 212992 全局 socket 接收缓冲区上限
net.core.wmem_max 212992 全局 socket 发送缓冲区上限
net.core.somaxconn 4096 netns_core.sysctl_somaxconn Accept 队列上限
net.core.netdev_max_backlog 1000 netdev_max_backlog per-CPU backlog 队列长度
net.core.netdev_budget 300 netdev_budget 单次软中断处理包数上限
net.ipv4.tcp_rmem 4096 131072 6291456 sysctl_tcp_rmem[3] TCP 接收缓冲区
net.ipv4.tcp_wmem 4096 16384 4194304 sysctl_tcp_wmem[3] TCP 发送缓冲区
net.ipv4.tcp_max_syn_backlog 128/1024 sysctl_max_syn_backlog SYN 队列长度
net.ipv4.tcp_tw_reuse 2 sysctl_tcp_tw_reuse TIME_WAIT 复用
net.ipv4.tcp_fin_timeout 60 sysctl_tcp_fin_timeout FIN_WAIT_2 超时
net.ipv4.tcp_congestion_control cubic tcp_congestion_control 拥塞控制算法
net.ipv4.tcp_fastopen 1 sysctl_tcp_fastopen TCP Fast Open
net.ipv4.tcp_keepalive_time 7200 sysctl_tcp_keepalive_time Keepalive 空闲时间
net.ipv4.tcp_syncookies 1 sysctl_tcp_syncookies SYN Cookie 防护
net.ipv4.tcp_slow_start_after_idle 1 sysctl_tcp_slow_start_after_idle 空闲后重启慢启动

参考文献

  1. Linux 内核源码 include/net/netns/ipv4.hstruct netns_ipv4 中的所有 TCP sysctl 字段定义
  2. Linux 内核源码 include/net/netns/core.hstruct netns_core 中的核心 sysctl 字段
  3. Linux 内核源码 include/linux/netdevice.hNAPI_POLL_WEIGHTnetdev_max_backlog 定义
  4. Linux 内核源码 include/net/sock.hstruct socksk_rcvbufsk_sndbuf 字段
  5. Linux 内核文档 Documentation/networking/scaling.rst:RSS、RPS、RFS、XPS 机制
  6. Linux 内核文档 Documentation/admin-guide/sysctl/net.rst:网络 sysctl 参数文档

上一篇网络丢包定位:从 drop_monitor 到 kfree_skb 追踪

同主题继续阅读

把当前热点继续串成多页阅读,而不是停在单篇消费。

2026-04-27 · linux / networking

【Linux 网络子系统深度拆解】多队列与流量分发:RSS/RPS/RFS/XPS

单队列网卡的时代早已过去,但多队列本身只是起点——如何把包分到正确的 CPU 上,才是性能的关键。本文从 Linux 6.6 内核源码拆解多队列网络的完整流量分发体系:RSS 硬件哈希与 Toeplitz 算法、RPS 软件多队列模拟与 get_rps_cpu() 路径、RFS 应用感知的 rps_sock_flow_table 机制、XPS 发送端 CPU/队列亲和、aRFS 硬件流表加速,以及 netdev_pick_tx() 发送队列选择逻辑。