关键在于“网卡队列—cpu核心—应用线程”三者对齐:先用ethtool -l、/proc/interrupts和lscpu确认硬件多队列支持与cpu拓扑,再按场景选rss(物理机)、rps/rfs(虚拟机或老旧设备),同步调优xps、ring buffer及netdev_max_backlog等内核参数。

要让 Linux 网卡真正扛住高并发访问,关键不是堆参数,而是让“网卡队列—CPU核心—应用线程”三者对齐。单靠调大某个值(比如把队列设成64)反而可能因中断不均或缓存失效拖慢整体性能。
先确认硬件能力:别在单队列网卡上硬配 RSS
很多问题其实出在第一步就错了——网卡根本不支持多队列,却强行调参。执行这三条命令快速判断:
- ethtool -l eth0:看 Combined 字段的 Current hardware settings 值。大于 1 才表示当前已启用多队列;若为 1,RSS 就无法生效
- cat /proc/interrupts | grep eth0:观察中断号是否分散(如 eth0-TxRx-0、eth0-TxRx-1…),若只有一行带 eth0,说明中断全挤在单个 CPU 上
- lscpu | grep "CPU(s)" 和 numactl --hardware:确认逻辑 CPU 数与 NUMA 节点分布,队列数一般不应超过可用逻辑核数(例如 16 核服务器,设 16 队列比设 32 更稳)
接收侧优化:按场景选 RSS、RPS 或 RFS
RSS 是首选,但只在硬件支持时有效;RPS/RFS 是软件兜底方案,适合老旧设备或虚拟机:
- RSS(推荐用于物理服务器):用 ethtool -L eth0 combined N 设定队列数(N 通常 = CPU 核心数),再配合 irqbalance --numa 或手动绑定中断到对应 CPU(echo 0-3 > /proc/irq/*/smp_affinity_list)
- RPS(单队列网卡必开):启用前先设全局流表大小:echo 32768 > /proc/sys/net/core/rps_sock_flow_entries;再为每个 rx 队列指定可用 CPU 掩码,例如 echo ff > /sys/class/net/eth0/queues/rx-0/rps_cpus(ff = 前 8 核)
- RFS(延迟敏感型服务如实时 API):在 RPS 基础上开启,需同步调大 flow limit:echo 32768 > /proc/sys/net/core/rps_flow_cnt;它会把同一连接的数据包尽量导向正在处理该连接的应用线程所在 CPU,提升 L1/L2 缓存命中率
发送侧与缓冲区协同调优
只优化接收不碰发送,容易出现“收得快、发不出”的瓶颈:
- XPS(发送路径亲和):避免跨 CPU 访问 TX 队列,写入十六进制掩码到 /sys/class/net/eth0/queues/tx-0/xps_cpus,确保与对应 RX 队列绑定在同一组 CPU 上
- Ring Buffer 扩容:突发流量下小 buffer 容易丢包,用 ethtool -G eth0 rx 4096 tx 4096 把收发环形缓冲区从默认 256–512 提至 2K–4K(注意:最大值查 ethtool -g eth0,不能超限)
- 软中断均衡:检查 cat /proc/softirqs | grep NET_RX 是否集中在少数 CPU;若失衡,可临时用 taskset -c 0-7 nice -n -20 irqbalance 限定其运行范围,或改用静态绑定
配套内核参数不可少
网卡队列只是入口,后端协议栈和内存必须跟上:
- 连接队列扩容:net.core.somaxconn = 65535、net.core.netdev_max_backlog = 5000、net.ipv4.tcp_max_syn_backlog = 65535
- TIME_WAIT 快速回收:启用 net.ipv4.tcp_tw_reuse = 1 + net.ipv4.tcp_timestamps = 1(公网服务慎开 tcp_tw_recycle)
- 端口与缓冲区:net.ipv4.ip_local_port_range = "1024 65535";TCP 缓冲区设为 net.ipv4.tcp_rmem = "4096 65536 16777216",避免小包拷贝和大流阻塞











