摘要:
网络协议栈专栏已经从内核角度深入剖析了 TCP/IP 实现、拥塞控制、缓冲区机制、epoll、零拷贝和容器网络。本篇是横向整合:将那些散落在各篇的调优参数汇聚为一份生产可用的 sysctl 调优清单,并给出每个参数的”为什么调”而不仅仅是”调成什么”。同时,介绍如何用 iperf3 和 netperf 科学地进行网络基准测试——测试不是为了拿到一个漂亮的数字,而是为了量化调优前后的对比,验证每一步调整的实际效果。最后给出三个典型场景(高吞吐量数据传输、低延迟 RPC、高并发连接)的完整调优配置,以及如何用 ss、ethtool、netstat 验证调优是否真正生效。
第 1 章 网络调优的分层模型
1.1 从哪里下手:网络栈的四个调优层次
网络性能问题根据所在层次不同,调优手段截然不同:
Layer 4:应用协议层
→ 连接池复用(减少 TIME_WAIT)
→ 请求批量合并(减少小包 RTT 代价)
→ 协议选择(HTTP/1.1 vs HTTP/2 vs gRPC)
Layer 3:Socket / TCP 层
→ 缓冲区大小(tcp_rmem / tcp_wmem)
→ 拥塞控制算法(cubic → bbr)
→ 连接队列(somaxconn / tcp_max_syn_backlog)
→ TIME_WAIT 回收(tcp_tw_reuse)
Layer 2:内核网络栈层
→ 软中断(netdev_budget)
→ 接收路径(GRO / RSS / RPS / RFS)
→ 发送路径(GSO / TSO / GSO size)
Layer 1:NIC / 驱动层
→ Ring Buffer 大小(ethtool -G)
→ 队列数量(ethtool -L)
→ 中断合并(ethtool -C)
→ 网卡特性(TSO/LRO/checksum offload)
调优应从 Layer 1 开始往上:NIC 层的丢包会让上层所有调优都白费(如果 Ring Buffer 溢出,数据包在驱动层就丢弃了,TCP 再怎么调也没用)。
1.2 基准:调优前先测量
# 在调优任何参数之前,先记录基准性能,后续调优效果对比的参考
# 使用 iperf3 测量 TCP 吞吐量(client → server,60 秒)
iperf3 -c <server_ip> -t 60 -P 4 -w 256K > baseline_throughput.txt
# 使用 netperf 测量 TCP_RR(请求-响应)延迟(代表 RPC 场景)
netperf -H <server_ip> -t TCP_RR -l 60 -- -r 100,100 > baseline_latency.txt
# 记录当前关键 sysctl 参数
sysctl net.core.somaxconn net.ipv4.tcp_rmem net.ipv4.tcp_wmem \
net.ipv4.tcp_congestion_control net.core.netdev_budget > baseline_params.txt
# 记录网卡当前状态
ethtool -S eth0 | grep -E "rx_missed|drop|error" > baseline_nic.txt
ethtool eth0 | grep -E "Speed|Duplex" >> baseline_nic.txt第 2 章 NIC 层调优:消除驱动层丢包
2.1 Ring Buffer:第一道防线
什么是 Ring Buffer:在 07 Linux 网络包的完整收发路径——软中断、NAPI 与 XDP 中详细介绍过,Ring Buffer 是网卡驱动和内核之间的 DMA 环形缓冲区。每当网卡收到数据包,DMA 将其写入 Ring Buffer;当内核软中断(NAPI)处理速度跟不上网卡收包速度时,Ring Buffer 填满,后续包被硬件直接丢弃(rx_missed_errors 计数增加)。
为什么 Ring Buffer 满了会丢包而不是等待:Ring Buffer 是有限的环形队列,网卡硬件写满后无法等待(等待会阻塞 DMA,影响后续硬件操作),只能丢弃新包。这是最底层的丢包,发生在 TCP 栈甚至驱动层之前,完全没有重传机制。
# 检查 Ring Buffer 是否在丢包
ethtool -S eth0 | grep -E "rx_missed|rx_fifo|drop"
# rx_missed_errors: 1234 ← !!持续增加说明 Ring Buffer 溢出
# 查看当前 Ring Buffer 大小
ethtool -g eth0
# Ring parameters for eth0:
# Pre-set maximums:
# RX: 4096
# TX: 4096
# Current hardware settings:
# RX: 512 ← 当前只有 512,但设备最大支持 4096
# TX: 512
# 增大 Ring Buffer(立即生效,重启失效)
ethtool -G eth0 rx 4096 tx 4096
# 永久配置(通过 NetworkManager 或 /etc/network/interfaces 的 post-up)
# 对于 systemd-networkd:
cat > /etc/systemd/network/10-eth0.link << 'EOF'
[Match]
OriginalName=eth0
[Link]
RxBufferSize=4096
TxBufferSize=4096
EOFRing Buffer 大小的权衡
Ring Buffer 越大,越不容易因为软中断处理慢而丢包;但每个 slot 预分配了 DMA 内存(约 2KB/slot),4096 个 slot = 8MB 专用内存。对于内存紧张的场景需要权衡。通常先增大 Ring Buffer 解决丢包,再排查软中断处理瓶颈的根本原因。
2.2 中断合并(Interrupt Coalescing)
什么是中断合并:网卡默认每收到一个数据包就触发一次硬件中断。在 10Gbps 网卡满速收包时,每秒可能触发 100 万次中断,中断处理本身就消耗大量 CPU。中断合并(Interrupt Coalescing)让网卡在收到 N 个包或等待 T 微秒后才触发一次中断,大幅降低中断频率:
# 查看当前中断合并配置
ethtool -c eth0
# Coalesce parameters for eth0:
# rx-usecs: 50 ← 距离上次中断 50µs 后触发(或 rx-frames 个包)
# rx-frames: 32 ← 或累积 32 个包后触发
# tx-usecs: 50
# tx-frames: 32
# 高吞吐场景:增大合并阈值(降低中断频率,提升吞吐量,增加延迟)
ethtool -C eth0 rx-usecs 100 rx-frames 64
# 效果:中断频率降低,每次处理更多包,吞吐量提升 10-20%
# 代价:最坏情况延迟增加 100µs(一个中断周期)
# 低延迟场景:减小合并阈值(或禁用)
ethtool -C eth0 rx-usecs 1 rx-frames 1
# 效果:几乎每包一个中断,最低延迟
# 代价:中断频率高,CPU 开销大
# 自适应模式(让驱动自动选择合并策略)
ethtool -C eth0 adaptive-rx on adaptive-tx on
# 驱动根据当前流量动态调整合并参数(推荐)2.3 网卡多队列与 IRQ 亲和性
详细内容在 08 高性能网络编程——io_uring 网络、SO_REUSEPORT 与多队列 NIC 中已深入讲解。这里给出快速配置命令:
# 1. 确认网卡队列数
ethtool -l eth0
# Channel parameters for eth0:
# Combined: 8 ← 当前 8 个队列(Combined = RX+TX 合并队列)
# 2. 设置队列数等于 CPU 数
ethtool -L eth0 combined $(nproc)
# 3. 设置 IRQ 亲和性(网卡 CPU 0-7 各绑定一个队列)
# 使用 set_irq_affinity 脚本(各网卡驱动通常提供)
/usr/local/sbin/set_irq_affinity local eth0
# 或手动:
for i in $(seq 0 7); do
IRQ=$(cat /proc/interrupts | grep eth0-$i | awk '{print $1}' | tr -d ':')
echo $((1 << i)) > /proc/irq/$IRQ/smp_affinity
done
# 4. 启用 RPS(软件 RSS,用于无多队列网卡)
echo ff > /sys/class/net/eth0/queues/rx-0/rps_cpus # 所有 CPU 处理第 3 章 TCP/Socket 层调优:完整参数清单
3.1 连接队列(解决高并发连接建立)
# 场景:服务启动后瞬间大量连接建立,出现 SYN 被丢弃或连接超时
# 1. accept 队列上限(somaxconn 和 listen backlog 取最小值)
sysctl -w net.core.somaxconn=65535
# 同时修改应用层的 listen backlog:listen(fd, 65535)
# 2. SYN 队列(半连接队列)上限
sysctl -w net.ipv4.tcp_max_syn_backlog=65535
# 3. SYN Cookie(防止 SYN Flood 打满 SYN 队列)
sysctl -w net.ipv4.tcp_syncookies=1
# 验证是否有 SYN 队列溢出
netstat -s | grep -i "syn\|overflow"
# 12345 SYNs to LISTEN sockets dropped ← SYN 队列溢出
# 6789 times the listen queue overflowed ← accept 队列溢出3.2 TCP 缓冲区(解决吞吐量低)
为什么缓冲区会限制吞吐量:TCP 的发送速率受限于发送窗口大小(min(cwnd, rwnd) × MSS / RTT)。如果缓冲区过小(默认最大 4MB),在高带宽高延迟链路(例如跨数据中心:1Gbps,RTT = 20ms)上,BDP(带宽延迟积)= 1Gbps × 20ms = 2.5 MB,超过默认缓冲区上限,吞吐量被硬性限制在约 200 Mbps,远低于链路容量。
# 查看当前 TCP 缓冲区配置(三元组:最小、默认、最大,单位字节)
sysctl net.ipv4.tcp_rmem # 接收缓冲区
# net.ipv4.tcp_rmem = 4096 131072 6291456 ← 最大 6MB
sysctl net.ipv4.tcp_wmem # 发送缓冲区
# net.ipv4.tcp_wmem = 4096 16384 4194304 ← 最大 4MB
# 计算 BDP 并设置合适的缓冲区(以 10Gbps,RTT=1ms 为例)
# BDP = 10Gbps × 1ms = 1.25 MB → 缓冲区需要 ≥ 2 × BDP = 2.5 MB(留余量)
# 高吞吐场景(10GbE,数据中心内)
sysctl -w net.ipv4.tcp_rmem="4096 131072 33554432" # 最大 32MB
sysctl -w net.ipv4.tcp_wmem="4096 16384 33554432" # 最大 32MB
sysctl -w net.core.rmem_max=33554432 # socket 级别上限
sysctl -w net.core.wmem_max=33554432
# 高吞吐场景(跨 WAN,RTT=50ms,带宽=1Gbps)
# BDP = 1Gbps × 50ms = 6.25 MB → 缓冲区需要 ≥ 12 MB
sysctl -w net.ipv4.tcp_rmem="4096 131072 134217728" # 最大 128MB
sysctl -w net.ipv4.tcp_wmem="4096 16384 134217728"
sysctl -w net.core.rmem_max=134217728
sysctl -w net.core.wmem_max=134217728
# 确保 Autotuning 开启(内核在范围内动态调整,不设置最大值等于固定值)
sysctl -w net.ipv4.tcp_moderate_rcvbuf=1 # 默认已开启3.3 拥塞控制算法(提升长链路吞吐量)
# 查看当前拥塞控制算法
sysctl net.ipv4.tcp_congestion_control
# net.ipv4.tcp_congestion_control = cubic ← 默认 cubic
# 查看可用的拥塞控制算法
sysctl net.ipv4.tcp_available_congestion_control
# net.ipv4.tcp_available_congestion_control = reno cubic bbr
# 切换到 BBR(高带宽高延迟链路的最佳选择)
sysctl -w net.ipv4.tcp_congestion_control=bbr
# BBR 还需要 FQ(Fair Queue)调度器配合
sysctl -w net.core.default_qdisc=fq
# BBR 适用场景:
# - 跨 WAN / 跨 IDC 的数据传输(RTT > 10ms)
# - 存在随机丢包的网络(BBR 不把丢包当拥塞信号)
# CUBIC 适用场景:
# - 数据中心内部(RTT < 1ms,CUBIC 的探测性能已经足够)
# - 对公平性要求高的场景(多条流共享带宽)3.4 TIME_WAIT 优化(解决端口耗尽)
# 场景:客户端侧大量短连接,导致端口耗尽(TIME_WAIT 连接数 > 60000)
# 方法 1:TCP 时间戳 + TIME_WAIT 复用(推荐客户端配置)
sysctl -w net.ipv4.tcp_timestamps=1 # 必须开启(TIME_WAIT 复用的前提条件)
sysctl -w net.ipv4.tcp_tw_reuse=1 # 允许 TIME_WAIT 端口被新连接复用
# 效果:TIME_WAIT 连接的端口在 1 秒后即可复用,而不是等 60 秒
# 方法 2:增大本地端口范围(临时解决方案)
sysctl -w net.ipv4.ip_local_port_range="1024 65535" # 可用端口 64511 个
# 默认:32768-60999(约 28000 个)→ 扩展到约 64000 个
# 方法 3:减少 TIME_WAIT 超时(不推荐,可能破坏 TCP 的 2MSL 保证)
# net.ipv4.tcp_fin_timeout = 30 ← 默认 60 秒,控制 FIN_WAIT2 超时
# TIME_WAIT 的 2MSL 时间由内核内部固定(Linux 为 60 秒),不可直接修改
# 查看 TIME_WAIT 连接数
ss -s | grep TIME-WAIT
# 或
ss -ant | awk '{print $1}' | sort | uniq -c | sort -rn
# !! 不推荐使用 tcp_tw_recycle(Linux 4.12+ 已删除)
# tcp_tw_recycle 在 NAT 环境中导致连接被错误拒绝(不同客户端的时间戳不单调)3.5 Keepalive 参数(检测僵尸连接)
# TCP Keepalive 用于检测长时间空闲的连接是否仍然存活
# 场景:数据库连接池保持长连接,但中间防火墙/负载均衡有空闲超时
# 开启 TCP Keepalive(全局,但应用层要设置 SO_KEEPALIVE)
sysctl -w net.ipv4.tcp_keepalive_time=600 # 空闲 600 秒后开始发送探测包(默认 7200)
sysctl -w net.ipv4.tcp_keepalive_intvl=15 # 探测包间隔 15 秒(默认 75)
sysctl -w net.ipv4.tcp_keepalive_probes=3 # 探测失败 3 次后关闭连接(默认 9)
# 在 600 秒空闲后,每 15 秒发一次探测包,3 次失败后关闭
# 总超时时间:600 + 3 × 15 = 645 秒 ≈ 11 分钟
# 这比默认的 7200 + 9 × 75 ≈ 2 小时要快得多
# 应用层同时设置 SO_KEEPALIVE(内核 Keepalive 才会生效)
int yes = 1;
setsockopt(fd, SOL_SOCKET, SO_KEEPALIVE, &yes, sizeof(yes));3.6 内核软中断调优(解决高流量下的包处理瓶颈)
# net.core.netdev_budget:每次软中断最多处理的数据包数(默认 300)
sysctl -w net.core.netdev_budget=600
# 在高流量场景(10Gbps+)增大这个值,让每次 NAPI 轮询处理更多包
# 但过大会导致单次软中断时间过长,影响延迟
# net.core.netdev_budget_usecs:每次软中断最长运行时间(µs,默认 2000)
sysctl -w net.core.netdev_budget_usecs=8000
# 配合 netdev_budget,双重限制软中断时间
# net.core.netdev_max_backlog:每个 CPU 的软中断接收队列长度(默认 1000)
sysctl -w net.core.netdev_max_backlog=10000
# 当 NAPI 来不及处理时,包暂存在此队列,避免立即丢弃
# 验证软中断是否成为瓶颈
watch -n 1 "cat /proc/net/softnet_stat"
# 每行对应一个 CPU
# 字段:total dropped time_squeezed ...
# time_squeezed:因运行时间超限被打断的次数(持续增加说明需要增大 budget)
# dropped:软中断队列满丢包次数(持续增加说明需要增大 netdev_max_backlog)第 4 章 完整调优配置清单
4.1 高吞吐量场景(数据传输、备份、Kafka)
# /etc/sysctl.d/99-network-throughput.conf
# === TCP 缓冲区 ===
net.core.rmem_max = 134217728
net.core.wmem_max = 134217728
net.ipv4.tcp_rmem = 4096 131072 134217728
net.ipv4.tcp_wmem = 4096 16384 134217728
net.ipv4.tcp_moderate_rcvbuf = 1
# === 拥塞控制 ===
net.ipv4.tcp_congestion_control = bbr
net.core.default_qdisc = fq
# === 软中断处理 ===
net.core.netdev_budget = 600
net.core.netdev_budget_usecs = 8000
net.core.netdev_max_backlog = 10000
# === 连接管理 ===
net.core.somaxconn = 65535
net.ipv4.tcp_max_syn_backlog = 65535
net.ipv4.tcp_syncookies = 1
# === TIME_WAIT 优化 ===
net.ipv4.tcp_timestamps = 1
net.ipv4.tcp_tw_reuse = 1
net.ipv4.ip_local_port_range = 1024 65535
# 生效
sysctl -p /etc/sysctl.d/99-network-throughput.conf4.2 低延迟 RPC 场景(Redis、gRPC、高频交易)
# /etc/sysctl.d/99-network-lowlatency.conf
# === TCP 缓冲区(较小,减少缓冲膨胀)===
net.core.rmem_max = 16777216
net.core.wmem_max = 16777216
net.ipv4.tcp_rmem = 4096 65536 16777216
net.ipv4.tcp_wmem = 4096 65536 16777216
# === 拥塞控制(数据中心内用 CUBIC,RTT 短)===
net.ipv4.tcp_congestion_control = cubic
net.core.default_qdisc = fq_codel # FQ-CoDel 控制 buffer bloat
# === 禁用 Nagle(低延迟场景,配合应用层 TCP_NODELAY)===
# Nagle 在应用层禁用(TCP_NODELAY),内核侧不需要额外配置
# === 快速 ACK ===
net.ipv4.tcp_quickack = 1 # 快速 ACK(但应用层需要再次设置)
# === 连接建立优化 ===
net.ipv4.tcp_syn_retries = 3 # SYN 重试次数(默认 6),加快失败连接的发现
net.ipv4.tcp_synack_retries = 3 # SYNACK 重试次数
net.core.somaxconn = 65535
net.ipv4.tcp_max_syn_backlog = 65535
# === Keepalive 激进化 ===
net.ipv4.tcp_keepalive_time = 60 # 60 秒无数据开始探测(默认 7200 太长)
net.ipv4.tcp_keepalive_intvl = 10
net.ipv4.tcp_keepalive_probes = 3
sysctl -p /etc/sysctl.d/99-network-lowlatency.conf4.3 高并发连接场景(Nginx、API Gateway、WebSocket)
# /etc/sysctl.d/99-network-highconn.conf
# === 最大 socket 文件描述符 ===
fs.file-max = 10000000 # 系统级 fd 上限
fs.nr_open = 10000000 # 单进程 fd 上限(配合 ulimit -n)
# === 连接队列 ===
net.core.somaxconn = 65535
net.ipv4.tcp_max_syn_backlog = 65535
# === TIME_WAIT 快速回收(高并发短连接)===
net.ipv4.tcp_timestamps = 1
net.ipv4.tcp_tw_reuse = 1
net.ipv4.ip_local_port_range = 1024 65535
net.ipv4.tcp_max_tw_buckets = 500000 # 最多同时存在 50 万 TIME_WAIT(默认 180000)
# === 减少连接建立开销 ===
net.ipv4.tcp_fastopen = 3 # TCP Fast Open:客户端(1) + 服务端(2)都开启
# TFO 允许在 SYN 包中携带数据,消除初始 RTT
# === 内存压力下的 socket 回收 ===
net.ipv4.tcp_mem = 786432 1048576 26777216 # 三元组:低水位、压力线、高水位(页数)
sysctl -p /etc/sysctl.d/99-network-highconn.conf
# 同时配置系统和进程的 fd 上限
echo "* soft nofile 1000000" >> /etc/security/limits.conf
echo "* hard nofile 1000000" >> /etc/security/limits.conf
echo "root soft nofile 1000000" >> /etc/security/limits.conf
echo "root hard nofile 1000000" >> /etc/security/limits.conf第 5 章 网络基准测试方法论
5.1 iperf3:TCP/UDP 吞吐量测试
# 服务端启动
iperf3 -s -p 5201 # 监听 5201 端口
# 客户端:基础吞吐量测试(60 秒,单流)
iperf3 -c <server> -t 60 -p 5201
# [ ID] Interval Transfer Bitrate Retr
# [ 5] 0.00-60.00 sec 66.2 GBytes 9.49 Gbits/sec 0 sender
# 客户端:多并发流测试(4 个并发 TCP 流)
iperf3 -c <server> -t 60 -P 4
# 多流可以更好地利用多队列 NIC 的并行性
# 客户端:指定发送缓冲区大小(测试缓冲区调优效果)
iperf3 -c <server> -t 60 -w 4m # -w:socket 缓冲区大小
# 双向测试(同时测试上行和下行)
iperf3 -c <server> -t 60 --bidir
# 逆向测试(服务端发送到客户端,测试下行带宽)
iperf3 -c <server> -t 60 -R
# JSON 输出(方便脚本处理和对比)
iperf3 -c <server> -t 60 -J > result.json
python3 -c "import json; d=json.load(open('result.json')); \
print(f\"BW: {d['end']['sum_received']['bits_per_second']/1e9:.2f} Gbps\")"
# 测试特定 MTU 大小(模拟不同网络路径)
iperf3 -c <server> -t 60 --length 1400 # MTU = 1400 字节5.2 netperf:延迟和 QPS 基准测试
iperf3 侧重带宽测试,netperf 更擅长测量请求-响应模式(RPC 场景)的性能:
# 服务端
netserver -p 12865
# TCP_RR(TCP Request-Response):测量单连接 RPS 和延迟
# 模拟:一次发送 100 字节请求,接收 100 字节响应
netperf -H <server> -t TCP_RR -l 60 -- -r 100,100
# MIGRATED TCP REQUEST/RESPONSE TEST from 0.0.0.0 (0.0.0.0) port 0 to <server> port 0 : demo
# Local /Remote
# Socket Size Request Resp. Elapsed Trans.
# Send Recv Size Size Time Rate
# bytes Bytes bytes bytes secs. per sec
# 131072 131072 100 100 60.00 123456.78 ← 每秒 12.3 万次 RPC
# TCP_CRR(TCP Connect-Request-Response):测量包含连接建立的 RPS
# 模拟:短连接场景(每次 RPC 建立新连接)
netperf -H <server> -t TCP_CRR -l 60 -- -r 100,100
# 通常比 TCP_RR 慢 5-10 倍(TCP 三次握手开销)
# TCP_STREAM:吞吐量测试(功能类似 iperf3)
netperf -H <server> -t TCP_STREAM -l 60
# UDP_RR:UDP 请求-响应(测试低延迟 UDP 场景)
netperf -H <server> -t UDP_RR -l 60 -- -r 64,645.3 用基准测试量化调优效果
# 调优前后对比脚本
#!/bin/bash
SERVER=10.0.0.1
echo "=== 基准测试前 ==="
# 吞吐量
iperf3 -c $SERVER -t 30 -J | python3 -c "
import json,sys; d=json.load(sys.stdin)
bw = d['end']['sum_received']['bits_per_second']/1e9
print(f'吞吐量: {bw:.2f} Gbps')"
# RPC 延迟
netperf -H $SERVER -t TCP_RR -l 30 -- -r 100,100 | tail -1 | awk '{
printf "RPC QPS: %.0f/s\n", $NF
printf "RPC 平均延迟: %.3f ms\n", 1000/$NF
}'
echo ""
echo "修改 sysctl 参数..."
sysctl -w net.ipv4.tcp_congestion_control=bbr
sysctl -w net.core.default_qdisc=fq
echo "=== 调优后 ==="
iperf3 -c $SERVER -t 30 -J | python3 -c "
import json,sys; d=json.load(sys.stdin)
bw = d['end']['sum_received']['bits_per_second']/1e9
print(f'吞吐量: {bw:.2f} Gbps')"
netperf -H $SERVER -t TCP_RR -l 30 -- -r 100,100 | tail -1 | awk '{
printf "RPC QPS: %.0f/s\n", $NF
}'5.4 验证调优效果的 ss 命令
# 调优后,用 ss -ti 确认 TCP 连接已经使用了新的参数
# 验证 BBR 是否生效
ss -ti dst <server_ip> | grep -i bbr
# cwnd:10 ssthresh:2147483647 ... bbr ← 已使用 BBR
# 验证缓冲区是否增大(rcv_space 应接近调优后的最大值)
ss -ti dst <server_ip> | grep rcv_space
# rcv_space:65536 ← 若远低于 tcp_rmem 最大值,说明 Autotuning 未充分发挥
# rcv_space:33554432 ← 已充分扩展到最大缓冲区(33MB),带宽充分利用
# 验证拥塞窗口是否增大(cwnd 应随着连接稳定而增大)
ss -ti | grep cwnd | awk '{print $0}' | grep -v "cwnd:10 "
# 成熟连接的 cwnd 应远大于 10(初始值)小结
网络调优是一个多层联动的过程,任何单层的优化都可能被其他层的瓶颈抵消:
从底到上的调优顺序:
- NIC 层:Ring Buffer 丢包 →
ethtool -G增大;中断合并 →ethtool -C调整 - 软中断层:
netdev_budget和netdev_max_backlog防止软中断队列丢包 - TCP 缓冲区层:
tcp_rmem/tcp_wmem按 BDP 设置 - 拥塞控制:长链路 → BBR;数据中心短链路 → CUBIC
- 连接管理:
somaxconn+tcp_max_syn_backlog+tcp_tw_reuse
基准测试原则:
- 每次只调一个参数,用
iperf3/netperf验证效果 - 记录调优前的基准数据,用差分比较而非绝对值
- 基准测试场景要匹配真实负载(带宽型 → iperf3,延迟型 → netperf TCP_RR)
下一篇 08 系统调用开销与用户态优化——vDSO、seccomp 与零系统调用 将深入一个鲜少被系统讨论的性能维度:系统调用本身的开销。每次 gettimeofday()、clock_gettime()、read() 背后都是从用户态到内核态的切换,约 100-1000ns 的代价。vDSO 如何让某些系统调用完全不进内核,seccomp 过滤的延迟代价,以及如何识别并消除不必要的高频系统调用。
思考题
- TCP 接收/发送缓冲区在高带宽长延迟链路中可能不够。BDP = 带宽 × RTT。在 10Gbps、RTT 100ms 链路中 BDP 约 125MB——TCP 缓冲区至少需要这么大。
net.ipv4.tcp_rmem的三个值(min、default、max)分别在什么时机被使用?TCP 的自动调优(autotuning)如何动态调整缓冲区大小?- BBR 拥塞控制基于带宽和 RTT 测量,CUBIC 基于丢包反馈。在有一定随机丢包的网络中(如无线网络),CUBIC 会误认为发生了拥塞而降速,BBR 则不受影响。但 BBR v1 在多流竞争时可能导致不公平。BBR v2/v3 做了哪些改进?在数据中心内部网络中应该选择 BBR 还是 DCTCP?
- 网卡中断合并(
ethtool -C rx-usecs)在批量处理和延迟之间取舍。在交易系统中禁用中断合并可以降低延迟。CPU busy_poll(net.core.busy_poll)让应用线程主动轮询网卡——进一步消除中断延迟。busy_poll 的 CPU 开销在什么负载模式下是可接受的?