Linux veth pair 的 txqueuelen 与 net.core.netdev_max_backlog 调优

1次阅读

veth pair 的 txqueuelen 设太小会导致 tx_dropped 增长,因其控制 qdisc 层排队长度(包数),默认 1000 在高突发流量下易溢出;需两端同步设为 5000~10000,并匹配调大.net.core.netdev_max_backlog 至 2000~3000。

Linux veth pair 的 txqueuelen 与 net.core.netdev_max_backlog 调优

为什么 veth pair 的 txqueuelen 设太小会导致丢包

容器或虚拟网络中频繁出现 tx_dropped 增长,但 rx_errors/tx_errors 为 0,大概率是 txqueuelen 不足导致的队列溢出。veth 是软设备,不走物理网卡驱动队列,它的发送队列完全由内核 qdisc 管理,而默认 txqueuelen=1000 在高吞吐、突发流量(如短连接密集建立、rpc 批量调用)下极易填满。

  • txqueuelen 控制的是该接口 qdisc 层的排队长度(单位:数据包),不是字节;设为 0 表示“由 qdisc 自行决定”,但多数场景下不如显式设大更可控
  • 对 veth pair,必须两端同时调大:只改 host 侧或只改 Namespace 侧都没用,流量卡在瓶颈端
  • 典型安全值:5000~10000,超过 20000 需同步检查 net.core.netdev_max_backlog,否则会触发上层丢包
  • 临时生效:ip link set dev veth0 txqueuelen 5000;持久化需在创建 veth 后立刻设置(如 CNI 插件 hook 或 systemd-networkd 配置中)

net.core.netdev_max_backlog 调大后反而延迟升高?

这个参数控制的是“软中断上下文下 NIC 收包队列”的最大长度,它和 veth 的 txqueuelen 是上下游关系:veth 发出去的包,最终要被对端 veth 的收包路径塞进这个 backlog 队列。设太大,会导致 softirq 处理单次轮询时间变长,引发调度延迟、RTT 波动。

  • 默认值 1000 对大多数容器间通信偏小;但盲目设到 5000+ 容易让 softirq 占用 CPU 过久,尤其在低核数节点上
  • 合理值取决于单核处理能力与平均包大小:1500 字节包下,2000~3000 是较稳的区间;若跑的是小包(如 64B ICMP 或 gRPC metadata),建议压到 1000~1500
  • 检查是否真需要调大:看 /proc/net/softnet_stat 第 2 列(dropped)是否持续增长;只涨第 1 列(processed)说明没丢包,不必调
  • 修改命令:sysctl -w net.core.netdev_max_backlog=2500;注意该值不能低于任一接口的 rx_queue_size(如有 DPDK 或 XDP 场景)

veth 和宿主机 eth0 的 txqueuelen 能设成不同值吗

可以,而且通常应该不同。veth 是纯内存通道,无物理介质限制;而 eth0 受网卡驱动、TSO/GSO、ring buffer 等硬约束,两者队列意义完全不同。

  • veth 的 txqueuelen 影响的是 qdisc 排队行为(如 fq_codel 的内部队列),调大能缓解突发;eth0 的同名参数更多影响驱动层 ring buffer 映射,设太大可能浪费内存且无收益
  • 常见误配:把 eth0 的 txqueuelen 也拉到 10000,结果发现 ethtool -g eth0 显示 ring buffer 没变,实际队列仍被驱动截断——此时真正瓶颈在 rx/tx ring size,不是 txqueuelen
  • 建议组合:vethX: 5000eth0: 1000~2000(保持默认或略增即可),重点调 net.core.netdev_max_backlog 和 qdisc 类型(如换用 fq 替代 pfifo_fast

调完参数却看不到 tx_dropped 下降?检查这三个地方

丢包不一定发生在 veth 队列层,tx_dropped 计数器涵盖多个路径,光调参数不排查链路容易白忙。

  • 确认计数器归属:cat /proc/net/dev 看的是 Interface 层统计,但 veth pair 中 A→B 流量的 tx_dropped 在 A 上,B 上对应的是 rx_dropped;别只盯一个方向
  • 检查 qdisc 是否生效:tc qdisc show dev veth0,如果显示 pfifo_fast 且未限速,那 txqueuelen 就是唯一缓冲;若用了 sfqcodel,它们有自己的队列逻辑,txqueuelen 仅作上限
  • 排除上层丢包:netstat -s | grep -A 5 "packet receive errors",若 receiver errorslisten overflows 高,问题其实在 socket backlog(net.core.somaxconn)或应用读取慢

参数只是杠杆,支点永远在具体路径的瓶颈位置。veth 队列和 softirq backlog 是高频坑点,但别让它掩盖了应用层读写失衡或 cgroup 限速这类更隐蔽的问题。

text=ZqhQzanResources