在SPDK中使能E810网卡ADQ 特性
--改善TCP/IP 存储应用的性能
最近Intel发布了最新的100Gbps的以太网网卡控制器E810, 这款新的网卡不仅支持两种不同协议的RDMA 协议(iWARP 和RoCE v2),并且针对基于TCP/IP协议的应用(包括各种使用网络的应用)给出了基于ADQ(Application Device Queues)特性的性能改善方案,可用于改善网络应用的性能(诸如平均或者长尾延迟,以及throughput等)。
Intel 网卡中的ADQ特性是一种智能的系统级方法,旨在提高网络I/O性能。ADQ特性的目标是确保高优先级应用程序具有可预期的高性能,并显著降低抖动。ADQ的核心技术是将隔离的硬件网卡队列供某些应用程序进行专有使用。并且希望这些硬件网卡队列可以最佳地连接到所需应用程序中的不同线程。显而易见, 这种方法可以防止专有程序的网络流量与其他应用程序竞争,并且该应用程序的性能(例如,延迟)可以变得可预测。此外开启ADQ特性以后,我们仍然可以对专有应用程序在队列上提供QoS控制。
图1 Without ADQ那部分的图,给出了不使用ADQ的例子(也就是正常网卡的包处理)。如果把图中不同颜色的汽车看成不同的应用,不同的车道看成不同的网卡队列,我们可以看到同一个网卡队列上可以同时处理不同应用的网络包。这样的处理方法是通用的,但是不利于某些专有应用的QoS 控制。图1中使用了ADQ以后,我们可以看到某些网络队列可以直接分配给某些专有应用,于是这些应用的网络包可以在特定分配的队列上被处理,和其他应用程序隔离,继而可以进行后续的QoS控制。
图1 ADQ特性的开启以及关闭
总结一下ADQ隔离队列的思想,和DPDK/SPDK PMD的思想有些相似。基于DPDK的application可以去操纵分配给这个应用的物理队列,这一点来讲和ADQ的思想是完全相同的。唯一的区别是目前DPDK只工作在层3以下,所以工作在TCP/IP层的应用想要通过DPDK PMD驱动来享受到隔离队列的特性,必须使用基于DPDK的用户态TCP/IP栈。所以从这一点看来,ADQ的特性通用性更好一些,不需要应用强制使用用户态的解决方案。
另外我们可以看到ADQ的特性,对于多核应用的支持还存在需要加强的地方。因为使用ADQ以后,我们可以分配一些特定的队列给应用。比如给一个应用程序A分配4个队列,这个可以保证应用程序对这4个队列的独享 。但是如果这个应用是使用多CPU的,那么这个应用的多个线程(可能运行在不同的CPU core上)形成对这4个队列的内部竞争。我们在SPDK库中的集成工作,就是为了避免内部竞争的出现。
为了更好地解释SPDK库中ADQ的集成, 图2给出了SPDK NVMe-oF TCP应用使用ADQ的例子。首先在SPDK NVMe-oF TCP应用启动之前,需要做一些配置工作,诸如分配一些网卡队列,对应到不同的TC (traffic class)。于是监听在以下三元组的
图2 SPDK NVMe-oF集成ADQ的特性
为了实现图2中的使用需求,在SPDK SOCK库中,我们做了以下的工作,使得使用SPDK库的应用诸如NVMe-over TCP target可以更好地使用分配的队列。
在SPDK 的thread 设计中,每一个SPDK thread都可以使用一个polling group。这个polling group中可以处理所有归属于这个polling group处理的连接。比如在NVMe-oF target (app/nvmf/nvmf_tgt)以及相关的库(module/event/subsystems/nvmf/, lib/nvmf)实现中, 当NVMe-oF target启动以后,每个Reactor线程上启动一个NVMe-oF的SPDK thread,然后这个SPDK thread上会运行一个polling group。这个polling group可以处理不同transport上的polling group,诸如RDMA,TCP或者Fibre Channel上的各个polling group的连接。
所以在没有使用ADQ之前, 每一个SPDK thread上的TCP polling group处理的TCP连接,可能位于不同的队列上。而使用ADQ之后,处理的TCP连接可能分布在有限的几个队列上。举个例子,如果SPDK的NVMe-oF TCP应用使用了两个CPU core,被分配了4个队列。那么每个CPU core上运行的sock polling group能处理到4个不同的队列。那么这两个CPU对于网卡队列还是存在竞争关系。原则上,我们需要让不同的CPU core去处理不同的队列,才是效率最高的。也就是说, 假设一个CPU core i上处理的网卡队列集合是 N(i), 那么任意的CPU之间处理的网卡队列的交集都是空集,也就是:For any CPU core i and j, N(i) ∩ N(j) = ∅ 。
为了满足这一实现,我们在SPDK的sock library中,维护了placement_id(网卡队列的NAPI_ID在SPDK sock库中被抽象为placement_id)到sock polling group的映射, i.e.,
如果在nvmf层的逻辑中,通过查询spdk_sock_get_optimal_sock_group得到无效的sock_polling_group,就会采用默认的算法, 比如使用Roundrobin的算法(如图2所示)进行调度,寻找一个SPDK thread;如果发现了有效的sock_polling_group,我们就会找寻这个sock_polling_group的创建者(意思是由哪个SPDK thread创建),然后交由这个SPDK thread处理。无论哪种方式,我们最终都会到一个SPDK thread去处理这个连接,最后我们将会更新这个placement_id和对应的sock_polling_group的映射信息。此外, 在一个socket被一个polling group移除的时候,我们也要对placement_id和sock_polling_group相应的映射进行维护。
图3给出了同样硬件环境下,服务器端的SPDK NVMe-oF TCP target程序使用ADQ特性后的性能变化。我们可以看到在使用ADQ以后,可以更高效地利用CPU资源, 比如SPDK NVMe-oF TCP target使用5个CPU core,就基本可以达到E810网卡的line rate。如果不开启,那么可能需要使用6-7个CPU core。并且在1-5个CPU core的配置下,在ADQ模式和非ADQ模式下运行同样的工作负载,ADQ模式可以提升IOPS以及降低延迟。图4给出了同样测试下,长尾延迟(p99, p999以及p9999)的改善。我们可以看出使用了ADQ特性以后,NVMe-oF TCP target应用的可预测性有了很大的改善,也就是延迟的普遍降低趋势。
图3 SPDK NVMe-oF TCP性能
图4 长尾延迟的改善
总结
这篇文章中主要介绍在通过SPDK SOCK库中怎样透明的向上层模块暴露出Intel E810网卡的ADQ(Application Device Queue)的特性。一旦系统开启ADQ的支持,基于TCP/IP的服务器端存储应用可以得到很好的性能提升,比如IOPS的提升以及延迟的降低。
学习地址:http://ke.qq.com/course/5066203?flowToken=1043717
更多DPDK学习资料有需要的可以自行添加进入学习交流君 羊 793599096 免费获取,或自行报名学习,免费订阅,永久学习,关注我持续更新哦!!!
原文链接:https://blog.csdn.net/weixin_37097605/article/details/109349046