论文部分内容阅读
近年来,随着基础网络建设和网络业务的快速发展,传统的网络架构在成本、灵活性以及快速业务开发等方面越来越难以满足要求。不少企业,包括各种运营商和硬件提供商,开始研究并实践网络功能虚拟化(Network Function Virtualization,NFV)。网络功能虚拟化旨在将以往由硬件实现的网络功能,通过软件的方式运行在通用的管理平台上,从而带来更低的成本和更高的管理效率。NFV在应用过程中最大的问题是性能表现难以满足要求。因此,大量工作研究如何尽可能提升网络功能在通用设备上的性能。这些工作通过减少数据包在物理/虚拟网络中不必要的内存拷贝和CPU开销,来提高网络功能的吞吐量并减少延迟。而随着单个网络功能性能研究的推进,有不少工作研究网络功能链整体性能优化技术。面向网络功能链的性能优化更具有实际价值,因为企业在部署网络业务的时候,往往需要多个网络功能共同协作,形成链式结构。对于部署在多核系统上的网络功能链,网络管理人员往往会根据具体的业务性能要求,为网络功能链分配相应的CPU资源并进行合理的部署。但是存在一些网络功能链,无论网络管理人员如何部署调优,都无法充分地利用CPU资源,进而无法表现出很好的吞吐量。这类网络功能链的特点是,链上的不同网络功能之间处理数据包的时间相差比较大,并且每个网络功能运行在单独的线程(操作系统的最小调度实体)中。在这种情况下,处理时间较长的网络功能会主导整一条链的性能,而由于单线程最多在一个CPU核心上运行,主导的网络功能也最多只有一个CPU核心的处理能力,这会导致整一条链的性能出现瓶颈。为了避免这种瓶颈,我们需要将网络功能运行在多个线程中,以提升单个网络功能的处理能力。一种处理方式是在每个线程中并行执行同一份逻辑代码,但是对网络功能链来说,这种并行的处理方式由于没有考虑数据包之间的顺序依赖,会引入正确性、通用性和性能方面等诸多问题。为了解决网络功能链部署的瓶颈问题同时避免引入其他问题,本文提出按处理时间分割网络功能的思路。具体来说,我们将网络功能根据数据包处理流程分成几个阶段,每个阶段分别在一个线程中运行。任意一个数据包的处理都要按顺序经过这几个线程,使得每个线程的处理时间大体相同,并最终得到与单线程方式相同的结果。我们用代码分割的方式来实现上述的思路,主要的做法是用代码运行的指令条数来近似地代替处理时间的长短,通过分割不同的代码到不同的线程中来实现按处理时间分割的思想。代码分割在具体实施的时候存在两个难点,第一,分割后的代码可能存在各种需要在线程之间传输的临时变量,这会增加额外的代码工作量,产生巨大的人力开销,同时大量的变量传输也会引起性能上的不稳定;第二,代码运行过程中执行的指令条数与多种因素相关,依靠人脑很难精细化地分割代码,而粗略的划分可能导致某一部分处理的时间太长,进而让整条链产生性能瓶颈。为了解决这两个难点,我们设计了类似协程的机制来解决临时变量的传递问题,同时基于中间描述语言LLVM/Clang实现了自动化的代码分割工具。借助于我们设计的系统ChainSplit,部署人员可以很方便地对VNF链进行代码分割与部署。我们的实验表明,对于处理时间各异的VNF链,ChainSplit可以一直保持较高的性能;对于其中一些存在瓶颈的VNF链,ChainSplit相比普通的部署方式在多核情况下至少提升60%的吞吐量;在性能扩展性方面,ChainSplit可以让VNF链的性能随着分配CPU资源的增加而增加,最好情况下能够随着CPU核数增多而接近线性地提高其吞吐量。