导读:本期聚焦于高宇创作的《NUMA架构下如何优化网络性能?网卡与CPU绑定的正确做法》,敬请观看详情。服务器网络吞吐量上不去,延迟抖动明显,问题可能不在网卡本身,而在NUMA架构下的资源分配。现代多路服务器普遍采用NUMA设计,CPU和内存被划分到不同节点,如果网卡中断落在远离网卡所挂载节点的CPU上,跨节点访问会带来明显的性能损耗。本文从NUMA的基本原理讲起,介绍如何查看网卡所属的NUMA节点,如何通过irqbalance配置、中断亲和性设置以及进程绑核等手段,让网卡中断与数据处理跑在同一个NUMA节点上,并给出具体的命令操作和验证方法,帮助充分发挥高速网卡的性能。

在万兆、二十五兆网卡已经普及的今天,不少运维人员发现一个奇怪的现象:同样的硬件配置,有的服务器网络吞吐轻松跑满,有的却只能跑到六七成,延迟还抖动得厉害。排查网卡、交换机、驱动都没问题,最后往往发现症结出在NUMA架构的资源分配上。本文就来详细聊聊为什么要把网卡和CPU绑定在同一个NUMA节点,以及具体该怎么操作。

NUMA架构下如何优化网络性能?网卡与CPU绑定的正确做法

一、为什么NUMA架构会影响网络性能

要理解这个问题,先要从NUMA(Non-Uniform Memory Access,非统一内存访问)架构说起。早期的服务器是对称多处理器(SMP)架构,所有CPU通过同一条总线访问内存,访问延迟是一致的。但随着CPU核心数增加,总线成为瓶颈,于是厂商把CPU和内存划分成多个节点,每个节点内部的CPU访问本节点内存速度很快,跨节点访问则要通过互联总线(Intel的QPI或UPI,AMD的Infinity Fabric),延迟明显增加,带宽也会打折扣。

网卡作为PCIe设备,同样物理上挂载在某个NUMA节点下。当网卡收到数据包时,会产生硬件中断,内核的中断处理程序会在接收中断的CPU上执行,随后数据包会被复制到该CPU可以快速访问的内存区域,上层应用如果恰好在另一个节点上运行,就要跨节点读取这些数据。一次两次没什么感觉,但在每秒上百万包的高吞吐场景下,跨节点访问的累积开销就非常可观了,实测中跨NUMA节点的处理可能带来20%到40%的性能损失,延迟抖动也会加剧。

典型的不良状态是这样的:一块二十五兆网卡插在NUMA 0节点的PCIe插槽上,但中断亲和性设置不当或者irqbalance把中断分散到了NUMA 1的CPU上,应用进程又被调度器随机分配,结果每个数据包都要在两个节点之间来回搬运,QPI总线带宽被白白消耗,cache命中率也大幅下降。

二、如何确认网卡所属的NUMA节点

优化之前必须先摸清现状。Linux内核提供了/sys文件系统来查询PCIe设备的NUMA归属。假设网卡是eth0,先用以下命令找到它的PCIe地址:

# 查看网卡对应的PCIe设备地址
cat /sys/class/net/eth0/device/numa_node

# 如果输出是-1,说明BIOS没有正确上报ACPI信息
# 可以通过lspci找到设备总线地址再查
lspci | grep -i ethernet
cat /sys/bus/pci/devices/0000:19:00.0/numa_node

# 查看当前系统的NUMA拓扑
numactl --hardware
lscpu | grep NUMA

其中numa_node的输出就是网卡挂载的节点编号,通常为0或1。numactl --hardware会列出每个节点包含哪些CPU核心以及内存大小,这是后续绑核的依据。如果输出为-1,多半是BIOS中NUMA功能被关闭了,需要进BIOS开启NUMA选项,否则操作系统会把内存当作统一地址空间处理,性能调优无从谈起。

另外一个常见的坑是irqbalance服务。这个守护进程会自动在CPU之间迁移中断以实现负载均衡,出发点是好的,但对于高速网卡来说,它可能把同一个网卡的不同队列中断分散到不同NUMA节点上,破坏了 locality。在高性能网络场景下,通常建议直接关掉它:

systemctl stop irqbalance
systemctl disable irqbalance

三、中断亲和性与进程绑核的具体操作

现代高速网卡普遍支持多队列(RSS,Receive Side Scaling),每个队列有独立的中断号。理想的做法是把每个队列的中断绑定到网卡所在NUMA节点的不同CPU核心上,实现中断分布与内存局部性兼顾。先看一下网卡的中断情况:

# 查看网卡队列数量
ls /sys/class/net/eth0/device/msi_irqs/ | wc -l
ethtool -l eth0

# 查看中断号与亲和性掩码
grep eth0 /proc/interrupts
cat /proc/irq/128/smp_affinity

假设网卡在NUMA 0节点,而该节点包含CPU 0到15,那么可以把队列中断依次绑定到这些核心上。注意smp_affinity写入的是十六进制位掩码,每个bit代表一个CPU:

# 将中断128绑定到CPU 2(掩码 0x4)
echo 4 > /proc/irq/128/smp_affinity

# 将中断129绑定到CPU 3(掩码 0x8)
echo 8 > /proc/irq/129/smp_affinity

# 批量绑定的简单脚本
irqs=$(grep eth0 /proc/interrupts | cut -d: -f1)
cpu=2
for irq in $irqs; do
    mask=$(printf '%x' $((1 << cpu)))
    echo $mask > /proc/irq/$irq/smp_affinity
    cpu=$((cpu+1))
done

中断绑定只是第一步,应用进程也要跟着绑定。对网络密集型应用(比如DPDK应用、Nginx、高性能网关),使用numactltaskset把进程限制在网卡所在节点的CPU上,同时优先分配本节点内存:

# 使用numactl启动进程,绑定到节点0的CPU并使用节点0内存
numactl --cpunodebind=0 --membind=0 ./your_network_app

# 对已运行的进程进行绑核
taskset -pc 4-11 $(pidof nginx)

# 验证进程的NUMA内存分布
numastat -p $(pidof your_network_app)

对于DPDK这类内核旁路框架,绑核更是标配操作,通常会把网卡队列、工作线程一一对应地绑定到同一NUMA节点的核心上,再配合大页内存分配在本节点,性能才能完全释放。KVM虚拟化场景下则要额外注意vCPU的亲和性设置和vhost线程的绑核,保证虚拟机的收发包路径不跨节点。

四、验证优化效果与常见注意事项

优化完成后需要量化验证。常用的测试组合是用iperf3或qperf打流,配合mpstat观察各核心的软中断(%soft)分布,用numastat观察跨节点内存访问统计。如果优化到位,你会看到软中断集中在网卡所在节点的核心上,跨节点内存流量(numastat中的other_node字段)显著下降,吞吐提升且延迟更稳定。

# 打流测试
iperf3 -c 192.168.0.1 -t 60 -P 8

# 观察软中断分布
mpstat -P ALL 1

# 查看NUMA统计信息
numastat

# 确认中断是否集中
cat /proc/interrupts | grep eth0

有几点注意事项需要提醒。第一,不要把中断绑到CPU 0上,内核的很多基础活动都在CPU 0上执行,绑上去反而互相干扰。第二,绑核要与业务负载匹配,如果网卡所在节点的CPU本身已经满载,绑定反而不如跨节点分担负载,这时应该考虑把网卡换插到另一个节点的插槽,或者调整业务部署。第三,超线程环境下,建议优先使用物理核心,把同一个物理核心的两个超线程留给同一队列的中断和处理线程。第四,容器化环境中要注意cpuset的限制,确保容器的CPU配额落在正确的NUMA节点上,否则在宿主机层面的优化会被cgroup配置抵消。

总的来说,NUMA感知的网络优化是一项收益明确、成本不高的工作,尤其在高吞吐、低延迟场景下效果立竿见影。核心思路就一句话:让数据包从网卡中断、内核处理到应用消费的整个链路,尽量留在同一个NUMA节点内。掌握这个原则,再结合本文的命令工具,基本就能把硬件性能榨取到位了。

NUMA架构网卡绑定网络性能优化修改时间:2026-09-03 04:50:42

免责声明:已尽一切努力确保本网站所含信息的准确性。网站作品多为原创整理与精心创作,观点力求客观中立。本站旨在免费分享,内容仅供个人学习、研究或参考使用。若引用了第三方作品,版权归原作者所有。如内容涉及您的权益,请联系我们进行处理Email:chomcom@qq.com。
引用或转载本作品时,请注明当前出处:https://www.ipipp.com/html/20260903/49339.html,基于非商业用途的前提下,欢迎转载或二创本作品。
内容垂直聚焦
专注技术核心技术栏目,确保每篇文章深度聚焦于实用技能。从代码技巧到架构设计,为用户提供无干扰的纯技术知识沉淀,精准满足专业提升需求。
知识结构清晰
覆盖从开发到部署的全链路。AI、前端、编程、数据库、服务器、建站、系统层层递进,构建清晰学习路径,帮助用户系统化掌握开发与运维所需的核心技术。
深度技术解析
拒绝泛泛而谈,深入技术细节与实践难点。无论是数据库优化还是服务器配置,均结合真实场景与代码示例进行剖析,致力于提供可直接应用于工作的解决方案。
专业领域覆盖
精准对应开发生命周期。从前端界面到后端编程,从数据库操作到服务器运维,形成完整闭环,一站式满足全栈工程师和运维人员的技术需求。
即学即用高效
内容强调实操性,步骤清晰、代码完整。用户可根据教程直接复现和应用于自身项目,显著缩短从学习到实践的距离,快速解决开发中的具体问题。
持续更新保障
专注既定技术方向进行长期、稳定的内容输出。确保各栏目技术文章持续更新迭代,紧跟主流技术发展趋势,为用户提供经久不衰的学习价值。