摘要:
人们对无服务器计算越来越感兴趣,无服务器计算是一种云计算模型,可自动执行基础架构资源分配和管理,同时仅根据客户使用的资源向客户收费。
这些无服务器框架的高弹性和细粒度,将带来诸如流处理之类的工作量。但是,到目前为止,服务器CPU有限的并发性和高延迟阻止了许多交互式工作负载(例如,Web服务器和数据库客户端)利用无服务器计算来实现高性能。在
本文中,我们认为服务器CPU不适合运行无服务器工作负载(即lambda),并且提出了λ-NIC(一种开源框架),该框架直接在SmartNIC上运行交互式工作负载;更具体地说,是基于ASIC的NIC,它由网络处理单元(NPU)内核的密集网格组成。
λ-NIC利用SmartNIC靠近网络和大量NPU内核的方式,在具有严格尾延迟保证的情况下,在单个NIC上同时运行数千个lambda。为了简化lambda的开发和部署,λ-NIC公开了基于事件的编程抽象,Match + Lambda和一种机器模型,该模型允许开发人员在SmartNIC上轻松编写和执行lambda。我们的评估表明,λ-NIC分别在工作负载的响应延迟和吞吐量方面分别提高了880倍和736倍,同时显着减少了主机CPU和内存使用量。
背景/问题:
无服务器计算正在成为一种主动式云计算模型,该模型使开发人员仅专注于核心应用程序即可将工作负载构建为细粒度的自定义程序(即lambda),而不必担心其运行的基础架构。
云提供商针对这些工作负载动态地配置,部署,修补和监视基础架构及其资源(例如,计算,存储,内存和网络);租户仅需支付以毫秒为单位消耗的资源。无服务器计算降低了进入门槛,尤其是对于缺乏专业知识,人力和预算来有效管理基础架构资源的组织而言。
如今,所有主要的云供应商都提供某种形式的无服务器框架,例如Amazon Lambda,Google Cloud Functions和Microsoft Azure Functions,以及像OpenFaaS 这样的开源版本和OpenWhisk 。这些框架依赖于服务器虚拟化(即虚拟机(VM))和容器技术(即Docker)来执行和扩展租户的工作负载。
但是,在无服务器计算中,对租户隐藏了服务器管理,这些虚拟化技术变得多余,不必要地消耗了无服务器工作负载的代码大小,并导致处理延迟(数百毫秒)和内存开销(数十兆字节)。这些增加的开销还限制了这些工作负载在单个服务器上的并发执行(少于一百个左右),因此,增加了在数据中心中运行此类工作负载的总体成本。
云计算行业现在已经意识到了这些问题,一些提供商(例如Google和CloudFlare)已经开始开发替代框架(例如Isolate [42]),以删除这些技术层(例如容器)并直接在无服务器上运行无服务器工作负载裸机服务器。
然而,这些裸机替代品固有地受到基于CPU架构的设计限制的限制,而在以云数据中心规模运行时,这种限制会加剧。 CPU被设计为以极快的速度处理指令序列(即函数)。它们并非旨在并行运行数千个此类小型离散功能—典型的服务器CPU具有约4至28个内核,最多可同时运行56个线程。每个无服务器功能都会中断CPU内核以存储当前正在运行的功能的状态(例如,寄存器和内存),并使用新的功能对其自身进行加载,从而导致每个上下文切换浪费了数十毫秒的CPU周期(这种浪费的周期增加了云提供商的总成本。
最近,公共云提供商正在尽力部署SmartNIC,以减少主机CPU上的负载。
无服务器工作负载的设计规模很小,为SmartNIC提供了独特的机会来加速它们,同时还实现了严格的尾部延迟保证。
但是,使用SmartNIC的主要缺点在于编程的复杂性。对SmartNIC进行编程是一项艰巨的任务,需要对NIC的系统和资源体系结构(例如,内存层次结构,多核并行性和流水线方法)非常熟悉。开发人员需要仔细划分,调度和仲裁这些资源以最大化其应用程序的性能,这是与无服务器计算背后的动机相反的特征(即,开发人员不了解底层基础架构的架构细节)。此外,每个应用程序都必须显式处理数据包,因为SmartNIC中没有网络堆栈的概念。
解决办法:
提出了λ-NIC,这是一个完全在SmartNIC上运行交互式无服务器工作负载的框架。 λ-NIC支持新的编程抽象(Match + Lambda)和机器模型(是P4的matchaction抽象的扩展,具有更复杂的动作),并有助于以多种关键方式解决SmartNIC的缺点。
首先,用户提供自己的Lambda,由λ-NIC编译,然后在运行时通过匹配传入请求的数据包的报头选择执行。
其次,用户在假设内存模型的情况下编程其lambda。 λ-NIC分析内存访问模式(即读取,写入或两者兼有)和大小,并在NIC的不同内存层次结构之间最佳地映射这些lambda,同时确保隔离内存访问。
λ-NIC会推断每个lambda使用哪些数据包头,并自动为这些头生成相应的解析器,从而无需在这些lambda中手动指定数据包处理逻辑。
第四,λ-NIC无需跨多个NPU划分和调度单个Lambda,而是采用了运行到完成(RTC)模型的方式,利用了Lambda很小且可以在单个NPU内运行的事实。大量的NPU核心和lambda的短服务时间进一步缓解了导致高尾部延迟的行头阻塞和性能问题。
最后,无服务器功能通常使用独立的,互斥的请求-响应对进行通信,并且不需要TCP提供的严格的有序流传输语义。
因此,λ-NIC与RDMA一起使用了弱一致性的传递语义,用于无服务器工作负载之间的通信-直接在NIC核心内处理请求,而无需主机CPU。
实现细节:
图1说明了当今使用的四个不同的云计算框架。服务器虚拟化是云计算下最重要的技术,它允许裸机服务器托管多个VM,每个VM都有各自独立的隔离环境,其中包含单独的操作系统(OS),库和应用程序。正是在这种情况下,硬件的发展使单个应用程序难以有效地消耗整个裸机服务器资源,而在单个服务器上同时存在多个应用程序却引发了各种问题(例如隔离和资源争夺)。但是,随着趋势从整体式发展为微服务构建应用程序[58],以提高可管理性,弹性和可伸缩性,不再需要为每个微服务使用单独的操作系统而产生的开销。
随之而来的是容器虚拟化,这是在共享操作系统的同时隔离应用程序的二进制文件和库的一种方法。但是,随着云工作负载的复杂性和规模不断增长,对于许多用户而言,调配和管理基础结构资源的工作变得艰巨,而这些任务需要在不断变化的工作负载需求下对资源进行重新分配。
早期的解决方案主要是过度配置这些资源,从而增加了闲置资源的成本。最近,无服务器计算[59]成为一种有利的计算模型,它通过让用户仅指定工作负载,其内存和时序约束以及何时和哪些事件(例如,事件)来减轻用户的此类操作和财务负担。 API调用,数据库更新,传入数据流)来触发它们。作为响应,云提供商独立配置基础结构资源,按需部署一组容器来满足工作负载的请求。一旦工作负载完成,这些容器将被快速拆除,并且仅在执行容器时向用户收费。因此,无服务器工作负载的寿命很短,并且具有严格的计算时间和内存限制(对于Amazon Lambda [14],分别达到15分钟和3 GB)。
图2描述了典型的无服务器计算框架。 工作量管理器将用户的工作量编译为可执行的二进制文件,并将其与数据的依赖关系一起存储在全局存储中(例如,Amazon S3 [7],Google Cloud [31]或Microso‰Azure Storage [46])。 网关将用户的请求(或事件)代理到适当的工作负载,这些工作负载通常作为容器在一组称为工作节点的动态配置的服务器上运行。 完成后,结果将被写回到存储或转发给其他工作负载以进一步执行。
如今,无服务器框架已在两种类型的用例中成为应用程序[13、29、96]:(1)运行服务于交互式应用程序的API后端,例如返回静态或动态内容或基于用户请求的键值响应。 (2)实时处理数据存储中的更改,例如裁剪新上传的图像或对新添加的数据库条目运行自定义操作。 lambda函数的复杂性从运行简单的算术运算到做出通常是短暂的机器学习决策不等。裸机服务器可以容纳数千个此类lambda函数。
但是,这样做会导致CPU不断在这些功能之间进行上下文切换。这些以及其他通信开销使服务(使用Lambda函数)难以满足其尾延迟服务级别目标(SLO)[42]。为了减轻这些问题,正在努力将计算移至SmartNIC。
这些SmartNIC分为三种不同类型:基于FPGA,ASIC和SoC [56]。表1总结了主要区别。
λ-NIC背后的主要动机是通过以下方法来加速无服务器的交互式工作负载:(1)减轻过多的计算和网络虚拟化开销以及现代服务器体系结构的不足,以实现低和有限的lambda功能尾部延迟;以及(2) 利用正确的特定领域的架构,(即,基于ASIC的SmartNIC)来维持高吞吐量,同时减少云数据中心的CPU负载和每单位成本。
λ-NIC:
在λ-NIC中,用户以一种受限的类似于C的语言(称为Micro-C [27])提供一个或多个lambda。清单1显示了顶层函数的签名,每个lambda必须以该签名开头, 具有两个参数:标头和match_data。 λ-NIC中所有支持的标头的编号和结构(即EXTRACTED_HEADERS_T数据结构)和功能参数(即MATCH_DATA_T)均按先验定义。 lambda直接在这些参数和标头上操作,而不必解析数据包,这是在解析阶段完成的(图3)。 此外,这些函数可以同时具有局部对象和全局对象,这些对象可以在运行之间保持状态不变。
清单2显示了作为Web服务器运行的lambda的真实示例。该函数从headers变量中读取服务器地址(第6行)。然后,它将请求的Web内容从内存中复制到服务器地址所指向的标头位置(第8行),然后再返回。
最后,工作负载管理器将lambda(MicroC代码)和match阶段(P4代码)配对到单个Match + Lambda程序中,并为其添加了通用的P4数据包解析逻辑。然后,它将程序编译并转换为目标SmartNIC可以执行的格式(第5节),同时确保公平分配资源和隔离lambda工作负载之间的隔离。
在λ-NIC中,用户将其Match + Lambda工作负载针对抽象的机器模型编写(图3)。在此模型中:(1)Lambda是独立的程序,它们不共享状态并且彼此隔离;只有匹配的规则才能调用这些功能。 (2)匹配阶段用作调度程序(类似于OS网络堆栈),用于将数据包转发到匹配的lambda或主机OS。最后,(3)解析器处理数据包操作(如标头识别),而lambda直接在解析的标头上进行操作。 Match + Lambda机器模型的这些特性使软件开发人员更容易通过分离解析和匹配逻辑来表达无服务器功能,并且使硬件设计人员能够在其目标SmartNIC上有效地支持该模型(第5节)演示了一种使用Netronome SmartNIC的实现。因此,抽象机器模型实现了独特的优化,使无服务器工作负载可以作为lambda并行运行,而不会互相干扰。
在本节中,我们介绍在启用P4的Netronome SmartNIC上的λ-NIC的实现(图4)。这些NIC包含数百个RISC核心,这些核心被分组到各个island中。每个内核都有自己的指令和本地内存,以及每个island都有一个群集目标内存(CTM)[27],并且能够同时执行多个线程。信号也是所有island及其内核之间共享的片上内部存储器(IMEM)和外部存储器(EMEM);专用调度器单元将传入的数据包定向到核心。因此,Netronome SmartNIC的体系结构具有必要的元素,可以有效地实现λ-NIC的Match + Lambda抽象机模型:内核可以执行lambda来完成(D1),数据可以驻留在不同的内存中(例如,本地,CTM (或更多)基于它们的使用方式(D2),并且调度程序可以将RPC定向到lambda(D3)。更具可编程性的调度器(例如,基于RMT / PIFO的[37,94])可以直接执行机器模型的解析和匹配阶段,而内核仅处理lambda逻辑。但是,我们用于评估的Netronome NIC内的调度程序是不可编程的。它节省了工作,并且将传入的trac均匀地分布到所有核心。因此,我们在一个内核中一起执行所有三个阶段(解析,匹配和lambda),每个内核运行相同的Match + Lambda程序。4,5对于单数据包消息,调度程序将传入的数据包随机定向到一个内核,该解析器使用数据包中嵌入的ID来选择匹配的lambda。多数据包消息通过RDMA传输到内存,lambda从所需位置直接读取。