Skip to content

SPDK 与 DPDK

DPDK 和 SPDK 是虚拟化基础设施中容易被低估的两个组件。它们做的事情用一句话概括:把内核从 IO 数据路径上移除。DPDK 处理网络包(Data Plane Development Kit),SPDK 处理存储 IO(Storage Performance Development Kit),两者的架构思想完全同源——用户态程序通过轮询和直接硬件访问绕过内核协议栈,将 IO 延迟从微秒级压到亚微秒级。

为什么内核 IO 路径成为瓶颈

传统的内核网络路径是中断驱动的:网卡收到数据包 → 触发中断 → CPU 切换上下文进入内核态 → 协议栈逐层处理 → 拷贝到用户态缓冲区。这个路径在低负载下完全够用,但在高包速率下暴露两个根本问题:

中断开销。万兆网卡满载时每秒到达约 1480 万个最小包,每个包一次中断意味着每秒 1480 万次上下文切换。中断风暴下 CPU 将全部时间花在"进入内核态-处理一个包-返回用户态"的固定开销上,实际处理数据的计算占比反而很少。

拷贝开销与系统调用边界。每个数据包从网卡 DMA 缓冲区到用户程序,中间经历多次拷贝和系统调用。每次系统调用本身的固定成本(上下文切换、权限检查)在微秒级数据路径上变得不可忽视。

DPDK 的解决方案直接且激进:放弃中断,改用轮询。用户态程序独占网卡(通过 UIO/VFIO 驱动将网卡的寄存器映射到用户态地址空间),以忙等的方式持续检查接收队列。数据包到达后由网卡 DMA 直接写入用户态可见的缓冲区,程序零拷贝处理。轮询牺牲了低负载时的 CPU 效率(空转等待),换来了高负载时的确定性低延迟。

DPDK:用户态网络数据面

DPDK 不是一个网络栈,而是一套数据面开发库。它提供:巨页内存管理(减少 TLB miss)、无锁环形队列(核心间的零拷贝通信)、批量收发包 API(摊薄每次调用的固定开销)、以及各网卡厂商的 PMD(Poll Mode Driver)驱动。

DPDK 在虚拟化基础设施中的核心场景是 vhost-user——虚拟机与宿主机之间的高速包转发。传统的 virtio 网络路径中,每个包需要 VM exit 到 hypervisor、由 QEMU 转发到宿主机网络栈;vhost-user 将数据面直接放到一个用户态 DPDK 进程(通常是 OVS-DPDK),虚拟机通过共享内存环形队列与这个进程直接交换数据包,完全绕开 QEMU 和宿主机内核。云计算中 OpenStack 的高性能网络平面(OVS-DPDK)、NFV 的虚拟网络功能(vSwitch、vRouter)都建立在这个机制上。

SPDK 是 DPDK 思想在存储领域的复制。它把 NVMe 设备的控制队列映射到用户态,用户程序直接向设备提交 IO 命令,绕过内核的块设备层和文件系统。SPDK 的典型性能:单核可驱动数百万 IOPS——这是内核路径(受限于中断和锁竞争,单核约十万级 IOPS)的十倍以上。

在虚拟化中的应用形态

DPDK/SPDK 在虚拟化中解决的核心问题是IO 性能的虚拟化损耗。虚拟机每次 IO 操作触发 VM exit——这个硬件级别的上下文切换成本是微秒级的,当 IO 延迟目标本身只有几十微秒时,虚拟化开销占比不可接受。

vhost-user:如上所述,将数据面放到宿主机用户态进程,虚拟机通过共享内存直接通信。这是 DPDK 在虚拟化中的主力形态。

SR-IOV:另一种思路是绕过软件数据面——网卡硬件将自己虚拟为多个 PCIe 功能(VF),每个 VF 直接分配给虚拟机。虚拟机的网络 IO 完全不经过宿主机 CPU——数据从网卡 DMA 直达虚拟机内存。性能最优(接近裸机),但代价是失去软件交换机的灵活性(流量不再经过可编程的 vSwitch,无法做虚拟网络的统一策略管理)。生产实践中常见 SR-IOV 与 vhost-user 混合:东西向流量走 vhost-user(灵活但经过 vSwitch),南北向大流量走 SR-IOV(直通硬件)。

SPDK 的 vhost 后端:QEMU 虚拟机可以用 SPDK 作为 virtio-blk 的后端——虚拟机发出的块 IO 请求被 SPDK 用户态进程直接提交给 NVMe 设备,绕开宿主机内核的块层。Ceph 的 RBD 后端、云厂商的本地 NVMe 云盘,很多都在这条链路上运行。

与容器生态的关系

容器化的数据面应用(5G 核心网的用户面、高频交易系统、边缘计算网关)大量使用 DPDK/SPDK。容器对这种应用的适配点在于:巨页内存(容器需要 hostPath 挂载 /dev/hugepages)、设备直通(需要 privileged 容器或设备插件)、CPU 亲和性(轮询进程需要独占 CPU 核,避免被调度器迁移破坏缓存局部性)。Kubernetes 的 Multus CNI 和 NFV 相关项目(如 NFD、SRIOV 设备插件)都是为这类负载服务的生态组件。

选型视角

DPDK/SPDK 不是"更快的替代品"——它们是有明确代价的技术路线。轮询模式放弃了 CPU 节能(核心持续满载)、放弃了内核协议栈的成熟功能(TCP 协议栈需要自己引入或降级为 UDP)、放弃了操作系统的调度和隔离(进程崩溃直接影响数据面)。选择它们的前提是:IO 性能是核心瓶颈,且业务可以接受这些代价。

对大多数业务虚拟机而言,virtio + 内核协议栈的性能已经足够。DPDK/SPDK 的价值集中在两个场景:承载高 IOPS 负载的虚拟化基础设施本身(vSwitch、存储网关),和需要确定性微秒级延迟的数据面应用。识别"是否需要绕开内核"的朴素判断标准:当 IO 延迟的抖动开始主导业务指标时,就是该考虑数据面技术的时候。