一周一論文(翻譯 總結) [SOCC 14] DaRPC
來自專欄 RDMA7 人贊了文章
論文題目 2014-SOCC- DaRPC: Data Center RPC
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系統:
- High throughput: 系統應該能夠每秒處理大量的RPC請求。 高吞吐量是關鍵在使用集中式組件(例如,locking服務,OpenFlow Control等)操作的大規模分散式系統的環境中。 單個RPC服務可能必須處理來自數千台伺服器的數百萬個RPC請求。
- Low Latency:即使RPC伺服器被載入的時候,單個RPC操作的延遲也應該接近原始網路延遲。 如果RPC操作是需要在短時間內完成的一系列序列化操作的一部分(例如,RPC用於存儲系統中的元數據查找),則此屬性是必不可少的。
- 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)的大規模分散式系統的擴展和性能。
推薦閱讀:
※一場關於基因測序的「無限戰爭」來了!
※有限差分方法、偽譜法的CUDA C實現以及計算效率比較
※大話SW26010系列之工欲善其事 必先Benchmark