一周一论文(翻译 总结)— [SOCC 14] DaRPC: Data Center RPC 基于RDMA的高性能通信RPC

目录

Abstract

1. Introduction

2. Motivation

3. Background

4. Design of DaRPC

4.1 Single Client-Server RPC

4.2 Server-Side Processing

4.3 Client-Side Processing

4.4 Reliability, Ordering and Flow Control

5. Application Programming Interface

6. Related Work

7. Conclusion


Abstract

       自80年代初以来,远程过程调用(RPC)一直是分布式系统的基石。 最近,在数据中心中运行的新类型的大规模分布式系统在扩展和延迟方面对RPC系统构成了额外的挑战。 我们发现现有的RPC系统对资源(CPU,内存,网络)的使用非常差,并且还没有准备好处理这些即将到来的工作负载。

       在本文中,我们介绍了DaRPC,这是一个RPC框架,它使用RDMA在用户空间中实现RPC消息处理和网络处理之间的紧密集成。 DaRPC在CPU cores和内存之间有效地分配计算,网络资源和RPC资源,以非常低的每请求延迟(iWARP为10μs)实现高聚合吞吐量(2-3M ops / sec)。 在评估中,我们表明DaRPC可以将云中现有分布式系统的RPC性能提升超过吞吐量和延迟的一个数量级。

1. Introduction

       自80年代初以来,远程过程调用(RPC)一直是分布式系统的关键构建块[5]。 然而,在数据中心运行的新型大规模分布式系统的出现给RPC系统增加了额外的压力。 例如,HDFS,Zookeeper或OpenFlowcontain等系统要求每秒处理大量RPC请求的集中式RPC服务(例如,名称,调度程序,控制器)。 此外,一些提供低延迟数据访问的新系统,如RAM-Cloud [16]或Tango [3],要求超低RPC延迟,同时仍然要求RPC系统扩展到高容量的请求。

       不幸的是,当今基于云的系统中使用的RPC实现很难满足这些要求。 例如,HDFS和Zookeeper中的RPC服务通常可以在200到500μs之间的延迟时间内每秒处理100-200K操作。 其他系统(如Tango中使用的系统)表现更好(60-70μs时600K op / s),但在所有这些情况下,RPC系统的性能远低于硬件(CPU,网络)所能提供的性能。 实际上,我们发现这些系统既不会使网络饱和,也不会使CPU饱和。 最近,已经在网络堆栈级别讨论了类似的低效率。 为了克服这些问题,已经建议在用户空间中实现网络堆栈,同时减少开销[9]。

       在这项工作中,我们更进一步,通过使用远程直接内存访问(RDMA)将RPC处理与用户空间中的网络处理集成在一起。 我们提供DaRPC,这是一种高吞吐量低延迟RPC框架,专为提高数据中心大规模分布式系统的性能而量身定制。 DaRPC中使用的关键思想是协调多核系统中RPC处理和网络的计算和内存资源分配。 这种方法与构建RPC系统的传统方法形成对比,其中RPC消息处理是独立于内核中的网络处理实现的(参见图1)。 通过将RPC处理和网络视为联合优化问题,我们可以避免上下文切换,缓存未命中并实现高度并行性以及超低延迟。

       除了可扩展性和延迟特性之外,DaRPC还提供了一个应用程序界面,可以出于多种原因使其易于用于现有的基于云的分布式系统。 首先,DaRPC完全用Java实现,因此将其性能优势直接推送到Hadoop,Zookeeper或Spark等系统的托管运行。 其次,DaRPC提供了一个纯粹的异步编程接口,允许应用程序使用极少的上下文切换和最小的cache pollution来处理RPC操作。 在内部,DaRPC利用RDMA网络堆栈的异步特性来最大限度地将RPC操作映射到网络操作。

       在本文中,我们在17节点集群上评估DaRPC,既作为独立系统,也作为现有分布式系统(如HDFS)的上下文。 我们证明,在单个服务器系统上,DaRPC可以处理高达2.4M RPC req / sec,在基于以太网的RDMA适配器上延迟低至10μs。 这比当今实践中使用的某些RPC系统的性能要好一个数量级。 我们进一步表明,在客户端使用标准以太网适配器(无RDMA支持)的配置中,可以实现类似的吞吐量增益(具有一些延迟惩罚)。

       总之,本文的贡献包括(1)对当今使用的RPC系统的可扩展性限制和延迟开销的分析(2)DaRPC的设计,它演示了如何联合优化RPC和RDMA网络资源以最大化吞吐量并最大限度地减少延迟 RPC请求处理,以及(3)演示如何在真实云工作负载中使用DaRPC

2. Motivation

       我们使用HDFS和Zookeeper来突出今天云服务中可用的一些内置RPC系统的缺点。之前已经研究过这些系统的RPC性能,但这些研究都是基于千兆以太网网络上的部署[2,22]。虽然千兆以太网仍然是当今数据中心中使用的主导网络技术,但10Gbit / s以太网正变得越来越流行。在使用千兆位以太网的部署中,RPC服务的性能可能受网络带宽的限制。在这项工作中,我们有兴趣研究RPC系统的全部潜力。因此,我们对17节点测试平台进行了一系列测试,该测试平台由双插槽8核Intel Xeon服务器组成,这些服务器通过10 Gbit / s以太网网络互连。图2显示了HDFS中getBlockLocation()操作和Zookeeper中exists()操作的吞吐量和延迟。就吞吐量而言,Zookeeper和HDFS名称节点的扩展速度可达100-130K ops / sec,直到达到饱和点。同时,每个客户端的平均延迟从最初的200μs持续增加到500μs。

       有趣的是,这些数字与使用功能较弱的服务器机器在千兆网络部署上测量的性能数字相同(考虑到Zookeeper的只读工作负载)[2,22]。由此,我们可以假定性能不受服务器上的网络带宽或CPU消耗的限制。我们的测量也证实了这一点,显示在CPU负载不超过15%的情况下最多使用1.6%的带宽(1个内核= 100%)。

       鉴于服务器上的CPU和网络都没有得到充分利用,I / O处理的低效率可能是潜在的瓶颈。 I / O效率低下的示例是高速缓存未命中,过度中断处理或服务器线程之间的不均衡负载平衡。 我们发现对于Zookeeper和HDFS场景,缓存未命中率在25-30%之间,并且每个RPC操作执行大约2个上下文切换。 在本文后面,我们展示了DaRPC只使用很少的上下文切换操作,并且使用较少的缓存未命中,这两种效果都会导致更高的RPC吞吐量和更低的延迟。

3. Background

       在这一点上,我们想简要介绍一下RDMA网络的背景知识。 DaRPC使用jVerbs [23],这是专门为Java虚拟机设计的低延迟RDMA堆栈。 jVerbs通过标准化接口将RDMA网络硬件资源直接暴露给JVM,并在两个联网JVM虚拟机之间传输数据时为Java进程提供众所周知的RDMA功能,如kernel bypass和zero-copy network I / O.

       jVerbs提供了一组丰富的操作,其中post send()/ post recv()操作与RPC消息传递最相关。 通过这些操作,发送方发送消息,而接收方预先发布应用程序缓冲区,指示它想要接收数据的位置。

       应用程序使用jVerbs在网络接口上创建硬件资源,例如send,receive和complete Queue。对于NIC上的每个物理队列,一个队列对象在主机内存中被分配,然后该对象映射到JVM,并且可以由应用程序使用jVerbs直接访问。应用程序将数据传输请求异步发送到Send/Receiv e Queue。数据传输请求(有时也称为工作请求)标识操作类型(例如,Send或Receive)并指向可以从JVM内访问的存储缓冲区。 RDMA NIC处理send / recv队列中的请求(通常称为“Queue Pair”(QP)),并在操作完成后将完成通知放入Complete Queue。Complete Queue(CQ)可以由多个Queue Pair所共享,应用程序可以在轮询模式或阻塞模式下查询它。在数据传输期间,RDMA NIC直接通过DMA以零拷贝方式访问由数据请求引用的用户内存。为了安全地工作,需要使用jVerbs中提供的reg mr API调用向RDMA子系统注册应用程序数据缓冲区。通过这样做,RDMA子系统将确保内存固定且无法换出。此外,要求用于jVerbs数据操作的所有缓冲区都是“Direct”缓冲区类型。 Java提供显式API调用,以在堆的专用区域中分配“Direct”缓冲区,该区域不由垃圾回收机制管理。这对jVerbs至关重要,因为我们不能让垃圾回收机制干扰RDMA的数据操作。

       jVerbs的特殊功能是Stateful Verb Calls(SVC)。 SVC消除了重复数据操作期间发生的任何开销。典型的数据操作如post send()或post recv()需要应用程序准备一组工作请求,而这些工作请求在放置工作时必须由jVerbs序列化 请求进入正确的队列。 对于SVC,可以通过应用程序缓存jVerbs操作到序列化工作请求的整个状态,并在重复操作中重复使用。 这样可以减少CPU消耗以及jVerbs RDMA操作的延迟。

4. Design of DaRPC

       这项工作的最终目标是创建一个满足以下三个要求的RPC系统:

  1. High throughput: 系统应该能够每秒处理大量的RPC请求。 高吞吐量是关键在使用集中式组件(例如,locking服务,OpenFlow Control等)操作的大规模分布式系统的环境中。 单个RPC服务可能必须处理来自数千台服务器的数百万个RPC请求。
  2. Low Latency即使RPC服务器被加载的时候,单个RPC操作的延迟也应该接近原始网络延迟。 如果RPC操作是需要在短时间内完成的一系列序列化操作的一部分(例如,RPC用于存储系统中的元数据查找),则此属性是必不可少的。
  3. Cloud integration该系统可以很简单的用于基于云的分布式系统。

       通过DaRPC,我们通过联合优化用户空间中的RPC处理和RDMA网络来满足前两个要求。 我们通过提供强大的编程接口来满足最后的要求,该接口为JVM中的应用程序缓冲区提供零拷贝RPC。我们将在第5节中描述DaRPC的应用程序编程接口。这里,我们首先关注的是DaRPC的设计。 我们首先在单个客户端 - 服务器场景中说明RDMA和RPC处理的基本相互作用。 在第二步中,我们将了解如何扩展DaRPC的服务器端以有效地处理大量RPC请求。 最后,我们描述了客户端使用的原则,即使在并发访问时也能维持低RPC延迟。

4.1 Single Client-Server RPC

       图3说明了单个客户端和服务器之间DaRPC中简单RPC操作所涉及的基本步骤。 首先,客户端将输入参数和潜在协议数据编组到预先注册的RPC缓冲区中,并触发post send()以向服务器发送消息。 在服务器上,NIC将消息DMA化为RPC接收缓冲区,并将工作完成请求放入服务器的完成队列。 在检测到工作完成事件后,服务器解组消息,执行RPC调用,将response值编组到输出RPC缓冲区中并自行触发post send()以传输响应消息。 一旦客户端检测到新的工作完成事件,它就知道响应消息已到达并已被DMA到其用户空间RPC缓冲区中。 然后,客户端对响应值进行解组并完成RPC调用。

       在DaRPC中,我们利用jVerbs的Stateful Verb Call(SVC)来避免在传输RPC请求或响应时序列化工作请求的任何开销。 具体而言,对于用于发送和接收RPC数据的每个网络缓冲区,DaRPC保留一个预序列化的SVC对象,围绕该对象对给定的操作进行编码,并可立即置于RDMA发送或接收队列中。

       在这样的单个客户端 - 服务器RPC消息交换中,zero-copy network I / O和kernel-bypass的RDMA优势自然会转化为低RPC响应时间。 例如,DaRPC在被隔离的客户端 - 服务器方案中为RPC操作提供10μs的延迟。 这比我们在同一部署中测量的raw RDMA send / recv延迟仅高1μs。

4.2 Server-Side Processing

       关于服务器端,关键的挑战是在多核系统中并行化RPC请求处理,同时避免I / O效率低下,例如上下文切换,锁定或缓存未命中。

       在下文中,通过修改上一节中描述的基本RPC机制的服务器端,我们提出了几个设计选项并讨论了它们的优点和局限性。 我们将说明图5中每个选项对RPC吞吐量的影响。我们与本节一起使用的RPC基准测试实现了一个“null”操作,没有在服务器上执行应用程序级代码。 所有实验都在第2节中描述的17节点集群上运行。

Simple completion queue scaling: 将单客户端设置扩展到多个客户端的一种简单方法是为服务器接受的每个连接提供单独的完成队列。 单独的服务器线程可用于查询这些完成队列,处理RPC消息并将响应传输回客户端。 已经使用基于常规的Socket网络堆栈实现了类似的方法,并且已知由于服务器线程之间的大量上下文切换而导致严重扩展[17,27]。 此外,由于服务器线程中的复制资源,该方法会占用大量内存。

       我们的测量结果(图5)显示,通过使用简单的完成队列扩展,DaRPC可以为16个客户端提供每秒480,000个RPC请求的聚合量。 虽然这比我们之前在HDFS和Zookeeper中看到的要好3倍,但是添加更多客户端会导致服务器争用并且性能会迅速降低。

Completion queue sharing: 通过让客户端连接在服务器上共享单个完成队列,可以避免大量服务器线程之间的争用。 可以使用单个服务器线程查询完成队列并将事件分派到有限制的处理线程池中。这种方法类似于可伸缩Web系统的架构,其中负载均衡器将请求分派给集群中的不同节点。 从图5中可以看出,与简单完成扩展相比,完成队列共享将服务器上的RPC吞吐量提高了3倍。

Completion queue clustering: 完成队列共享的一个问题是单个完成队列可能很快成为瓶颈。 首先,完成队列的大小是有限的,因此它可能会在繁重的负载下填满。 其次,完成队列只能由单个调度程序线程处理(只有一个线程可以进入阻塞调用),这可能会使该线程成为问题。 第三,该方法增加了额外的上下文切换,因为在事件发送后需要调度工作线程。 为了缓解DaRPC中的这些问题,我们使用了完成队列集群。 在此方法中,创建完成队列池,每个队列由服务器上接受的连接的子集共享。我们将与单个完成队列关联的一组连接称为完成队列集群。

       每个cluster包含一个cluster-head,负责CQ事件处理。 本质上,cluster-head用来接收处理RPC请求,如图4所示。 在连接接受时,新连接将分配给专用群集。 DaRPC基于CQ轮询历史不断地监视每个群集的负载并相应地分配连接。 使用聚类的DaRPC体系结构如图4所示。

       clustering方法有两个优点。 首先,可以将clustering分配给专用核心以分配负载。 其次,RPC请求现在可以在cluster-head的上下文中就地处理,而不是将请求分配给单独的工作线程。 这样可以节省上下文切换并减少CPU负载。 在我们的测试平台中,我们将DaRPC配置为使用4个完成队列集群。 从图5中可以看出,通过这样的配置,我们设法处理高达2M RPC req / sec。

Work stealing and load balancing: 维护每个cluster的相同数量的连接可能不会导致RPC服务器的CPU core之间的均匀负载分布。 实际上,即使cluster包含较少的连接,某些cluster可能会遇到比其他cluster更高的负载(由于被加载的连接)。 为了缓解此问题,我们会持续监控每个cluster的负载,并始终为最小负载cluster分配新连接。 在这里,轮询周期的历史可以很好地指示集群的负载。 通常,在处理RPC请求之后,cluster-head将重新轮询完成队列,并在找到未完成的请求之前继续处理,最终再次进入阻塞模式。 如果cluster的cluster-head几乎不会回到阻塞模式,则可以认为cluster已加载。 因此,我们使用完成队列上连续成功轮询的次数来衡量cluster的负载。

       遗憾的是,即使在没有添加或删除连接的情况下,群集之间的负载分配也可能会动态变化,这仅仅是因为连接的负载随时间而变化。 在DaRPC中,我们使用工作窃取来防止集群中的短期负载峰值。 如果cluster-head的负载(基于刚刚讨论的度量)超过某个阈值,则会将一些传入的RPC请求放入全局队列中,该队列可由系统中的所有cluster-head访问。 同时,其他cluster-head在轮询自己的完成队列之前每次轮询并可能处理全局队列。 此方法可确保一个cluster中的峰值被其他负载较少的cluster使用。

Memory locality: 现代多核系统通常提供类似NUMA的存储器访问,其中存储器访问时间取决于相对于处理器核心的存储器位置。即使所有内核都可以访问所有内存,访问本地内存通常比访问远程内存更快。因此,我们希望确保cluster中使用的所有内存资源都在运行cluster-head的核心的本地内存中。内存资源的示例包括Queue Pair,Complete Queue,Work Completion Events或RPC message buffers。在DaRPC中,类似NUMA的数据位置如下实现。首先,为每个cluster分配一个资源管理器,该资源管理器固定到与cluster-head相同的CPU cores。其次,cluster-head和连接请求的内存资源将通过集群自己的资源管理器进行分配。通常,操作系统将内存本地分配给请求线程,在这种情况下,所有cluster资源都被分配给执行cluster-head事件循环的核心。

       图5显示了启用了Memory Locality的配置中DaRPC的吞吐量性能。 从图5中可以看出,这样的配置将RPC吞吐量提高了另外300K req / sec。

Multiple NICs: 服务器系统通常包括多个网络接口。 DaRPC旨在通过使用实例在多个接口上运行。 DaRPC实例是指绑定到特定网络接口的完成队列cluster Pool。 RPC应用程序请求在给定网络接口的给定CPU核心池上创建DaRPC实例。可以为多个网络接口创建多个DaRPC实例。 RPC服务的典型方法是对可用核心进行分区,并使用每个分区创建单独的DaRPC实例。客户端请求可以使用DNS或ARP在不同的实例上进行负载平衡。

       我们使用两个DaRPC实例运行测试。每个实例由4个集群组成,所有集群都在单独的核心上进行调度。第一个实例绑定到Chelsio T5 NIC,第二个实例绑定到Chelsio T4 NIC。这种配置可提供高达3.2M RPC req / sec。这个数字几乎完全匹配我们在仅使用一个NIC的隔离实验中看到的RPC吞吐量性能的总和。例如,如果将一个DaRPC实例连接到功能较弱的T4 NIC,我们就可以驱动790K RPC req / sec。

Hardware Limits: 在我们的实验中,Chelsio T5 NIC提供2.4M RPC请求/秒。 为了正确考虑这个数字,考虑10Gbits / s NIC应支持的原始数据包速率为14.8M packet-s / sec2。 然而,为了维持这种分组速率,现代NIC以突发或批量方式传送数据包以分摊DMA,PCIe事务,中断和CPU处理等成本.MICA [12]使用32的数据包突发大小(RouteBrick [6]也建议使用类似的批量大小)来维持每个NIC 8.2-9.6M数据包/秒的数据包速率。 相比之下,T5的2.4M请求/秒的性能没有任何批处理。 批量适中8(参见第6.1节),DaRPC可提供8.8M re-q / sec。 此外,RDR NIC的特定实现进一步改善了DaRPC的性能。 正如我们之前观察到的,不同的RNIC代(例如,在T4和T5之间)具有不同的RDMA处理能力。

4.3 Client-Side Processing

       虽然在服务器端DaRPC专门处理来自网络的事件,但客户端的操作既可以从网络也可以从应用程序触发。 同样,一个关键的挑战是在上下文切换,锁定等方面尽可能高效。此外,需要特别注意处理来自不同应用程序线程的并发访问。 我们为DaRPC的客户端确定了两种可能的设计选项。

Direct CQ access: 使用此选项,每个RPC连接将在连接的客户端接收其自己的单独完成队列(不要与连接是完成队列集群一部分的服务器端混淆)。 单独的完成队列允许客户端通过在等待RPC回复时直接轮询CQ来完全避免任何上下文切换。 保存上下文切换可以大大减少延迟 - 在我们的部署中最多可达4μs。 但是,轮询会增加CPU负载,并可能导致竞争线程之间的CPU周期争用。 在多个线程在同一连接上发出并发RPC请求的情况下,可能还存在争用访问共享完成队列的争用。

CQ dispatching: 一种直接替代Direct CQ access的设计是在多个连接之间共享完成队列,并使用单独的线程来查询CQ和分发事件。 优点是,由于调度程序专门拥有完成队列,因此不存在CQ访问争用。 此选项类似于服务器端使用的cluster,唯一的区别是工作完成事件无法在调度程序的上下文中处理,但需要传递给应用程序。 原则上,没有任何东西可以阻止调度程序在每个连接队列中排队工作完成事件,并让应用程序轮询这些队列。然而,无论何时CPU更友好的方法都将由dispatcher在新工作完成事件发生时通知应用程序。 已收到。 这里,在向应用程序线程分派通知时需要一个额外的上下文切换。

       在下文中,我们比较两种选项的延迟性能 –CQ Dispatching 和 Direct CQ Access- 用于两种不同的配置。 在第一个配置中,多个线程使用与服务器的单个DaRPC连接并发地发出RPC调用。 在第二个配置中,多个线程发出RPC调用,但每个线程使用自己独立的连接。 图6显示了这四种情况中每一种情况下线程,RPC连接,队列对和完成队列之间的相互作用。 在实验中,我们进一步将CQ调度与通知和CQ调度与轮询区分开来。 在前者中,每次RPC操作完成时,调度程序都会唤醒线程。 在后者中,调度程序将通知消息放入每个连接队列中,该队列由该连接的线程轮询。

Single connection: 对于单个连接配置(图7的顶部),如果只有一个线程处于活动状态,则Direct Access CQ的选项可实现11.5μs的RPC延迟。与使用分别导致17μs和25μs的延迟的CQ调度器相比,这快30-60%。显然,避免上下文切换是保持整体RPC延迟较低的关键。但是,随着线程数量的增加,情况发生变化,使用CQ调度器变得更加有利。在具有16个线程的极端点处,直接CQ接入导致每请求等待时间为160μs,而CQ调度可以达到34-40μs。这些结果证实了我们的想法,即在Direct Access CQ模式下对sharedCQ访问(由于Lock 锁的开销)的争用不能很好地与线程数量成比例。相反,当在多个线程之间共享单个连接时,通过使用调度程序消除对CQ和CPU访问的争用更有利可图。从实现CQ调度的两种模式,轮询通常比使用通知更好地执行,但是它也更加CPU密集(未示出)。

Multiple connections: 当为每个客户端线程使用单独的服务器连接时,可以期望看到直接CQ选项的改进结果,因为至少消除了对sharedCQ的争用。 这由图7(底部)证实,其表明Direct CQ Access选项在整个频带的等待时间方面优于CQ Dispatching。 例如,通过直接CQ访问和每个线程的单独连接,即使16个线程同时运行,我们也可以实现16μs的RPC延迟。

       这些实验仅提供了两种客户端设计选项的粗略比较。 实际上,具有多个线程的应用程序不太可能在紧密循环中背靠背发出RPC请求。 相反,人们可以期望来自单个客户端线程的各个请求之间有更多的空间,这反过来会使Direct CQ Access变得有吸引力,即使在具有许多线程和单个连接的配置中也是如此。 通常,我们认为这些实验表明这两种方法 – Direct CQ Access和CQ Dispatching - 都有其自身的优点和缺点。 因此,我们决定在DaRPC中导出API级别的两个选项,让应用程序选择哪个选项最符合应用程序要求,工作负载模式,硬件设置等。通常,对延迟敏感的应用程序将使用Direct CQ Access, 虽然具有许多并发RPC操作的应用程序在CQ Dispatching方面会更好。

4.4 Reliability, Ordering and Flow Control

       一个重要问题是关于故障情况下的可靠性。 DaRPC旨在在可靠的传输协议之上运行,例如TCP(在iWARP的情况下)或Infiniband可靠的传输层。 因此,除非连接中断,否则最终将传递RPC请求和响应消息。 在后者中,应用程序尝试重新建立RPC连接并再次发出RPC请求。 应用程序也可以在这种情况下过滤掉重复项。

       另一个有趣的方面是关于在服务器上处理RPC请求的顺序。 在没有Work-stealing的情况下,在同一连接上发出的所有RPC请求都将按顺序处理。但是,在工作窃取时,无法保证处理RPC请求的顺序,即使对于在其上发出的请求也是如此。 因此,如果需要强制执行某个顺序,则必须在应用程序级别实施。

       在流量控制方面,任何基于RDMA的系统都需要特别注意。请记住,DaRPC客户端发出的RPC请求要求在服务器上预先发布RDMA接收操作。客户端不能够超出服务器并发出在服务器上没有发送接收的请求。在DaRPC中,是使用每个连接的缓冲环来解决的。在接受新连接之前,DaRPC服务器为环中的所有缓冲区发布RDMA接收操作,并与客户端共享环的大小。服务器上的接收缓冲区由传入请求消耗,但一旦解析和反序列化请求,就可以立即重新发布。客户端只需维护一个请求预算,该预算最初设置为环的大小,如服务器所公布的那样。随后,发送的每个请求都会减少请求预算,而传入的响应会增加预算。只要客户端仅在预算高于零时发出RPC请求,就不可能超出服务器范围。

5. Application Programming Interface

       设计DaRPC接口的目的是提供一个API,它可以导出DaRPC的所有性能优势,同时又易于使用且功能强大,足以满足云中大型复杂分布式系统的需求。

       DaRPC通过提供面向对象的异步编程接口来满足这些要求。每个DaRPC应用程序的起点是DaRPCInstance类。 DaRPCInstance用作RPC连接的工厂(DaRPCEndpoint)。在内部,它实现了一个完成队列Cluster。应用程序通过在创建实例时传递亲缘关系来定义Cluster的大小和NUMA亲和力。可以在CQ DIRECT或CQ DISPATCHED模式中创建DaRPCInstance。根据所选模式,从该实例创建的DaRPCEndpoint对象要么具有自己的RDMA CQ,要么共享完成队列,如4.3节所述。传递给DaRPCInstance的一个关键参数是实际的RPC服务。 RPC服务需要实现DaRPCService接口,即processRPC()方法,该方法由DaRPC运行时为从网络接收的每个新RPC请求调用。此方法的输入和输出参数(引用请求和RPC操作的响应)都需要是DaRPCParam类型,这是一个定义如何序列化这些参数的接口。我们使用Java“泛型”来避免从接口类型到实际应用程序特定类型的不必要的转换。

       服务器应用程序创建DaRPCEndpoint,将其绑定到本地接口(表中未显示的API调用),并接受来自客户端的新RPC连接(参见图8a)。 在内部,DaRPC运行时分配与DaRPCInstance内的cluster的连接。 从这一点开始,所有已建立连接的RPC处理都由相关的集群以上下文切换和数据本地方式驱动,如第4节所述。

       客户端应用程序将使用DaRPCService的实现来实例化DaRPCInstance,该实现与服务器上使用的实现相匹配。 DaRPCService的两个实现匹配,如果它们都基于相同的请求/响应类型,这保证了消息是线路兼容的。 客户端 - 与服务器不同 - 可以自由地提供processRPC()的空实现。

       在正确实例化DaRPCInstance之后,客户端应用程序创建一个DaRPCEndpoint并连接到RPC服务器。主客户端RPC接口可通过DaRPCStream类获得。该应用程序使用rpc()发出新的RPC请求。此调用是非阻塞的,并返回DaRPCFuture类型的对象,该对象充当给定RPC操作的句柄。在任何时候,应用程序都可以使用DaRPCFuture.isDone()轮询RPC操作的状态,或使用DaRPCFuture.join()显式阻止RPC操作完成(图8)。完成的RPC操作将进一步与DaRPCStream对象一起排队,该对象首先触发RPC。 DaRPCStream接口为应用程序提供DaRPCFuture的替代方案,以跟踪RPC操作。例如,应用程序可以背靠背发出多个RPC操作,然后使用DaRPCStream.take()或DaRPCStream.poll()来检索已完成的第一个操作。对于任何已完成的RPC操作,可以使用DaRPCFuture.getResponse()来访问响应值。

6. Related Work

       RPC已经成为许多分布式系统的支柱。 随着20世纪90年代高性能网络的出现,许多项目都在RPC的背景下研究应用数据传输操作的低延迟应用[4,10,20,24]。 这些系统识别源自数据副本,上下文切换,低效主机接口,编组和解组参数,协议和数据包处理等的RPC性能开销。现代高性能RDMA接口和用户空间网络堆栈建立在他们的发现之上。 DaRPC更进一步,将多核,CPU / NIC局部性,负载下的RPC容量可扩展性和语言运行时考虑因素(例如JVM等托管运行时)等集成到RPC性能中。

       已知RPC很小并且数据包处理很重。 在现代10或40 Gbits / s网络上,它们每秒可以轻松生成数百万个请求。 最近,有许多工作旨在有效地处理多核服务器上的小数据包[8,9,19,21]。 此外,快速用户空间数据包处理框架的可用性还导致了完整网络和应用程序堆栈的用户空间实现。 与DaRPC类似,mTPC [9]管理用户空间中的数据包处理,TCP连接管理和应用程序接口,以实现最佳并行性。 但是,mTCP的主要关注点是高小的数据包吞吐量,这是通过避免内核以及I / O路径上的高效数据包和事件级批处理来实现的。 DaRPC的单核处理单个RPC请求的架构(具有最小的上下文切换开销)受到RouteBricks的启发[6]。

       在现代大规模分布式系统中,RPC性能大多被视为构建大型分布式系统过程中的优化问题。例如,Tango的RPC框架利用特殊的操作系统功能在单客户端场景中实现570K RPC操作/秒,每次操作的延迟为35μs[3]。构建RPC堆栈作为大规模分布式系统(例如键值存储)的一部分,可实现跨层性能优化。一种这样的优化是在不同层进行的大量批处理以分摊RPC的小数据包处理的成本。 Percolator系统使用批处理[18]运行集中时间戳oracle,作为RPC服务实现,吞吐量为2M req / sec。类似地,Vasudevan等人提出的矢量界面。对于他们的键值存储,可以在单个服务器上实现1.6 M req / sec [26]。 Masstree是另一个键值服务器,它通过批处理提供6M查询/秒[14]。虽然批处理会增加RPC吞吐量,但这会以延迟为代价。例如,mTCP峰值性能的延迟数比DaRPC慢几个数量级(以msecs为单位)。我们已经证明,DaRPC可以在批量大小和过程接近10M RPC /秒的情况下进行缩放。亚毫秒延迟。

       MICA [12]是最近提出的键值存储,它将数据包I / O和键值请求处理作为一个联合问题进行处理。 MICA和DaRPC都需要高效的网络I / O处理,但是,MICA和DaRPC处理请求的方式存在一些根本区别。 MICA利用了键值存储值通常小于数据包大小的事实。 因此,MICA无法处理大于数据包大小的请求大小。 此外,它使用UDP进行I / O,并且在丢包的情况下,客户端需要检测并重新发送丢失的请求(或数据包)。 尽管幂等键值请求是可接受的,但RPC的这种行为是不受欢迎的。 RPC通常涉及数据或服务服务器上的状态更改,并且需要一致的一次性调用语义。

       此外,上面讨论的系统都没有在托管运行时中实现,这使得它们在云/虚拟化环境中的部署变得困难。 表3列出了这些系统的关键属性,并将它们与DaRPC进行了比较。

       最近,人们越来越关注在基于云的分布式系统中使用RDMA网络[7,11,15]。 这些工作并不特别针对RPC性能,但它们展示了网络和更高级别系统之间紧密集成的潜力。

       专门解决Hadoop中RPC性能的工作是[13]。 通过使用更复杂的缓冲区分配方案和传输路径上的零拷贝,他们的工作能够将Hadoop中的RPC性能提高多达82%.

7. Conclusion

       在这项工作中,我们介绍了DaRPC,一个高吞吐量低延迟RPC的框架。 DaRPC使用RDMA在用户空间中实现RPC处理和网络处理之间的紧密集成。 通过跨核心和内存联合分发RPC和RDMA资源,DaRPC设法增加并行性并扩展到大量RPC请求。 在本文中,我们证明了DaRPC可以使用单个服务器处理高达2.4M RPC请求/秒,每个RPC的延迟为3-10μs。 DaRPC完全用Java编写,因此可以被当今云中部署的许多分布式系统轻松使用。 如本工作所示,DaRPC可以改善运行数据中心(如HDFS)的大规模分布式系统的扩展和性能。

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值