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

【网络工程】内核网络参数调优:sysctl 全景与实战

文章导航

分类入口
network
标签入口
#kernel-tuning#sysctl#tcp#network-performance#linux-networking

目录

Linux 内核的网络栈有数百个可调参数,分散在 /proc/sys/net/ 的各个子目录下。很多工程师要么不敢动、要么乱调一通——要么保守到错失性能,要么激进到引发故障。本文的目标不是列出所有参数,而是讲清楚哪些参数值得调、为什么要调、调多少、怎么验证效果

一、参数体系总览

1.1 /proc/sys/net/ 目录结构

/proc/sys/net/
├── core/                 # 通用网络核心参数
│   ├── somaxconn         # listen() backlog 上限
│   ├── netdev_max_backlog # 网卡收包队列长度
│   ├── rmem_default      # 默认接收缓冲区
│   ├── rmem_max          # 最大接收缓冲区
│   ├── wmem_default      # 默认发送缓冲区
│   ├── wmem_max          # 最大发送缓冲区
│   ├── optmem_max        # 辅助数据缓冲区
│   └── busy_poll         # 忙轮询超时
├── ipv4/                 # IPv4/TCP/UDP 参数
│   ├── tcp_*             # TCP 相关(最多)
│   ├── ip_*              # IP 层参数
│   ├── conf/             # 接口级 IP 配置
│   └── neigh/            # ARP 邻居表
├── ipv6/                 # IPv6 参数
├── netfilter/            # conntrack 相关
│   ├── nf_conntrack_max  # 连接追踪表大小
│   └── nf_conntrack_*    # 各协议超时
└── unix/                 # Unix domain socket

1.2 查看和修改参数

# 查看单个参数
sysctl net.core.somaxconn
cat /proc/sys/net/core/somaxconn

# 临时修改(重启后失效)
sysctl -w net.core.somaxconn=65535

# 永久修改
echo "net.core.somaxconn = 65535" >> /etc/sysctl.d/99-network.conf
sysctl -p /etc/sysctl.d/99-network.conf

# 查看所有网络参数
sysctl -a 2>/dev/null | grep "^net\." | wc -l  # 通常 500+

# 查看当前值与默认值的差异
# 没有直接命令,需要对比新装系统

二、收发缓冲区调优

2.1 TCP 缓冲区参数

TCP 缓冲区大小直接影响吞吐量——缓冲区太小,窗口满了就得等 ACK;缓冲区太大,浪费内存。

# TCP 内存管理三元组:[min, pressure, max](单位:page,通常 4KB)
sysctl net.ipv4.tcp_mem
# 示例输出:87381 116508 174762
# min      = 87381 pages ≈ 341 MB — TCP 总内存低于此值时不受限
# pressure = 116508 pages ≈ 455 MB — 进入压力模式,开始回收
# max      = 174762 pages ≈ 682 MB — TCP 总内存上限

# TCP 接收缓冲区三元组:[min, default, max](单位:字节)
sysctl net.ipv4.tcp_rmem
# 示例输出:4096 131072 6291456
# min     = 4096      — 每个 socket 最少 4KB
# default = 131072    — 默认 128KB
# max     = 6291456   — 最大 6MB(自动调优的上限)

# TCP 发送缓冲区三元组
sysctl net.ipv4.tcp_wmem
# 示例输出:4096 16384 4194304

2.2 自动调优机制

Linux 内核有 TCP 缓冲区自动调优(autotuning),会根据网络条件动态调整缓冲区大小:

# 启用/禁用自动调优
sysctl net.ipv4.tcp_moderate_rcvbuf
# 1 = 启用(默认),0 = 禁用

# 自动调优的工作原理:
# 1. 新连接从 tcp_rmem[1](default)开始
# 2. 内核根据 RTT 和带宽动态增大缓冲区
# 3. 不超过 tcp_rmem[2](max)
# 4. 如果 TCP 总内存超过 tcp_mem[1],进入压力模式,缩小缓冲区

# 带宽-延迟积(BDP)计算
# BDP = Bandwidth × RTT
# 示例:1 Gbps, 10ms RTT
# BDP = 1,000,000,000 / 8 × 0.010 = 1,250,000 bytes ≈ 1.2 MB
# 缓冲区至少要 >= BDP 才能跑满带宽

2.3 高带宽长延迟场景调优

# 场景:跨大洲数据传输
# 带宽 10 Gbps,RTT 100ms
# BDP = 10,000,000,000 / 8 × 0.100 = 125,000,000 bytes ≈ 125 MB

# 调优配置
cat > /etc/sysctl.d/99-high-bandwidth.conf << 'EOF'
# TCP 缓冲区——适配 10Gbps × 100ms
net.ipv4.tcp_rmem = 4096 1048576 134217728
net.ipv4.tcp_wmem = 4096 1048576 134217728

# Socket 层面的全局上限
net.core.rmem_max = 134217728
net.core.wmem_max = 134217728
net.core.rmem_default = 1048576
net.core.wmem_default = 1048576

# TCP 总内存上限(需要足够大以支持多连接)
# 单位:page(4KB)
# 134217728 * 100 connections / 4096 ≈ 3276800 pages
net.ipv4.tcp_mem = 1638400 2457600 3276800

# 保持自动调优开启
net.ipv4.tcp_moderate_rcvbuf = 1

# 窗口缩放(默认开启,确认一下)
net.ipv4.tcp_window_scaling = 1
EOF

sysctl -p /etc/sysctl.d/99-high-bandwidth.conf

2.4 缓冲区调优验证

# 1. 用 ss 查看 socket 实际缓冲区大小
ss -tim | head -20
# 输出中的关键字段:
# rcv_space: 接收窗口自动调优的目标值
# rcv_ssthresh: 接收慢启动阈值
# snd_wnd: 发送窗口大小

# 2. 用 iperf3 验证吞吐量
# 服务端
iperf3 -s

# 客户端——设置窗口大小
iperf3 -c server_ip -w 128M -t 30

# 3. 对比调优前后
# 调优前
iperf3 -c server_ip -t 10 -J | jq '.end.sum_sent.bits_per_second'

# 调优后
sysctl -p /etc/sysctl.d/99-high-bandwidth.conf
iperf3 -c server_ip -t 10 -J | jq '.end.sum_sent.bits_per_second'

三、连接队列与 Backlog

3.1 两级队列模型

TCP 服务器接收连接经过两个队列:SYN 队列(半连接)和 Accept 队列(全连接):

客户端                    服务器
  │                        │
  │─── SYN ──────────────→│
  │                   ┌────┴────┐
  │                   │ SYN 队列 │ ← tcp_max_syn_backlog
  │                   │(半连接)  │
  │←── SYN+ACK ──────┤         │
  │                   └────┬────┘
  │─── ACK ──────────────→│
  │                   ┌────┴────┐
  │                   │Accept队列│ ← min(somaxconn, backlog)
  │                   │(全连接)  │
  │                   └────┬────┘
  │                        │
  │                   accept()

3.2 队列参数调优

# Accept 队列上限
# 实际大小 = min(net.core.somaxconn, listen(fd, backlog) 的 backlog 参数)
sysctl net.core.somaxconn
# 默认值:4096(旧内核为 128)
# 高并发场景建议:65535

# SYN 队列上限(半连接队列)
sysctl net.ipv4.tcp_max_syn_backlog
# 默认值:1024 或 2048
# 高并发场景建议:65535

# 查看队列溢出
# Accept 队列溢出
netstat -s | grep "overflowed"
# SYN 队列溢出
netstat -s | grep "dropped"

# 或者用 nstat 查看增量
nstat -az TcpExtListenOverflows TcpExtListenDrops

# Accept 队列满时的行为
sysctl net.ipv4.tcp_abort_on_overflow
# 0(默认):丢弃 ACK,客户端会重传(静默丢弃)
# 1:发送 RST,客户端立即收到 "Connection reset"
# 建议保持 0,除非需要快速失败

3.3 网卡收包队列

# 网卡驱动到协议栈之间的队列
sysctl net.core.netdev_max_backlog
# 默认值:1000
# 高吞吐场景建议:10000-50000

# 网卡中断合并(减少 CPU 中断)
# 查看当前设置
ethtool -c eth0

# 设置中断合并参数
ethtool -C eth0 rx-usecs 50 rx-frames 64

# 多队列网卡的 RSS(Receive Side Scaling)
ethtool -l eth0        # 查看队列数
ethtool -L eth0 combined 8  # 设置 8 个收发队列

四、TIME_WAIT 管理

4.1 TIME_WAIT 的工程影响

# 查看 TIME_WAIT 连接数
ss -s | grep TIME-WAIT
# 或者
ss -tan state time-wait | wc -l

# TIME_WAIT 的作用:
# 1. 确保最后一个 ACK 被对端收到
# 2. 等待旧连接的迟到包过期
# TIME_WAIT 持续时间 = 2 × MSL(通常 60s)

4.2 TIME_WAIT 调优参数

# 允许 TIME_WAIT socket 被新连接复用
sysctl net.ipv4.tcp_tw_reuse
# 0(默认):禁用
# 1:启用——仅对客户端有效(connect 调用)
# 2:对 loopback 地址也启用
# 建议:客户端设为 1

# 最大 TIME_WAIT 数量
sysctl net.ipv4.tcp_max_tw_buckets
# 默认值:65536 或更高
# 超过时内核会销毁 TIME_WAIT socket 并打印警告

# TCP 时间戳(tcp_tw_reuse 的前提)
sysctl net.ipv4.tcp_timestamps
# 必须开启(默认 1)才能安全使用 tcp_tw_reuse

# !!!! 注意 !!!!
# net.ipv4.tcp_tw_recycle 在 Linux 4.12 后已移除
# 它在 NAT 环境下会导致大量连接失败
# 绝对不要使用

4.3 高并发短连接场景

# 场景:反向代理(大量到后端的短连接)
# 症状:大量 TIME_WAIT 占用端口

cat > /etc/sysctl.d/99-high-concurrency.conf << 'EOF'
# 允许 TIME_WAIT 复用
net.ipv4.tcp_tw_reuse = 1

# 可用端口范围(默认 32768-60999)
net.ipv4.ip_local_port_range = 1024 65535

# TIME_WAIT 桶上限
net.ipv4.tcp_max_tw_buckets = 200000

# 开启时间戳
net.ipv4.tcp_timestamps = 1

# FIN_WAIT2 超时(默认 60s)
net.ipv4.tcp_fin_timeout = 15
EOF

sysctl -p /etc/sysctl.d/99-high-concurrency.conf

五、conntrack 连接追踪

5.1 conntrack 概述

conntrack 是 Netfilter 框架的连接追踪模块。使用 iptables/nftables 做 NAT 或状态防火墙时会自动加载。

# 查看 conntrack 表当前状态
conntrack -C   # 当前连接数
conntrack -L 2>/dev/null | wc -l  # 列出所有连接

# conntrack 表大小
sysctl net.netfilter.nf_conntrack_max
# 默认值:65536 或根据内存自动计算
# 每条记录约占 320 字节

# conntrack 表满时的症状
# dmesg 中出现:nf_conntrack: table full, dropping packet
# 新连接无法建立,表现为随机丢包

# 查看是否有 conntrack 丢包
dmesg | grep "nf_conntrack: table full"
cat /proc/sys/net/netfilter/nf_conntrack_count
cat /proc/sys/net/netfilter/nf_conntrack_max

5.2 conntrack 调优

# 增大 conntrack 表
sysctl -w net.netfilter.nf_conntrack_max=1048576

# Hash 表大小(只能在加载模块时设置)
echo "options nf_conntrack hashsize=262144" > /etc/modprobe.d/nf_conntrack.conf

# 缩短超时时间以加速条目回收
sysctl -w net.netfilter.nf_conntrack_tcp_timeout_established=3600
sysctl -w net.netfilter.nf_conntrack_tcp_timeout_time_wait=30
sysctl -w net.netfilter.nf_conntrack_tcp_timeout_close_wait=30
sysctl -w net.netfilter.nf_conntrack_tcp_timeout_fin_wait=30
sysctl -w net.netfilter.nf_conntrack_udp_timeout=30
sysctl -w net.netfilter.nf_conntrack_udp_timeout_stream=120

# 对不需要 NAT/状态跟踪的流量禁用 conntrack
# 使用 raw 表的 NOTRACK
iptables -t raw -A PREROUTING -p tcp --dport 80 -j NOTRACK
iptables -t raw -A OUTPUT -p tcp --sport 80 -j NOTRACK

5.3 conntrack 容量规划

并发连接数 conntrack_max Hash 表大小 内存占用
10 万 131072 32768 ~40 MB
50 万 524288 131072 ~160 MB
100 万 1048576 262144 ~320 MB
500 万 5242880 1310720 ~1.6 GB

六、SYN Flood 防护参数

# SYN Cookie——当 SYN 队列满时启用
sysctl net.ipv4.tcp_syncookies
# 1(默认):启用
# SYN Cookie 不占队列空间,但会丢失 TCP 选项(窗口缩放、SACK)

# SYN 重试次数
sysctl net.ipv4.tcp_syn_retries
# 默认 6(约 127 秒),建议 2-3

# SYN+ACK 重试次数
sysctl net.ipv4.tcp_synack_retries
# 默认 5(约 63 秒),建议 2-3

# 综合防护配置
cat > /etc/sysctl.d/99-syn-flood.conf << 'EOF'
net.ipv4.tcp_syncookies = 1
net.ipv4.tcp_syn_retries = 2
net.ipv4.tcp_synack_retries = 2
net.ipv4.tcp_max_syn_backlog = 65535
net.core.somaxconn = 65535
EOF

七、Keepalive 参数

# TCP Keepalive 参数
sysctl net.ipv4.tcp_keepalive_time
# 默认 7200(2小时)——多久没数据后开始探测
# 高可用场景建议:600(10分钟)

sysctl net.ipv4.tcp_keepalive_intvl
# 默认 75(秒)——探测间隔
# 建议:15-30

sysctl net.ipv4.tcp_keepalive_probes
# 默认 9——探测次数
# 建议:5

# 完整配置
# 600 + 15 × 5 = 675 秒后发现死连接
cat > /etc/sysctl.d/99-keepalive.conf << 'EOF'
net.ipv4.tcp_keepalive_time = 600
net.ipv4.tcp_keepalive_intvl = 15
net.ipv4.tcp_keepalive_probes = 5
EOF

7.2 TCP 内存压力诊断

# 查看 TCP 内存使用
cat /proc/net/sockstat
# sockets: used 1500
# TCP: inuse 800 orphan 10 tw 200 alloc 900 mem 15000

# "mem" 字段单位是 page(4KB),15000 pages ≈ 58 MB

# 查看 TCP 内存限制
sysctl net.ipv4.tcp_mem
# 87381 116508 174762(页)

# 当 mem 接近 tcp_mem[1] 时,内核进入"内存压力"模式
# 表现:新连接的缓冲区被限制在 tcp_rmem[0],吞吐量骤降

# 查看是否进入了内存压力
cat /proc/net/sockstat | awk '/TCP:/{print "TCP mem:", $NF, "pages"}'
sysctl net.ipv4.tcp_mem | awk '{print "pressure threshold:", $2, "pages"}'

# 如果 mem > pressure,增大 tcp_mem
# 注意:tcp_mem 的单位是 page,不是字节

八、参数调优方法论

8.1 系统化流程

┌────────────┐
│ 1. 确定目标 │  吞吐量?延迟?并发数?
└─────┬──────┘
      ↓
┌────────────┐
│ 2. 基准测试 │  用 iperf3/wrk/ab 测量当前性能
└─────┬──────┘
      ↓
┌────────────┐
│ 3. 瓶颈分析 │  查看 netstat -s、ss -ti、dmesg
└─────┬──────┘
      ↓
┌────────────┐
│ 4. 调整参数 │  每次只改一个参数或一组相关参数
└─────┬──────┘
      ↓
┌────────────┐
│ 5. 验证效果 │  重跑基准测试,对比前后
└─────┬──────┘
      ↓
┌────────────┐
│ 6. 持久化   │  写入 /etc/sysctl.d/
└────────────┘

8.2 常见问题诊断

症状 可能原因 诊断命令 调优方向
新连接被拒 Accept 队列满 nstat TcpExtListenOverflows somaxconn
连接超时多 SYN 队列满 nstat TcpExtTCPReqQFullDrop tcp_max_syn_backlog
吞吐量低 缓冲区太小 ss -tim 看 rcv_space tcp_rmem/tcp_wmem
随机丢包 conntrack 表满 dmesg \| grep conntrack nf_conntrack_max
TIME_WAIT 多 短连接频繁 ss -s tcp_tw_reuse
延迟高 Nagle + Delayed ACK 应用层设置 TCP_NODELAY 应用层

8.3 完整调优配置模板

cat > /etc/sysctl.d/99-network-tuning.conf << 'EOF'
### 连接队列
net.core.somaxconn = 65535
net.ipv4.tcp_max_syn_backlog = 65535
net.core.netdev_max_backlog = 10000

### TCP 缓冲区
net.core.rmem_max = 16777216
net.core.wmem_max = 16777216
net.ipv4.tcp_rmem = 4096 1048576 16777216
net.ipv4.tcp_wmem = 4096 1048576 16777216
net.ipv4.tcp_moderate_rcvbuf = 1

### TIME_WAIT
net.ipv4.tcp_tw_reuse = 1
net.ipv4.ip_local_port_range = 1024 65535
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 防护
net.ipv4.tcp_syncookies = 1
net.ipv4.tcp_syn_retries = 2
net.ipv4.tcp_synack_retries = 2

### conntrack(如果使用 iptables/NAT)
# net.netfilter.nf_conntrack_max = 1048576
# net.netfilter.nf_conntrack_tcp_timeout_established = 3600

### 其他
net.ipv4.tcp_timestamps = 1
net.ipv4.tcp_sack = 1
net.ipv4.tcp_window_scaling = 1
net.ipv4.tcp_no_metrics_save = 1
EOF

sysctl -p /etc/sysctl.d/99-network-tuning.conf

九、中断亲和与软中断

9.1 中断亲和(IRQ Affinity)

网卡中断默认可能集中在 CPU 0 上,导致单核瓶颈。合理分配中断到多个 CPU 可以显著提升吞吐量。

# 查看网卡中断分布
cat /proc/interrupts | grep eth0
# 或者查看多队列网卡
cat /proc/interrupts | grep -E "eth0-TxRx|ens"

# 查看某个中断的 CPU 亲和性
cat /proc/irq/48/smp_affinity_list
# 输出 "0" 表示绑定到 CPU 0

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

# 使用 irqbalance 服务自动分配(大多数场景推荐)
systemctl status irqbalance
# irqbalance 会自动将中断分散到各 CPU
# 但在高性能场景下手动绑定可能更好

9.2 RPS/RFS/XPS

当网卡不支持多队列 RSS 时,可以用软件方式将包处理分散到多个 CPU:

# RPS(Receive Packet Steering)——软件层面的收包分发
# 将某个队列的包分发到多个 CPU 处理
# 掩码 ff 表示使用 CPU 0-7
echo ff > /sys/class/net/eth0/queues/rx-0/rps_cpus

# RFS(Receive Flow Steering)——将包导向处理该连接的 CPU
# 减少 CPU 缓存未命中
echo 32768 > /proc/sys/net/core/rps_sock_flow_entries
echo 4096 > /sys/class/net/eth0/queues/rx-0/rps_flow_cnt

# XPS(Transmit Packet Steering)——发送方向的 CPU 亲和
# 将发送队列绑定到特定 CPU
echo 1 > /sys/class/net/eth0/queues/tx-0/xps_cpus    # CPU 0
echo 2 > /sys/class/net/eth0/queues/tx-1/xps_cpus    # CPU 1
echo 4 > /sys/class/net/eth0/queues/tx-2/xps_cpus    # CPU 2
技术 方向 硬件要求 效果
RSS 接收 多队列网卡 硬件分发到多 CPU
RPS 接收 软件模拟 RSS
RFS 接收 包导向处理线程所在 CPU
XPS 发送 减少发送锁竞争

9.3 Busy Polling

对于延迟极敏感的场景,可以让 CPU 主动轮询网卡而不是等待中断:

# 全局启用 busy polling
sysctl -w net.core.busy_poll=50       # 轮询 50 微秒
sysctl -w net.core.busy_read=50       # 阻塞读时轮询 50 微秒

# 或者在 socket 级别启用
# setsockopt(fd, SOL_SOCKET, SO_BUSY_POLL, &poll_usecs, sizeof(poll_usecs));

# 代价:CPU 使用率增加,换取延迟降低
# 适用场景:金融交易、实时通信
# 不适用场景:CPU 资源紧张的通用服务器

十、拥塞控制算法选择

# 查看可用的拥塞控制算法
sysctl net.ipv4.tcp_available_congestion_control
# 输出:reno cubic bbr

# 查看当前使用的算法
sysctl net.ipv4.tcp_congestion_control
# 默认:cubic

# 切换到 BBR
modprobe tcp_bbr
sysctl -w net.ipv4.tcp_congestion_control=bbr

# 验证
sysctl net.ipv4.tcp_congestion_control
ss -tin | grep -o "bbr" | head -5
算法 适用场景 特点
cubic 通用默认 基于丢包的拥塞控制,公平性好
bbr 高带宽高延迟 基于带宽估计,不惧轻微丢包
reno 兼容性 最基础的 AIMD,现在很少使用
# BBR + fq 队列规则的组合
# BBR 配合 fq(Fair Queue)效果最佳
tc qdisc replace dev eth0 root fq pacing

# 持久化
cat >> /etc/sysctl.d/99-network-tuning.conf << 'EOF'
net.ipv4.tcp_congestion_control = bbr
net.core.default_qdisc = fq
EOF

十一、ARP/邻居表调优

在大型二层网络中(尤其是容器环境),ARP/邻居表可能溢出:

# ARP 表参数
sysctl net.ipv4.neigh.default.gc_thresh1
# 默认 128 — 开始垃圾回收的最低条目数
sysctl net.ipv4.neigh.default.gc_thresh2
# 默认 512 — 触发更积极 GC 的条目数
sysctl net.ipv4.neigh.default.gc_thresh3
# 默认 1024 — 硬上限,超过则无法创建新条目

# 大规模环境调优
cat >> /etc/sysctl.d/99-network-tuning.conf << 'TUNING_EOF'
net.ipv4.neigh.default.gc_thresh1 = 4096
net.ipv4.neigh.default.gc_thresh2 = 8192
net.ipv4.neigh.default.gc_thresh3 = 16384
net.ipv6.neigh.default.gc_thresh1 = 4096
net.ipv6.neigh.default.gc_thresh2 = 8192
net.ipv6.neigh.default.gc_thresh3 = 16384
TUNING_EOF

# 查看 ARP 表当前大小
ip neigh show | wc -l

# 查看 ARP 表溢出错误
dmesg | grep "neighbour table overflow"
场景 gc_thresh3 建议值
普通服务器 1024(默认)
容器宿主机(100+ Pod) 16384
大型二层网络(1000+ 主机) 65536

十二、实战案例

12.1 案例:Nginx 反向代理 TIME_WAIT 堆积

现象:Nginx 反代后端服务,高峰期 ss -s 显示 6 万+ TIME_WAIT,偶发 cannot assign requested address 错误。

分析

# 1. 确认 TIME_WAIT 数量
ss -s
# TCP:   85000 (estab 20000, closed 0, orphaned 0, timewait 65000)

# 2. 确认可用端口范围
sysctl net.ipv4.ip_local_port_range
# 32768 60999  → 只有 28231 个端口

# 3. 确认 tcp_tw_reuse 状态
sysctl net.ipv4.tcp_tw_reuse
# 0  → 未开启

# 4. TIME_WAIT 的四元组:src_ip:src_port → dst_ip:dst_port
# 到同一后端 IP:Port 的连接,最多 28231 个端口可用
# 减去 TIME_WAIT 中的端口,可用端口耗尽

解决

# 方案一:启用 tcp_tw_reuse + 扩大端口范围
sysctl -w net.ipv4.tcp_tw_reuse=1
sysctl -w net.ipv4.ip_local_port_range="1024 65535"
sysctl -w net.ipv4.tcp_fin_timeout=15

# 方案二:Nginx 配置长连接到后端(根本解决)
# upstream backend {
#     server 10.0.0.1:8080;
#     keepalive 256;            # 保持 256 个长连接
#     keepalive_requests 10000; # 每个连接最多 10000 请求
#     keepalive_timeout 60s;    # 空闲超时
# }
#
# location / {
#     proxy_http_version 1.1;
#     proxy_set_header Connection "";  # 清除 "close"
#     proxy_pass http://backend;
# }

结果:方案二上线后 TIME_WAIT 从 6 万+ 降到 500 以内。

12.2 案例:conntrack 表满导致间歇丢包

现象:K8s 集群中某些 Pod 间歇性连接超时,kubectl exec 偶尔也超时。

分析

# 1. 检查 dmesg
dmesg | tail -50
# [12345.678] nf_conntrack: table full, dropping packet

# 2. 查看 conntrack 使用率
cat /proc/sys/net/netfilter/nf_conntrack_count
# 131072
cat /proc/sys/net/netfilter/nf_conntrack_max
# 131072  → 已满!

# 3. 分析 conntrack 条目分布
conntrack -L 2>/dev/null | \
    awk '{print $3}' | sort | uniq -c | sort -rn
# 120000 tcp
#  10000 udp
#   1072 icmp

# 4. 检查 ESTABLISHED 超时
sysctl net.netfilter.nf_conntrack_tcp_timeout_established
# 432000 (5天)  → 太长!

解决

# 增大表 + 缩短超时
sysctl -w net.netfilter.nf_conntrack_max=524288
sysctl -w net.netfilter.nf_conntrack_tcp_timeout_established=3600
sysctl -w net.netfilter.nf_conntrack_tcp_timeout_time_wait=30

# 对高流量端口跳过 conntrack
iptables -t raw -A PREROUTING -p tcp --dport 80 -j NOTRACK
iptables -t raw -A PREROUTING -p tcp --dport 443 -j NOTRACK
iptables -t raw -A OUTPUT -p tcp --sport 80 -j NOTRACK
iptables -t raw -A OUTPUT -p tcp --sport 443 -j NOTRACK

8.4 调优注意事项

注意事项 说明
不要盲目抄配置 每个参数都要理解其含义和副作用
每次只改一组 否则无法判断哪个参数产生了效果
先测后改 没有基准数据的调优是盲目的
监控副作用 某些参数改大会增加内存消耗
内核版本差异 不同内核版本的默认值和行为可能不同
NAT 环境谨慎 tcp_tw_recycle 在 NAT 下会出问题(已移除)
容器环境 容器内的 sysctl 可能受宿主机限制

参考文献

  1. Linux Kernel Documentation, “IP Sysctl,” kernel.org/doc/Documentation/networking/ip-sysctl.rst.
  2. Hemminger, S., “TCP Tuning Guide,” Linux Foundation.
  3. Corbet, J., “TCP small queues,” LWN.net, 2012.
  4. Benvenuti, C., “Understanding Linux Network Internals,” O’Reilly, 2005.
  5. Stewart, R., “TCP/IP Illustrated, Volume 1,” Addison-Wesley, 2011.
  6. Linux man pages, “tcp(7), socket(7), ip(7).”
  7. Gregg, B., “BPF Performance Tools,” Addison-Wesley, 2019.
  8. Red Hat, “Performance Tuning Guide,” access.redhat.com/documentation.
  9. Cloudflare Blog, “How to achieve low latency with 10Gbps Ethernet,” 2015.

上一篇: 网络取证:流量分析、异常检测与事件响应 下一篇: 网络性能基准测试:iperf3、netperf 与测试方法论

同主题继续阅读

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

2025-08-01 · network

【网络工程】网络延迟优化:Nagle、TCP_NODELAY 与中断亲和

网络延迟优化是延迟敏感应用的核心关注点。本文从 Nagle 算法与 Delayed ACK 的经典交互问题出发,系统讲解 TCP_NODELAY 和 TCP_CORK 的正确用法、中断亲和与 RPS/RFS、Busy Polling、socket 调优、应用层延迟优化,以及延迟分解和定位方法论。


By .