UCloud高性能RoCE網絡設計

電商、直播等業務要求以非常快的速度完成請求應答,計算和存儲的飛速提高也在推動HPC、分佈式訓練集羣、超融合等新應用的普及,網絡變成制約性能的主要因素之一。爲此,我們設計了低開銷高性能的RoCE網絡,構建了低時延、無損的大型以太網數據中心,作爲RDMA等技術的底層基石,也爲UCloud未來的物理網絡建設打下了良好基礎。

一、低開銷高性能的無損網絡選型

普通的內網進行數據包交互時,通常會使用系統級的TCP/IP協議棧或者是DPDK技術,這兩種方案都是依靠軟件進行協議棧解封裝的,對系統的CPU有不少消耗。而有一種方案:RDMA,可以直接使用網卡進行協議棧解封裝,無需消耗系統CPU,能有效降低數據處理的延時。

RDMA並沒有規定全部的協議棧,比如物理鏈路層、網絡層、傳輸層每個字段長什麼樣,如何使用,但對無損網絡有相當高的要求:

– 不輕易丟包,重傳帶來的延時非常大。

– 吞吐量巨大,跑滿最好。

– 延時越低越好,100us都嫌長。

依據上述要求,主流的網絡方案有三種:

UCloud高性能RoCE網絡設計

圖:主流的RDMA網絡方案

① InfiniBand: 該方案重新設計了物理鏈路層、網絡層、傳輸層,是RDMA最初的部署方案,所以要使用專用的InfiniBand交換機做物理隔離的專網,成本較大,但性能表現最優;

② iWARP: 該方案的目的是讓主流的以太網支持RDMA,將InfiniBand移植到TCP/IP協議棧,使用TCP協議保證無丟包,但缺點在於TCP開銷較大,且算法複雜,所以性能表現較差;

③ RoCEv2: 該方案的目的也是讓主流的以太網支持RDMA(RoCEv1版本已很少提及了)。網絡側使用PFC保證擁塞時不丟包,網卡側又使用DCQCN的擁塞控制算法進一步減緩擁塞(該擁塞算法需要網絡側支持ECN標記),傳統的以太網經過PFC和ECN的加持進化成爲無損以太網,在無損以太網上運行RDMA性能大大增強。

RoCEv2(後文簡稱RoCE)方案的成熟案例較多,我們也選用了該方案進行研究。但RoCE方案仍存在一些問題,如PFC壓制的不公平性、PFC傳遞帶來的死鎖風險、過多的調參、ECN標記的滯後性(ECN概率標記是軟件輪詢機制)等,是需要我們解決完善的。

二、網絡設計的目標

要把RoCE搬到經典的數據中心網絡上,這可不是一件容易的事兒。

當前數據中心是常見的CLOS架構,LCS是匯聚交換機,LAS是TOR交換機。如果RoCE直接運行在這上面,問題是顯而易見的:例如出現Incast事件時,轉發不了的報文會被存放在交換機緩存中,但緩存也不是無限大的,如果存滿了,這個數據包就丟掉了,很明顯這種丟包頻率肯定不能被RDMA所接受。

UCloud高性能RoCE網絡設計

圖:CLOS架構示意

上面只是舉了一個簡單的例子,實際上出現的問題要更復雜一些。在設計之前,需要先明確好我們的目標是什麼,做到有的放矢。

簡單來講我們的目標就是:

– 在各種流量模型下,網絡帶寬要能跑滿;

– 緩存使用要儘可能低;

– 極限情況下緩存使用滿了也不能丟包。

總結來說,爲了讓RoCE跑在已有的網絡上,我們需要從三個方面下手:
① QOS設計:指隊列、調度、整形等一系列的轉發動作,相對獨立。

② 無損設計:是RDMA的要求之一,使用PFC技術實現。無損是一種基本保障,含義是在最擁塞的情況下也能保證其可用性,讓上層應用可以放心發送數據,不必擔心丟包的風險(所以說PFC並不是降速的手段)。

③ 擁塞控制設計:使用DCQCN技術實現。擁塞控制是滿足基本保障前提下的進一步優化,含義是在開始擁塞的時候,就告知服務器兩端,使其從源端開始降速,從根本上解決問題。

補充一點擁塞帶來的壞處:當出現擁塞後,必然要使用緩存,使用緩存後雖然不丟包了,但是帶來的後果是延遲上升,而且吞吐也不能再增加一絲一毫。網絡中擁塞點有很多,每一跳都可能成爲擁塞點,在上圖的網絡中,最多會有3個擁塞點。

緩存的使用能帶來多少延時?

我們按25Gbps來算,緩存25Mb的數據,大約需要1ms的時間才能發送完畢,25Mb也僅僅是3.1MB,而常見的Broadcom Trident 3芯片有32MB的緩存。

有了這三個方面的認識,我們就可以化繁爲簡,逐一破解。

三、QOS設計

QOS的設計,無非是入隊、調度、監管和整形。

入隊方式可以依據DSCP、TOS、COS等標記,然後信任某種標記入隊,也可以選擇使用策略抓取其它報文特徵入隊。我們最終選擇的策略是:在IDC邊界處,使用報文特徵抓取入隊,並重寫DSCP,IDC內部僅根據DSCP入隊(IDC內部減少策略使用,滿足高速轉發即可)。這樣,既能保證DSCP標記的可信任,又能減輕IDC內部的策略複雜度。根據這個思路,我們分別設置對應策略:

– 對ToR下行端口與Border上行端口: 抓取特定報文,進入特定隊列。

– 對其餘設備和端口設置:信任DSCP,按映射入隊。

用圖表表達即:

■ IDC邊界入隊

次序

Match

Action

1

udp_dport==4791  &&
dscp==48

入隊列6

2

udp_dport==4791  &&
dscp==46

入隊列5

其他

其他

修改dscp爲預定義

*這是已有的標記策略,我們IDC內部爲業務進行分類,並標記特定的DSCP。

*其中次序1、2只在RoCE網絡的ToR部署。

■ IDC內部DSCP映射

DSCP

隊列

48

6

46

5

其他

2…

下面該聊聊調度設計了,調度的對象是緩存中的數據,也就是說,調度是僅在擁塞時才生效的,而且調度生效後,影響的將是各隊列的流量大小。

帶着以上的認識,我們開始調度設計。在一般的RoCE網絡中,使用的有如下隊列(或流量):

① 協議信令類,目前來看只有CNP流量;(其它協議均不跨跳,所以不考慮)

② RoCE流量;

③ 業務/管理流量。

UCloud高性能RoCE網絡設計

這三大類流量,還可以繼續分小類。按照ETC所推薦的調度模型,我們選擇了SP+WDRR的調度方式,即:1類流量絕對優先,在緩存積壓的時候優先調度,直到隊列爲空。2類和3類流量次優,兩者之間按照WDRR調度,權重值可以靈活定義。這樣就能保證CNP報文在3us內轉發給流量源站(沒有擁塞的網絡單跳的延時在1us以內)。

以上調度設計中有個漏洞:如果隊列6的流量過大,可能會將低優先級的隊列餓死(即長時間得不到調度),雖然理論上隊列6的流量一般都在幾十~幾百Mbps,但仍要提防服務器惡意***行爲。於是,我們將SP的隊列限制其隊列使用帶寬。這個便是所謂的監管和整形了。

四、無損涉及與分析

RoCE的流量需要保證運行在無損隊列中,無損隊列使用了PFC技術,能針對某一隊列發送Pause幀,迫使上游停流。

UCloud高性能RoCE網絡設計

在博通的XGS系列芯片中,有一塊緩存管理單元MMU(簡稱緩存),存放已收到但沒轉發走的報文,並給入口和出口都計數:“0/1的入口和0/2的出口,都用了1個cell”(cell是緩存資源的最小單位)。

緩存會給每個入口和出口設置一個上限,超過這個上限就不能再使用cell緩存報文了。上限以下還畫了很多其它的水線,同時對每一個出口和入口進行進一步細分,可以按照隊列進行統計限額其中入方向。入方向上,細分了PG-Guaranteed大小、PG-Share大小、Headroom大小;出方向上,細分了Queue-Guaranteed大小,Queue-Share大小(如下圖所示,這裏我們不考慮端口,只考慮隊列)。

UCloud高性能RoCE網絡設計

圖:隊列入方向與出方向示意

緩存使用的時候,總是從下往上依次申請使用,所以更喜歡把這些區塊大小稱之爲“水線”,當“某區塊”都使用完畢,就稱之爲“緩存水位”到達了“某水線”。例如:當PG-Share區塊使用完畢,就稱之爲,入口緩存水位已經到達PG-Share水線。如果所有區塊用完就產生丟包了,稱爲no buffer丟包。

每一塊大小都有其特殊用處,先簡單看下其作用,後面再探討下無損隊列中的這5個水線應該如何設置。

►PG-GuaranteedQueue-Guaranteed是保證緩存,這部分是獨享的,即使不用,別的隊列也不能搶佔使用。

►PG-ShareQueue-Share使用的是共享緩存,因爲動態水線的緣故,它們的大小不固定,如果很多隊列都在用,那平分一下,每個隊列的水線就都很小。另外,PG-Share還有另一個重要的作用:PFC發送的臨界點,也稱爲xoff水線,只要到達該水線,PFC就會從這個口發出去,回落一些後,才恢復正常。

►Headroom是一個特殊的水線,只有在無損隊列中才能發揮其作用。設想一下,PFC發出去以後,流量真的能瞬間停下來麼?答案是不能的!因爲線纜中還有一部分數據,而且七七八八的轉發處理時間也要算進去。所以Headroom空間就是用來做這個的。

**1、PG-Guaranteed和Queue-Guaranteed

**

講完了基本原理,回過頭來看網絡設計。先看PG-Guaranteed和Queue-Guaranteed水線,這倆水線與“無損隊列”關係不大,保證緩存的作用只是滿足交換機基本的存儲轉發功能,所以配置爲一個數據包大小即可。那我們按照最差的情況來算,即MTU=9216的巨型幀。

但實際上我們不必爲此發愁,因爲動態水線的緣故,共享緩存中總會有剩餘的緩存以供使用,所以保持原廠的默認配置即可。

2、Queue-Share

接下來是Queue-Share水線。在無損隊列中,我們希望在緩存丟包前,能觸發PFC進行反壓,所以在任何情況下,都應該入口PG-Share先到達水線,出口Queue-Share永遠不能到達水線(PG-Share到達會發PFC,Queue-Share到達會丟包)。

之前講過,MMU記賬是出口入口各記一筆,這樣來看,最差情況應該是多打一(出口的帳全記在一個隊列上,入口的帳會均攤到不同隊列中)。爲了讓出口水線永遠不會到達,索性將出口水線配置爲無限大好了,事實證明這樣做也沒有問題,因爲入口的PG-Share是動態水線,總能在Buffer破產前觸發該水線。

這樣一來,Queue-Share好像已經搞定了,其實不然,如果TCP流量參與進來混跑呢?這問題可就嚴重了,TCP的Lossy隊列會吃掉大量緩存,所以Lossy隊列中,對應的Queue-Share水線也應當限制一下。

3、PG-Share

PG-Share水線只要配置爲動態水線即可,大小可以隨意調節,都不會出太大問題的,但需要滿足一個不等式:(PG-Share + PG-Guarantee + Headroom) * [入口個數]≤ Queue-Share + Queue-Guarantee

該公式描述的是一個端口多打一的場景。入口個數根據實際情況選取一個較大值(拿ToR來看,最差情況是39打1,32個25G下行,8個100G上行)。

這裏的PG-Share是動態水線,動態水線用一個簡潔的公式即可表達:PG-Share = [剩餘Buffer] * α

這裏的α是縮放因子,用戶可自由調節。可以看出,縮放因子決定了PG-Share水線的大小。依據上面等式,我們只要將Queue-Share水線設置爲靜態最大、PG-Share設置爲動態即可,入口的縮放因子α可隨意。當然入口α也不能設置太小,在端口少打多的情況下,由於入口的水位很低,導致均攤到每個出口時,出口的水位更低!出口的水位過低時,會發現已有的ECN配置不再生效(例如:可能出口的水位還到不了Kmax的一半)。在我們的經驗看來,無損隊列中PG-Share的α,配置1/8,1/4,1/2,1都可以,具體大小還要聯合擁塞設計中ECN參數來決定。

4、Headroom

Headroom水線很重要,但可以通過實驗+推導的方式得出合理的配置,先來看一個等式:[Headroom大小] = [PFC構造到停流的時間] * [端口速率] / [64字節小包占用的比特數]

使用64字節小包計算,是因爲小包對緩存的使用率最低,單個Cell有200多字節,但只能被一個報文獨享。其中,只有[PFC構造到停流的時間]是需要進一步分解的:T = Tm1 +Tr1 + Tm2 +Tr2* Tm1:下游PG檢測到xoff用完,到構造PFC幀發出的時間。

* Tr1:PFC幀從下游發往上游的時間。

* Tm2:對端收到PFC幀,到隊列停止的時間。

* Tr2:隊列停止後,線纜中報文傳輸的時間。

可以看出,這四個時間中,只有線纜長度是變量,繼續化簡後可以得出:[Headroom大小] = (Tm1 + Tm2 +2 * [線纜長度] / [信號傳播速度]) * [端口速率] / [64字節小包占用的比特數])

這裏面Tm1 + Tm2 是常數,可以實驗測得,剩餘的都是已知量了。最後根據公式就可以算得100G口,100M光纖下,H = 408 cell;25G口,15M AOC下,H = 98 cell。當然,真正使用的時候,還要再冗餘一點,畢竟這是臨界值。

5、死鎖分析和解決

談到PFC就不得不提一下死鎖,死鎖危害極大,而且其傳遞性會迅速擴散到整個網絡,以至於整個網絡的無損隊列全部停流。死鎖的研究很多,其中較詳細的是微軟的一篇論文《Deadlocks in Datacenter Networks: Why Do They Form, and How to Avoid Them》。

死鎖產生的一個必要條件是CBD(環狀緩存依賴),在我們的組網環境中,是典型的CLOS組網,所以在穩定狀態下不會存在CBD,也沒有死鎖風險。而且整個POD內部路由不做過濾,明細互知,匯聚採用4臺~8臺冗餘,即使出現兩點故障,收斂後的拓撲也不會存在CBD,即不會存在死鎖風險。

UCloud高性能RoCE網絡設計

圖:CBD和死鎖

至此,我們已經解決穩定狀態下的死鎖了,但還要考慮一點:收斂過程中,是否存在CBD?其實仔細分析一下還是會存在的,我們考慮了很多收斂場景,確實會有部分場景下,存在微環路。有微環路就一定有CBD。事實證明,我們也真實地模擬出了微環路導致的死鎖。

死鎖問題總是要解決的。我們使用三種方法:

1、針對各種微環路場景,通過設計網絡協議,控制收斂的現先後關係,避免出現微環路出現。

2. 對於其它未知的死鎖風險,使用交換機的死鎖檢測功能,釋放緩存(釋放緩存會產生丟包,但收斂過程本身就有亂序/丟包情況)。

3. 將PG-Share的水線適當拉高,儘量使用DCQCN擁塞控制來壓制流量。

五、擁塞控制設計與分析

網絡擁塞控制是一個很複雜的課題,這裏只講一些基本的設計思路。
RoCE使用的擁塞控制算法是DCQCN,_《Congestion Control for Large-Scale RDMA Deployments》_這篇論文很詳細地描述了該算法。

這裏先簡單的描述下這個算法:維護這個算法的節點是服務器,也就是流量的兩端,中間的交換機作爲傳輸節點,通告是否擁塞。發送方叫Reaction Point,簡稱RP;接收方叫Notification Point,簡稱NP;中間交換機叫 Congestion Point,簡稱CP。發送方(RP)以最高速開始發送,沿途過程中如果有擁塞,會被標記ECN顯示擁塞,當這個被標記的報文轉發到接收方(NP)的時候,接收方(NP)會迴應一個CNP報文,通知發送方(RP)。收到CNP報文的發送方(RP),就會開始降速。當發送方沒有收到CNP報文時,就開始又提速了。

上述過程就是DCQCN的基本思路。雖然整個算法十分複雜,但都是圍繞這個基本思路,繼續完善算法細節(下圖分別是NP的狀態機和RP的算法)。可調參數也十分衆多,比如降速要降低多少?提速效率是否積極?網絡擁塞度如何維護?擁塞度更新週期多久?CNP報文的敏感度多大?這都是問題,需要對流量建模後找出合理參數。

UCloud高性能RoCE網絡設計

圖:接收方

UCloud高性能RoCE網絡設計

圖:發送方

DCQCN算法中,對RP、NP和CP都有很多參數可以調節。RP和NP節點在服務器上,準確來說應該是在網卡上,網卡初始化的參數已經爲最優值,無需再進行調整,這樣就剩CP上的參數需要調整了。

CP上有三個參數其實就是WRED-ECN的那三個參數,分別是Kmin,Kmax,Pmax,這三者的關係,可以用下圖來表示。橫軸是出向隊列長度,縱軸是報文被標記的概率。從圖中可以看到,在隊列長度超過Kmax時,標記概率出現一個跳變,從Pmax直接到達100%。

UCloud高性能RoCE網絡設計

根據上面的理論分析,我們可以通過實驗證實和試錯的方法一步步找到最優解。

現在設想一下:在一個擁塞場景中,當出口隊列長度小於Kmin時,不會被標記,出口隊列長度可能會穩步增長,當隊列長度超過Kmin時,DCQCN纔開始降速。
所以Kmin的大小決定了RoCE網絡的基礎延時,這些緩存中的報文是發送者發出,但未被接收者確認的報文,我們稱之爲inflight bytes,約等於延時帶寬積。所以,Kmin的配置規範爲小於期望的延時帶寬積。有了這個理論基礎後,實踐測得理論符合實際,還可以根據測得的延時進一步調整該數值。

我們用同樣的思路來思考Kmax,承接剛剛的思路,那就是:Kmax的配置規範爲小於或等於能容忍的延時帶寬積。但這次不再這麼簡單了,因爲Kmax還決定了圖中的斜率。同樣決定斜率的還有Pmax,在討論Kmax和Pmax前,我們不得不先介紹下整個ECN的理想與現實。

理想狀態下,標記概率在定義域Kmin~Kmax內的變化是連續的,而且,隊列的長度是準確的。但事與願違,博通芯片SDK使用軟件輪詢的方式測得隊列長度,而且將此刻的隊列長度與歷史值做指數平均,並依此計算標記概率。軟件輪詢帶來的結果是,標記概率在定義域Kmin~Kmax內的變化是不連續的,其次,指數平均值會讓測得的隊列長度是滯後的(當然指數平均也帶來了好處,這裏不展開)。

這件事帶給我們的影響就是,理論推導的Pmax,甚至Kmin、Kmax都被推翻,請繼續往下看:理想狀態下,一個25G端口、單QP會話下,最大的有效Pmax是多少?

根據DCQCN中NP的算法,50us內收到多個CE標記包,會被認爲只有一個有效包,所以最高的CE標記速率應該爲20000個包每秒(即1個包每50微秒),依此,我們算得最高有效Pmax,即是設置的Pmax值,如下表所示:我們假設一個25G端口、只有一個QP會話,此時最高有效Pmax是多少?可以根據表格中第4、5列計算出最後一列最高有效Pmax的值。

UCloud高性能RoCE網絡設計

再回到現實,我們按照推導的數據對錶格最後一行進行驗證。

對端口限速模擬擁塞,測得穩定時RoCE流量pps=2,227,007,然後選取一組ECN配置:Kmin=1cell,Kmax=1400cell,Pmax=1%,理論上來說Pmax已經超出最高有效的值了,理論上即使在擁塞時,出口水位也不可能達到1400cell,所以再設置一個監控項,監控出口水位有沒有超過1400cell(觸發式告警,並非輪詢,所以不會存在採集不到的情況)這是第一個實驗。

作爲對比,第二個實驗使用另一組ECN配置,Kmin=800cell,Kmax=1400cell,Pmax=1%,按照之前分析,這一組配置下,出口水位也不會超過1400cell,因爲在1400cell水位時,Pmax=1已經超過最高有效標記概率了。

可是實驗結果並不符合預期,第一個實驗沒有觸發告警,通過;第二個卻觸發告警了。這就意味着在某些時刻,緩存水位超過1400cell了!水位是波動的,並沒有穩定在某個值!我們大膽猜測其中原因:從緩存隊列積壓,到得到緩解,這其中有太多地方消耗了時間:隊列長度的輪詢、指數平均算法、CNP的生成與轉發,甚至於降速後線纜中的數據傳輸等等。

爲解決這一難題,我們另闢蹊徑,選擇了另外一條路:首先制定了幾個小目標,然後通過大量的實驗來摸索出驗證一套安全可靠的配置。這個方法雖然更野蠻,但很有效。

 小目標1:服務器端口吞吐量要在95%以上;

 小目標2:所有流量場景下交換機99%的時間裏PFC發送速率不得高於5pps;

 小目標3:任意場景下服務器端到端延時不得高於80us(90%場景下低於40us)。

對於流量模型,我們設計篩選後,選用了50餘種流量,最終我們得到了同時滿足這三個小目標的合理參數。

不得不說,DCQCN很難玩轉,參數衆多且互有聯繫,這裏也只是提供一些實踐規律,歡迎一同深入探討。

六、總結

爲使物理網絡具備承載RDMA業務流量的能力,我們選擇了RoCE的網絡方案,並通過QOS、無損、擁塞控制三塊設計,來保證物理網絡無損轉發。RoCE無損網絡爲快傑雲主機這樣高性能的業務系統提供了強大的支撐,如高達120萬IOPS的RSSD雲盤,25Gbps的內網線速轉發帶寬。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章