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

为什么 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: 5000,eth0: 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就是唯一缓冲;若用了sfq或codel,它们有自己的队列逻辑,txqueuelen仅作上限 - 排除上层丢包:
netstat -s | grep -A 5 "packet receive errors",若receiver errors或listen overflows高,问题其实在 socket backlog(net.core.somaxconn)或应用读取慢
参数只是杠杆,支点永远在具体路径的瓶颈位置。veth 队列和 softirq backlog 是高频坑点,但别让它掩盖了应用层读写失衡或 cgroup 限速这类更隐蔽的问题。










