沈逸凡 張文力 劉 珂 陳明宇
(*中國科學(xué)院計算技術(shù)研究所 北京 100190)
(**中國科學(xué)院大學(xué) 北京 100049)
數(shù)據(jù)中心服務(wù)器需要處理來自不同應(yīng)用的多種類型的混雜請求,這些請求往往帶有不同的服務(wù)等級目標(biāo)(service level objective,SLO)。例如,在阿里巴巴的數(shù)據(jù)中心服務(wù)器上[1]同時運(yùn)行有對響應(yīng)延遲不敏感的批處理、機(jī)器學(xué)習(xí)等任務(wù),并同時需要對延遲敏感的網(wǎng)頁服務(wù)、社交網(wǎng)絡(luò)等交互式應(yīng)用的請求進(jìn)行服務(wù)。非延遲敏感型請求會對延遲敏感型請求造成搶占中央處理器(central processing unit,CPU)、引發(fā)排隊阻塞等干擾,導(dǎo)致響應(yīng)尾延遲上升。因此數(shù)據(jù)中心服務(wù)器需要對混雜的請求負(fù)載進(jìn)行分類與調(diào)度,保證延遲敏感型請求的響應(yīng)尾延遲,以提高用戶體驗。
在不同的負(fù)載場景中,數(shù)據(jù)中心服務(wù)器需要定義不同的策略以實(shí)現(xiàn)對延遲敏感型請求的準(zhǔn)確甄別與調(diào)度。例如,在來自不同應(yīng)用或是同一應(yīng)用的不同類型的請求間,可以通過關(guān)鍵詞匹配識別請求類型來進(jìn)行優(yōu)先級分類與調(diào)度(比如物聯(lián)網(wǎng)服務(wù)器場景[2]中區(qū)分用戶請求和長連接心跳包);而在網(wǎng)頁服務(wù)中則需要根據(jù)對服務(wù)響應(yīng)時間的估計,對基礎(chǔ)響應(yīng)延遲較低的請求優(yōu)先進(jìn)行服務(wù),因為這些請求的延遲波動會對用戶體驗造成更大影響[3](相比5 s才能加載的網(wǎng)頁,1 s 的響應(yīng)延遲波動對1 s 就能加載的網(wǎng)頁的用戶體驗影響更大)。
在數(shù)據(jù)中心服務(wù)器上,網(wǎng)絡(luò)協(xié)議棧負(fù)責(zé)從網(wǎng)卡收發(fā)數(shù)據(jù)包并進(jìn)行網(wǎng)絡(luò)協(xié)議處理,處在每個請求處理的關(guān)鍵路徑上,可以獲得全局的狀態(tài)信息,因此是實(shí)現(xiàn)請求負(fù)載分類調(diào)度的理想位置。然而,現(xiàn)有的網(wǎng)絡(luò)協(xié)議棧并不能有效地對數(shù)據(jù)中心混雜的負(fù)載進(jìn)行分類調(diào)度。傳統(tǒng)操作系統(tǒng)使用的內(nèi)核協(xié)議??梢允褂胑BPF(extended Berkeley packet filter)[4]等方式實(shí)現(xiàn)豐富的分類調(diào)度策略,但面對不同應(yīng)用和場景時需要重新編寫eBPF 代碼,缺少靈活性,且內(nèi)核協(xié)議棧的高額開銷導(dǎo)致其已無法滿足當(dāng)下數(shù)據(jù)中心應(yīng)用的性能需求[5-6]。用戶態(tài)協(xié)議棧采用內(nèi)核旁路技術(shù),避免了內(nèi)核協(xié)議棧的性能瓶頸,為數(shù)據(jù)中心應(yīng)用提供高性能的網(wǎng)絡(luò)服務(wù)[5-11]。文獻(xiàn)[2]使用用戶態(tài)協(xié)議棧,通過對請求添加靜態(tài)優(yōu)先級標(biāo)簽實(shí)現(xiàn)在服務(wù)端的優(yōu)先隊列調(diào)度,避免了排隊延遲,但需要客戶端與智能網(wǎng)卡的配合,當(dāng)面對不同應(yīng)用及負(fù)載場景時缺乏靈活性。文獻(xiàn)[11]也使用用戶態(tài)協(xié)議棧,通過識別請求類型,優(yōu)先調(diào)度處理時間短的請求,以避免復(fù)雜請求阻塞帶來的尾延遲,但只能在應(yīng)用層進(jìn)行調(diào)度,且只支持根據(jù)請求頭部類型信息進(jìn)行分類。這些系統(tǒng)在服務(wù)器上的應(yīng)用及負(fù)載場景發(fā)生變化時,都要對系統(tǒng)進(jìn)行復(fù)雜的修改才能實(shí)現(xiàn)對新環(huán)境負(fù)載的有效調(diào)度,且受設(shè)計架構(gòu)約束,無法對某些場景進(jìn)行有效的調(diào)度。
針對上述問題,本文提出了面向應(yīng)用定義優(yōu)先級調(diào)度的用戶態(tài)協(xié)議棧。為實(shí)現(xiàn)不同負(fù)載場景下的延遲敏感型請求的響應(yīng)延遲保證,本研究支持每個應(yīng)用向協(xié)議棧制定符合自身請求協(xié)議及負(fù)載特征的優(yōu)先級識別與調(diào)度策略,并由用戶態(tài)協(xié)議棧提供優(yōu)先級識別調(diào)度所需的狀態(tài)信息及調(diào)度支持,實(shí)現(xiàn)在不修改網(wǎng)絡(luò)協(xié)議棧的情況下同時對不同數(shù)據(jù)中心應(yīng)用實(shí)現(xiàn)靈活準(zhǔn)確的優(yōu)先級識別調(diào)度。同時,數(shù)據(jù)中心供應(yīng)商也可根據(jù)常見的調(diào)度策略及自身負(fù)載特征,為所有應(yīng)用定制默認(rèn)的優(yōu)先級識別調(diào)度方案。
本文組織如下,第1 節(jié)介紹研究背景與相關(guān)工作,第2 節(jié)介紹如何在用戶態(tài)協(xié)議棧支持應(yīng)用定義的優(yōu)先級識別及調(diào)度,第3 節(jié)介紹系統(tǒng)實(shí)現(xiàn)及應(yīng)用移植,第4 節(jié)介紹實(shí)驗評測方法及結(jié)果,第5 節(jié)對全文進(jìn)行了總結(jié)。
在阿里巴巴[1]、Google[12]等數(shù)據(jù)中心服務(wù)器上,為提高服務(wù)器資源利用率,混雜有來自不同應(yīng)用、帶有不同負(fù)載特征與服務(wù)等級目標(biāo)的請求,這些請求相互之間形成干擾,對響應(yīng)延遲造成波動。混雜請求間的相互干擾主要有2 種類型:大量延遲非敏感型請求造成的排隊延遲和處理時間長的復(fù)雜請求占用CPU 導(dǎo)致的阻塞延遲。
請求間相互干擾的一種體現(xiàn)是,當(dāng)負(fù)載高峰時,大量的對延遲不敏感的請求對請求處理的各個階段造成排隊,導(dǎo)致少量對延遲敏感的請求因為排隊而引發(fā)響應(yīng)尾延遲上升,本文通過實(shí)驗對該問題進(jìn)行了驗證。在實(shí)驗中,仿照物聯(lián)網(wǎng)(Internet of Things,IoT)服務(wù)器場景大量低優(yōu)先級請求混合少量高優(yōu)先級負(fù)載的模式[2],在客戶端生成包含5%延遲敏感型請求和95%非延遲敏感型請求的突發(fā)式負(fù)載。在服務(wù)端,使用基于mTCP[5]的一個echo 服務(wù),對收取到的每個請求進(jìn)行10 ms 的處理后原樣返回響應(yīng)。本文記錄了延遲敏感型請求的響應(yīng)尾延遲以及它們在請求處理各個階段的排隊延遲(均取99th 尾延遲),并測量統(tǒng)計了模擬理想情況(非延遲敏感型請求在網(wǎng)卡接收后就丟棄)下響應(yīng)尾延遲。如圖1所示,混雜負(fù)載的延遲敏感型請求相比在理想情況下要高72 倍。其中,延遲敏感型請求在傳輸控制協(xié)議(transmission control protocol,TCP)接收緩沖區(qū)的等待時間約占總體延遲的67%,這是在等待上層應(yīng)用處理完大量的非延遲敏感型請求后才被處理。此外,延遲敏感型請求數(shù)據(jù)包在被從網(wǎng)卡接收隊列收取到收包緩沖區(qū)后,在收包緩沖區(qū)的排隊等待時間約占總體延遲的33%。這是因為網(wǎng)絡(luò)協(xié)議棧在處理每個TCP 請求與響應(yīng)數(shù)據(jù)包時都需要幾百納秒的開銷,延遲敏感型請求數(shù)據(jù)包要等待大量非延遲敏感型請求數(shù)據(jù)包被協(xié)議棧接收處理后才能進(jìn)入?yún)f(xié)議棧處理。從該實(shí)驗中可以看到,混雜請求的排隊延遲會對延遲敏感型請求的響應(yīng)延遲產(chǎn)生嚴(yán)重干擾。
圖1 排隊延遲對響應(yīng)尾延遲的影響
請求間相互干擾的另一種方式,是處理時間長的復(fù)雜請求占用CPU 導(dǎo)致對處理簡單的延遲敏感型請求產(chǎn)生阻塞延遲。在證明該問題的實(shí)驗中,仿照數(shù)據(jù)庫服務(wù)場景大量微秒級簡單讀/寫請求混合少量毫秒級遍歷請求的負(fù)載模式[10],使用99.5%處理時間為1 μs 的延遲敏感型請求混合有0.5%處理時間為1 ms 的復(fù)雜請求。在mTCP 上測試了響應(yīng)尾延遲,并模擬計算了理論最優(yōu)響應(yīng)尾延遲(使用優(yōu)先級搶占調(diào)度的情況下)。如圖2 所示,因為復(fù)雜請求占用CPU 導(dǎo)致的阻塞,延遲敏感型請求的響應(yīng)尾延遲以階梯狀呈現(xiàn)快速上升,達(dá)到了理論最優(yōu)值的62 倍。
圖2 復(fù)雜請求阻塞延遲對響應(yīng)尾延遲的影響
請求間的相互干擾會導(dǎo)致延遲敏感型請求響應(yīng)尾延遲上升,因此數(shù)據(jù)中心服務(wù)需要對請求類型進(jìn)行識別并進(jìn)行優(yōu)先級調(diào)度。
傳統(tǒng)操作系統(tǒng)提供的內(nèi)核態(tài)協(xié)議棧使用內(nèi)核態(tài)驅(qū)動通過網(wǎng)卡硬中斷進(jìn)行數(shù)據(jù)包收取,并在隨后產(chǎn)生的軟中斷中對數(shù)據(jù)包進(jìn)行網(wǎng)絡(luò)協(xié)議處理,再由上層應(yīng)用調(diào)用套接字(socket)接口通過系統(tǒng)調(diào)用進(jìn)行數(shù)據(jù)收發(fā)。在使用內(nèi)核協(xié)議棧時,應(yīng)用可以通過eBPF[4]向內(nèi)核的網(wǎng)絡(luò)數(shù)據(jù)包處理流程的特定環(huán)節(jié)注冊回調(diào)函數(shù),根據(jù)數(shù)據(jù)包內(nèi)容及其他內(nèi)核協(xié)議棧相關(guān)信息實(shí)現(xiàn)豐富的調(diào)度策略。但是內(nèi)核協(xié)議棧因其中斷、系統(tǒng)調(diào)用、各級數(shù)據(jù)結(jié)構(gòu)的鎖等高額開銷,導(dǎo)致整體性能無法滿足當(dāng)今數(shù)據(jù)中心應(yīng)用的性能需求[5-6]。同時,開發(fā)人員需要為每個調(diào)度環(huán)節(jié)單獨(dú)進(jìn)行eBPF 代碼實(shí)現(xiàn)。如果有多種調(diào)度策略,還要將它們整合到一個函數(shù)中。受限于內(nèi)核的保護(hù)機(jī)制,內(nèi)核態(tài)的eBPF 代碼很難與用戶態(tài)應(yīng)用進(jìn)行通信,不同環(huán)節(jié)的eBPF 也只能分別對每個數(shù)據(jù)包進(jìn)行調(diào)度,很難實(shí)現(xiàn)不同層次間的協(xié)同調(diào)度。此外,隨著操作系統(tǒng)內(nèi)核的更新,開發(fā)人員還可能需要對eBPF 代碼重新進(jìn)行實(shí)現(xiàn)。
近年來,數(shù)據(jù)中心應(yīng)用普遍采用用戶態(tài)協(xié)議棧[5-11]的設(shè)計避免傳統(tǒng)操作系統(tǒng)內(nèi)核協(xié)議棧的性能瓶頸問題。用戶態(tài)協(xié)議棧使用用戶態(tài)驅(qū)動對網(wǎng)卡進(jìn)行輪詢,收取的數(shù)據(jù)包直接被送到用戶態(tài),在用戶態(tài)完成網(wǎng)絡(luò)協(xié)議處理后直接由上層應(yīng)用進(jìn)行收取,避免了操作系統(tǒng)內(nèi)核的中斷、系統(tǒng)調(diào)用等開銷,并通過批處理、內(nèi)存池管理等方式,大幅提升了網(wǎng)絡(luò)處理能力。相當(dāng)部分用戶態(tài)協(xié)議棧[5-7]采用先到先服務(wù)的處理,不考慮任務(wù)調(diào)度問題。也有一些用戶態(tài)協(xié)議棧以不識別請求內(nèi)容的形式對任務(wù)進(jìn)行調(diào)度,例如,ZygOS[8]、TAS (TCP acceleration as a service)[9]等用戶態(tài)協(xié)議棧以task-stealing[13]的方式對任務(wù)進(jìn)行調(diào)度,空閑的處理核可以從忙碌核的任務(wù)隊列“偷”任務(wù)進(jìn)行處理,一定程度上避免了復(fù)雜請求導(dǎo)致的阻塞延遲,但頻繁的任務(wù)偷取會引發(fā)嚴(yán)重的核間競爭導(dǎo)致系統(tǒng)開銷上升,且當(dāng)所有處理核都被復(fù)雜請求阻塞時還是會導(dǎo)致阻塞延遲。文獻(xiàn)[10]采用時間片的方式,由中心化協(xié)議棧線程將執(zhí)行時間過長的請求線程中斷并調(diào)度新任務(wù)執(zhí)行,以避免復(fù)雜請求導(dǎo)致的阻塞延遲,但會產(chǎn)生大量的上下文切換開銷。并且,不識別請求內(nèi)容的任務(wù)調(diào)度都無法避免排隊延遲對延遲敏感型請求響應(yīng)尾延遲的干擾。
LNS (labeled network stack)[2]是一個利用標(biāo)簽實(shí)現(xiàn)請求類型識別及優(yōu)先級調(diào)度的用戶態(tài)協(xié)議??蚣?。LNS 在客戶端將請求優(yōu)先級以標(biāo)簽的形式附著在請求數(shù)據(jù)包中。該優(yōu)先級標(biāo)簽在服務(wù)端由智能網(wǎng)卡進(jìn)行硬件識別處理,并根據(jù)優(yōu)先級標(biāo)簽,在網(wǎng)卡隊列調(diào)度、協(xié)議棧處理、事件框架、上層應(yīng)用處理等各個階段將請求放入不同優(yōu)先級隊列,以實(shí)現(xiàn)對高優(yōu)先級請求的優(yōu)先調(diào)度處理,避免了高優(yōu)先級請求受到排隊延遲對響應(yīng)尾延遲的干擾。但LNS 需要客戶端的配合并需要專用網(wǎng)卡硬件,無法大規(guī)模部署并缺乏支持豐富應(yīng)用的靈活性。此外,LNS 只能根據(jù)靜態(tài)的請求類型標(biāo)簽進(jìn)行優(yōu)先級調(diào)度,無法支持根據(jù)應(yīng)用在服務(wù)端對請求處理時間的測量調(diào)度不同復(fù)雜度的請求以避免阻塞延遲。
Perséphone[11]在網(wǎng)絡(luò)協(xié)議棧處理包后,在將請求提交到上層應(yīng)用處理前,使用一個應(yīng)用注冊的分析回調(diào)函數(shù)對請求內(nèi)容進(jìn)行識別(讀取應(yīng)用層協(xié)議頭類型,例如超文本協(xié)議讀請求、Redis 寫請求等),將請求分為不同類型。通過監(jiān)控每個類型請求的平均處理時間,為短請求和復(fù)雜請求分別賦予高優(yōu)先級和低優(yōu)先級。在把請求分發(fā)給worker 處理核進(jìn)行請求處理時,優(yōu)先分發(fā)高優(yōu)先級的請求,并預(yù)留部分處理核只用于高優(yōu)先級請求處理,從而有效避免了復(fù)雜請求對延遲敏感型請求產(chǎn)生的干擾。但是Perséphone 在傳輸層后才進(jìn)行優(yōu)先級識別與調(diào)度,無法避免延遲敏感型請求在協(xié)議棧處理過程中的排隊延遲。此外,Perséphone 只根據(jù)請求執(zhí)行時間進(jìn)行優(yōu)先級調(diào)度,但實(shí)際生產(chǎn)環(huán)境中可能存在大量執(zhí)行時間同樣不長但對響應(yīng)延遲并不敏感的低優(yōu)先級請求,引發(fā)排隊延遲導(dǎo)致的尾延遲上升。理論上Perséphone 的架構(gòu)也可以實(shí)現(xiàn)其他類型的調(diào)度策略,但是其調(diào)度函數(shù)只能使用應(yīng)用層提供的信息,且無法在不修改系統(tǒng)實(shí)現(xiàn)的情況下動態(tài)調(diào)節(jié)優(yōu)先級調(diào)度策略。
通過對以上問題的分析,本文提出了支持應(yīng)用定義優(yōu)先級調(diào)度的用戶態(tài)協(xié)議棧,通過支持各應(yīng)用靈活制定針對不同負(fù)載場景的優(yōu)先級識別策略,并加以由應(yīng)用定義的優(yōu)先級調(diào)度,避免延遲敏感型請求在請求處理中受到排隊延遲與阻塞延遲影響,以保障其響應(yīng)尾延遲及用戶體驗。
為了在用戶態(tài)協(xié)議棧上實(shí)現(xiàn)對延遲敏感型請求的靈活調(diào)度,本文提出了應(yīng)用定義優(yōu)先級調(diào)度,即讓用戶態(tài)協(xié)議棧在不修改協(xié)議棧本身的情況下,支持?jǐn)?shù)據(jù)中心維護(hù)人員及各類數(shù)據(jù)中心應(yīng)用根據(jù)自身負(fù)載特征制定對延遲敏感型請求的識別與調(diào)度策略。
為此,設(shè)計了盡早對延遲敏感型請求進(jìn)行識別以避免排隊延遲的應(yīng)用定義驅(qū)動層優(yōu)先級識別(詳見2.1 節(jié)),設(shè)計了支持應(yīng)用定制豐富的優(yōu)先級識別策略的應(yīng)用定義傳輸層優(yōu)先級識別(詳見2.2節(jié)),并設(shè)計了用戶態(tài)協(xié)議棧對優(yōu)先級信息的傳遞以及對應(yīng)用定義優(yōu)先級調(diào)度的支持(詳見2.3 節(jié))。通過以上設(shè)計,用戶態(tài)協(xié)議棧能夠靈活支持不同負(fù)載場景下的延遲敏感型請求優(yōu)先級調(diào)度,為其響應(yīng)尾延遲與用戶體驗提供保障。
驅(qū)動層負(fù)責(zé)從網(wǎng)卡收發(fā)數(shù)據(jù)包,是數(shù)據(jù)包進(jìn)入服務(wù)端軟件棧的第一步,因此在驅(qū)動層實(shí)現(xiàn)優(yōu)先級識別可以避免后續(xù)請求處理階段的排隊延遲。
如圖3(a) 所示,應(yīng)用定義驅(qū)動層優(yōu)先級識別讓應(yīng)用以注冊回調(diào)函數(shù)的形式將優(yōu)先級識別函數(shù)pri_filter()加入到驅(qū)動層處理。在用戶態(tài)協(xié)議棧從網(wǎng)卡接收數(shù)據(jù)包并放入接收緩沖區(qū)時,對每一個數(shù)據(jù)包都調(diào)用該回調(diào)函數(shù)?;卣{(diào)函數(shù)返回的優(yōu)先級會被寫入數(shù)據(jù)包元數(shù)據(jù),數(shù)據(jù)包也會被放入對應(yīng)優(yōu)先級的接收緩沖區(qū)中,在后續(xù)處理中進(jìn)行優(yōu)先級調(diào)度。
圖3 應(yīng)用定義優(yōu)先級識別架構(gòu)示意圖
應(yīng)用定義的驅(qū)動層優(yōu)先級識別必須能夠快速對數(shù)據(jù)包進(jìn)行優(yōu)先級區(qū)分,否則可能對后續(xù)所有處理產(chǎn)生阻塞。得益于直接數(shù)據(jù)輸入輸出(data direct I/O,DDIO)[14]技術(shù)的支持,應(yīng)用定義的驅(qū)動層優(yōu)先級識別函數(shù)所使用的數(shù)據(jù)(數(shù)據(jù)包元數(shù)據(jù)與數(shù)據(jù)包內(nèi)容)都會被存放在處理器cache 中,避免了訪存延遲與開銷,進(jìn)行簡單的協(xié)議頭解析與標(biāo)志位識別的額外開銷在50 ns 以下。
在應(yīng)用定義的驅(qū)動層優(yōu)先級分類函數(shù)中,可用于輔助優(yōu)先級識別的輸入信息包括數(shù)據(jù)包的元數(shù)據(jù)(例如數(shù)據(jù)包長等)以及數(shù)據(jù)包本身數(shù)據(jù)內(nèi)容(例如協(xié)議頭固定標(biāo)志位提取等)。以下為使用驅(qū)動層優(yōu)先級識別的2 個典型場景舉例。
場景1吞吐密集型應(yīng)用在傳輸大塊數(shù)據(jù)時通常每個數(shù)據(jù)包都會達(dá)到最大傳輸單元(maximum transmission unit,MTU)上限,因此可根據(jù)數(shù)據(jù)包元信息中的數(shù)據(jù)包長度進(jìn)行優(yōu)先級識別,將長度超過閾值的數(shù)據(jù)包設(shè)置為低優(yōu)先級。
場景2對數(shù)據(jù)包請求頭部進(jìn)行優(yōu)先級關(guān)鍵字提取,識別客戶端寫入的優(yōu)先級標(biāo)簽(兼容LNS)或是對請求類型進(jìn)行識別(區(qū)分讀請求及寫請求等)。
傳輸層[15]負(fù)責(zé)為應(yīng)用進(jìn)程提供端到端的通信服務(wù)。在傳輸層,除數(shù)據(jù)包信息外,還可以獲取流狀態(tài)等信息,并通過socket 抽象與上層應(yīng)用通信,在此可以利用豐富的語義信息實(shí)現(xiàn)靈活準(zhǔn)確的優(yōu)先級識別策略。本文在傳輸層主要討論對TCP 協(xié)議的支持與處理,但該設(shè)計思想適用于所有傳輸層協(xié)議。
如圖3(b) 所示,應(yīng)用定義傳輸層優(yōu)先級識別讓協(xié)議棧支持應(yīng)用以注冊回調(diào)函數(shù)的形式為每一條TCP連接注冊傳輸層優(yōu)先級識別函數(shù)pri_extraction()。每當(dāng)TCP/IP 協(xié)議棧處理到帶有TCP 負(fù)載的數(shù)據(jù)包時,會對該數(shù)據(jù)包調(diào)用當(dāng)前TCP 連接對應(yīng)的優(yōu)先級識別回調(diào)函數(shù)進(jìn)行優(yōu)先級信息分析。分析得到的優(yōu)先級被寫入數(shù)據(jù)包的元數(shù)據(jù)及向事件框架添加的事件中,在后續(xù)處理中進(jìn)行優(yōu)先級調(diào)度。
應(yīng)用可以通過多種方式靈活地注冊傳輸層優(yōu)先級識別回調(diào)函數(shù)。數(shù)據(jù)中心供應(yīng)商可根據(jù)常見的調(diào)度策略及自身負(fù)載特征,定制默認(rèn)的優(yōu)先級識別方案。應(yīng)用可以向TCP 的listener 注冊優(yōu)先級識別函數(shù),該識別函數(shù)會成為從該listener 接收到的TCP 連接的默認(rèn)優(yōu)先級識別函數(shù),從而讓一個數(shù)據(jù)中心應(yīng)用的所有TCP 連接都使用根據(jù)該應(yīng)用請求特征定制的優(yōu)先級識別函數(shù)。應(yīng)用也可以通過socket 接口為某個TCP 流注冊特定的優(yōu)先級分析函數(shù)。甚至在優(yōu)先級識別函數(shù)處理過程中,可以根據(jù)狀態(tài)的改變,為當(dāng)前TCP 流更換使用新的優(yōu)先級識別函數(shù)。通過為每個TCP 連接注冊獨(dú)立的優(yōu)先級識別函數(shù),可以避免單個優(yōu)先級識別函數(shù)處理過多應(yīng)用類型導(dǎo)致處理過程冗長,從而避免對系統(tǒng)整體性能產(chǎn)生影響。
傳輸層優(yōu)先級識別可以利用豐富的數(shù)據(jù)包與TCP 流狀態(tài)信息對數(shù)據(jù)包優(yōu)先級進(jìn)行識別。以下為使用TCP 狀態(tài)進(jìn)行優(yōu)先級識別的2 個典型場景的舉例。
場景3對于來自廣域網(wǎng)高丟包高延遲鏈路的請求,用戶對響應(yīng)延遲的小幅度波動并不敏感[3],而相同的響應(yīng)延遲波動會對低網(wǎng)絡(luò)延遲用戶的體驗產(chǎn)生較大影響。因此根據(jù)TCP 連接擁塞控制提取的往返延遲(round trip time,RTT)及丟包率等信息,將來自網(wǎng)絡(luò)狀況較差的連接的請求標(biāo)記為低優(yōu)先級。
場景4根據(jù)當(dāng)前TCP 連接已經(jīng)傳輸?shù)淖止?jié)數(shù),將已接收數(shù)據(jù)量超過閾值的TCP 連接視為來自吞吐密集型應(yīng)用,將其請求標(biāo)記為低優(yōu)先級。
當(dāng)進(jìn)行傳輸層優(yōu)先級識別時,如果該數(shù)據(jù)包已經(jīng)通過驅(qū)動層優(yōu)先級識別獲取了優(yōu)先級,可以在傳輸層優(yōu)先級識別過程中讀取數(shù)據(jù)包元數(shù)據(jù)中的優(yōu)先級信息作為參考,并可以對其進(jìn)行覆蓋。
為支持應(yīng)用定義優(yōu)先級函數(shù)進(jìn)行跨數(shù)據(jù)包的有狀態(tài)分析,以及與上層應(yīng)用的通信,如圖3(b) 所示,為每個TCP 連接設(shè)置了長度為64 字節(jié)(一個cacheline)的專用于優(yōu)先級識別的私有域(在系統(tǒng)中,該64 字節(jié)占TCP 狀態(tài)信息結(jié)構(gòu)體的7%)。傳輸層優(yōu)先級函數(shù)可對所屬TCP 連接的私有域進(jìn)行讀寫操作,將優(yōu)先級分析的中間狀態(tài)暫存,從而實(shí)現(xiàn)有狀態(tài)的分析。上層應(yīng)用也可通過socket 接口直接訪問該私有域,從而實(shí)現(xiàn)應(yīng)用與優(yōu)先級識別函數(shù)的通信。此外,得益于用戶態(tài)協(xié)議棧中協(xié)議棧處理與應(yīng)用線程位于同一個命名空間(namespace),優(yōu)先級識別函數(shù)可以直接使用上層應(yīng)用傳遞的指針及對應(yīng)的內(nèi)存空間。以下為利用私有域進(jìn)行優(yōu)先級識別的2 個典型場景的舉例。
場景5當(dāng)請求長度超出單個數(shù)據(jù)包長度上限時,優(yōu)先級分析函數(shù)在私有域中記錄當(dāng)前請求未讀取長度或匹配結(jié)束符,該TCP 連接后續(xù)屬于同一請求的數(shù)據(jù)包將被標(biāo)記為與該請求第一個數(shù)據(jù)包相同的優(yōu)先級。
場景6上層應(yīng)用在處理請求過程中統(tǒng)計每個類型請求的執(zhí)行時間并進(jìn)行估計,通過私有域下發(fā)到優(yōu)先級識別函數(shù),將預(yù)計執(zhí)行時間超過閾值的請求標(biāo)記為低優(yōu)先級。
應(yīng)用定義優(yōu)先級識別得到的優(yōu)先級信息需要在協(xié)議棧處理的各個階段間進(jìn)行傳遞。如圖3 所示,由應(yīng)用定義優(yōu)先級識別函數(shù)返回的優(yōu)先級會被寫入到對應(yīng)請求數(shù)據(jù)包的元數(shù)據(jù)的優(yōu)先級標(biāo)志位中,并隨數(shù)據(jù)包被傳遞到后續(xù)階段。當(dāng)請求數(shù)據(jù)包被放入TCP 接收緩沖區(qū)時,協(xié)議棧需要通過類epoll[16]的事件框架生成收包事件以提醒上層應(yīng)用收取數(shù)據(jù),并將數(shù)據(jù)包的優(yōu)先級寫入到事件結(jié)構(gòu)體中,由事件框架根據(jù)事件優(yōu)先級對其進(jìn)行調(diào)度。
協(xié)議棧需要根據(jù)優(yōu)先級信息在各個處理階段對請求進(jìn)行調(diào)度。為避免1.1 節(jié)所分析的排隊延遲對延遲敏感型請求響應(yīng)尾延遲的影響,在協(xié)議棧從驅(qū)動接收緩沖區(qū)收取數(shù)據(jù)包以及上層應(yīng)用從事件隊列收取事件時,采用了類似LNS 的基于數(shù)據(jù)包和事件優(yōu)先級的優(yōu)先隊列調(diào)度[2]。
本文設(shè)計了應(yīng)用定義的事件框架優(yōu)先級調(diào)度。協(xié)議棧支持上層應(yīng)用調(diào)用事件框架接口時收取指定優(yōu)先級事件,從而實(shí)現(xiàn)更復(fù)雜的應(yīng)用定義優(yōu)先隊列調(diào)度,例如,避免低優(yōu)先級請求得不到處理而餓死。同時,上層應(yīng)用可通過配置事件框架,將不同優(yōu)先級的事件只分發(fā)到指定處理核。例如,場景6 中將識別到的低優(yōu)先級復(fù)雜請求分流到單獨(dú)處理核進(jìn)行處理,避免產(chǎn)生1.1 節(jié)所分析的阻塞延遲。
本文在LNS[2]的基礎(chǔ)上對支持應(yīng)用定義優(yōu)先級調(diào)度的用戶態(tài)協(xié)議棧進(jìn)行了實(shí)現(xiàn),在利用LNS 已有的用戶態(tài)協(xié)議棧優(yōu)先級調(diào)度框架基礎(chǔ)上,增加了應(yīng)用定義的優(yōu)先級識別與應(yīng)用定義的事件框架優(yōu)先級調(diào)度支持。修改與增加的代碼量在2000 行左右。如圖4 所示,在LNS 的基礎(chǔ)上,在驅(qū)動層,將智能網(wǎng)卡驅(qū)動更換為數(shù)據(jù)平面開發(fā)套件(data plane development kit,DPDK)的通用網(wǎng)卡驅(qū)動,并加入應(yīng)用定義優(yōu)先級識別;在傳輸層,加入應(yīng)用定義傳輸層優(yōu)先級識別支持,并對TCP 連接對象增加了私有域等數(shù)據(jù)結(jié)構(gòu)支持;在事件框架,在優(yōu)先隊列調(diào)度的基礎(chǔ)上增加了應(yīng)用定義事件框架優(yōu)先級調(diào)度的支持。
圖4 面向應(yīng)用定義優(yōu)先級調(diào)度的用戶態(tài)協(xié)議棧實(shí)現(xiàn)
此外,本文還移植了lighttpd[17],一個開源Web服務(wù)器,以驗證應(yīng)用定義優(yōu)先級調(diào)度的用戶態(tài)協(xié)議棧在真實(shí)應(yīng)用上的效果。選擇支持用戶態(tài)協(xié)議棧與多線程模式的mTCP 版本lighttpd 進(jìn)行移植[5],并加入了基于場景3 的優(yōu)先級識別函數(shù)注冊等配置修改,根據(jù)擁塞控制模塊的RTT 統(tǒng)計及丟包統(tǒng)計,將網(wǎng)絡(luò)狀況好的TCP 流的請求標(biāo)記為高優(yōu)先級。修改與增加的代碼量在100 行左右。
本節(jié)驗證了應(yīng)用定義優(yōu)先級調(diào)度在不同的負(fù)載場景下,可以通過定制優(yōu)先級識別策略實(shí)現(xiàn)對延遲敏感型請求的靈活準(zhǔn)確識別,并通過優(yōu)先級調(diào)度保證其響應(yīng)尾延遲,保障用戶體驗。
本實(shí)驗中使用1 臺客戶端和1 臺服務(wù)器,對應(yīng)用定義優(yōu)先級調(diào)度的用戶態(tài)協(xié)議棧的系統(tǒng)效果進(jìn)行評測。服務(wù)端和客戶端服務(wù)器均使用E5-2630 v4 2.2 GHz 處理器,64 GB 內(nèi)存,Intel82599 10 Gbps 網(wǎng)卡。
在服務(wù)端,部署了如第3 節(jié)所述的支持應(yīng)用定義優(yōu)先級調(diào)度的用戶態(tài)協(xié)議棧;實(shí)現(xiàn)了一個虛擬負(fù)載服務(wù)應(yīng)用(synthetic server),對收取到的每個請求一段時間處理后返回響應(yīng),請求處理時間由請求內(nèi)的相關(guān)域指定。
在該應(yīng)用上,使用應(yīng)用定義驅(qū)動優(yōu)先級識別實(shí)現(xiàn)了對LNS 的模擬,以避免使用專用網(wǎng)卡硬件,該調(diào)度效果與LNS 基本完全一致;還在協(xié)議棧與應(yīng)用層間增加了任務(wù)調(diào)度器,實(shí)現(xiàn)了對Perséphone 的DARC(dynamic application-aware reserved cores)調(diào)度算法[11]的模擬,并將優(yōu)先級調(diào)度支持范圍擴(kuò)展到相同處理時間的不同類型請求上。將這2 種調(diào)度方式與本文設(shè)計的應(yīng)用定義優(yōu)先級調(diào)度(applicationdefined priority scheduling,ADPS)進(jìn)行了對比。此外,還對移植后的lighttpd 進(jìn)行了測試。
在客戶端,使用一款開源負(fù)載發(fā)生器MCC(massive concurrent connection)[18]來進(jìn)行流量生成。MCC 可以生成突發(fā)式負(fù)載,將每秒生成的請求以網(wǎng)絡(luò)線速的速度進(jìn)行發(fā)送,以測試服務(wù)端在面對突發(fā)流量時的響應(yīng)尾延遲。MCC 可以生成虛擬負(fù)載請求,在請求內(nèi)部寫入每個請求在服務(wù)端需要處理的時間,并在請求頭部寫入請求類型以進(jìn)行優(yōu)先級識別。MCC 同樣可以生成超文本傳輸協(xié)議(hyper text transfer protocol,HTTP) 請求負(fù)載,用于lighttpd 的測試。每組實(shí)驗重復(fù)4 次,取其平均值作為結(jié)果。
測試應(yīng)用定義驅(qū)動層優(yōu)先級識別對延遲敏感型請求響應(yīng)尾延遲的影響(場景2)。使用MCC 生成虛擬負(fù)載請求,每個請求處理時間為10 ms,5%的請求通過類型被標(biāo)記為高優(yōu)先級延遲敏感型請求,并統(tǒng)計該類型請求的99th 響應(yīng)尾延遲。在服務(wù)端,使用應(yīng)用定義驅(qū)動層優(yōu)先級識別對數(shù)據(jù)包優(yōu)先級進(jìn)行識別,并與Perséphone 在協(xié)議棧后進(jìn)行優(yōu)先級識別調(diào)度的方式進(jìn)行了對比。
如圖5 所示,使用應(yīng)用定義驅(qū)動層優(yōu)先級識別,由于有效地避免了高優(yōu)先級請求的排隊延遲,延遲敏感型請求的響應(yīng)尾延遲相比沒有優(yōu)先級調(diào)度時降低了98.5%。而Perséphone 雖然在協(xié)議棧處理后對請求優(yōu)先級進(jìn)行識別并進(jìn)行調(diào)度,避免了在應(yīng)用層的排隊延遲,但延遲敏感型請求依然會在數(shù)據(jù)包接收緩沖區(qū)等待協(xié)議棧處理時經(jīng)歷排隊延遲,因此延遲敏感型請求的響應(yīng)尾延遲比使用應(yīng)用定義驅(qū)動層優(yōu)先級識別時高24.5 倍。
圖5 應(yīng)用定義驅(qū)動層優(yōu)先級識別響應(yīng)尾延遲
此外,場景1 與場景4 的表現(xiàn)與本實(shí)驗有所重合。場景1 與場景4 優(yōu)先級調(diào)度目的均為區(qū)分延遲敏感型應(yīng)用請求與吞吐密集型應(yīng)用請求,方法區(qū)別為場景1 在驅(qū)動層通過數(shù)據(jù)包長度區(qū)分,場景4 在傳輸層通過TCP 流傳輸數(shù)據(jù)量區(qū)分。實(shí)驗發(fā)現(xiàn),通過將吞吐密集型應(yīng)用請求調(diào)度為低優(yōu)先級,可以有效降低延遲敏感型請求響應(yīng)尾延遲。在傳輸層通過TCP 連接數(shù)據(jù)量識別請求類型時(場景4)表現(xiàn)與圖5的Perséphone 基本一致,而使用應(yīng)用定義驅(qū)動層優(yōu)先級識別時(場景1),因為避免了數(shù)據(jù)包在接收緩沖區(qū)排隊,能夠進(jìn)一步降低延遲敏感型請求響應(yīng)尾延遲,并與圖5 的ADPS 基本一致。
本實(shí)驗驗證了應(yīng)用定義事件框架優(yōu)先級調(diào)度在混合有不同處理復(fù)雜度的請求時對延遲敏感型請求尾延遲的保證(場景6)。使用MCC 生成虛擬負(fù)載請求,99.5%處理時間為1 μs,0.5% 處理時間為1 ms,并統(tǒng)計1 ms 請求的響應(yīng)尾延遲。在服務(wù)端,使用應(yīng)用定義驅(qū)動層優(yōu)先級識別將1 μs 請求定義為高優(yōu)先級,1 ms 請求定義為低優(yōu)先級。在事件框架使用應(yīng)用定義優(yōu)先級調(diào)度,將低優(yōu)先級事件分流到一個特定核進(jìn)行處理,該核只負(fù)責(zé)處理低優(yōu)先級事件,以避免產(chǎn)生阻塞干擾。同時,對比了LNS 只進(jìn)行優(yōu)先級隊列調(diào)度的模式,以及沒有優(yōu)先級調(diào)度下的響應(yīng)尾延遲。
如圖6 所示,在沒有優(yōu)先級調(diào)度時,受到復(fù)雜請求的阻塞干擾,延遲敏感型請求響應(yīng)尾延遲呈階梯狀迅速上升。LNS 通過優(yōu)先級隊列實(shí)現(xiàn)了響應(yīng)尾延遲的大幅下降,但因為處理核在處理完高優(yōu)先級請求后開始處理低優(yōu)先級的復(fù)雜請求,導(dǎo)致后續(xù)到達(dá)的高優(yōu)先級請求被阻塞,引發(fā)阻塞延遲。而使用應(yīng)用定義事件框架優(yōu)先級調(diào)度的情況下,低優(yōu)先級的復(fù)雜請求完全不會對高優(yōu)先級請求處理產(chǎn)生任何影響,有效地將響應(yīng)尾延遲降低到?jīng)]有優(yōu)先級調(diào)度時的1.6%。
圖6 99.5% 1 μs+0.5% 1 ms 混合請求響應(yīng)尾延遲
本實(shí)驗驗證了應(yīng)用定義傳輸層優(yōu)先級識別中使用TCP 流私有域進(jìn)行跨數(shù)據(jù)包有狀態(tài)優(yōu)先級分析的作用(場景5)。用MCC 生成虛擬負(fù)載請求,每個請求執(zhí)行時間為100 μs,5%的請求通過類型被標(biāo)記為高優(yōu)先級延遲敏感型請求,并統(tǒng)計該類型請求的99th 響應(yīng)尾延遲。實(shí)驗分2 次進(jìn)行,請求長度分別為1024 字節(jié)(需要1 個TCP 包傳輸)和4096 字節(jié)(需要3 個TCP 包傳輸),請求的長度被寫在請求頭部。在服務(wù)端,使用應(yīng)用定義傳輸層優(yōu)先級識別,根據(jù)請求頭部中的請求類型判斷優(yōu)先級。當(dāng)請求長度超過單個TCP 包上限時,記錄當(dāng)前未讀取數(shù)據(jù)字節(jié)數(shù)及對應(yīng)優(yōu)先級,將該TCP 流后續(xù)屬于該請求的數(shù)據(jù)包標(biāo)記為相同優(yōu)先級。使用應(yīng)用定義驅(qū)動層優(yōu)先級識別來復(fù)現(xiàn)沒有客戶端配合時的LNS 調(diào)度。因為沒有在每個數(shù)據(jù)包內(nèi)加入優(yōu)先級標(biāo)簽,當(dāng)請求長度超過一個TCP 包長度時,LNS 只能識別第一個數(shù)據(jù)包的優(yōu)先級,并將該請求的后續(xù)數(shù)據(jù)包標(biāo)記為低優(yōu)先級。
如圖7 所示,在請求長度為1024 字節(jié)時,應(yīng)用定義優(yōu)先級調(diào)度和LNS 都能對延遲敏感型請求進(jìn)行有效的優(yōu)先級調(diào)度,尾延遲為無優(yōu)先級調(diào)度時的6%。但當(dāng)請求長度上升到4096 字節(jié)時,因為LNS無法對請求后幾個數(shù)據(jù)包進(jìn)行正確優(yōu)先級識別,導(dǎo)致延遲敏感型請求受到排隊延遲影響。LNS 在4096 字節(jié)時延遲敏感型請求的響應(yīng)尾延遲還是優(yōu)于無優(yōu)先級調(diào)度。這是因為在上層應(yīng)用收取到高優(yōu)先級收包事件時會嘗試收取當(dāng)前TCP 連接所有數(shù)據(jù),如果該請求的所有數(shù)據(jù)包都已在TCP接收緩沖區(qū)中,則高優(yōu)先級請求立刻可以得到處理。Perséphone 沒有支持跨數(shù)據(jù)包請求優(yōu)先級識別,表現(xiàn)與LNS 基本一致。
圖7 不同長度的混合優(yōu)先級請求響應(yīng)尾延遲
本實(shí)驗驗證了應(yīng)用定義傳輸層優(yōu)先級識別中使用TCP 相關(guān)狀態(tài)判斷網(wǎng)絡(luò)狀態(tài),從而對請求做出優(yōu)先級調(diào)度的效果(場景3)。該場景的依據(jù),來自于文獻(xiàn)[3]。在不同的請求響應(yīng)延遲階段,響應(yīng)延遲波動對用戶體驗質(zhì)量(quality of experience,QoE)的影響是不同的,基本延遲較低時響應(yīng)延遲波動會帶來更大的QoE 損失。
用MCC 與客戶端保持1000 條長連接發(fā)送HTTP 請求,并通過流量控制工具,為50%的TCP 連接增加50 ms 的網(wǎng)絡(luò)延遲(網(wǎng)絡(luò)狀況較好),為剩余50%的TCP 連接增加200 ms 的網(wǎng)絡(luò)延遲和1%的隨機(jī)丟包(網(wǎng)絡(luò)狀況較差)。分別統(tǒng)計這2 種TCP連接的響應(yīng)延遲,并根據(jù)文獻(xiàn)[3]對Web 應(yīng)用場景的QoE 模型評估用戶體驗(使用歸一化值)。在服務(wù)端,使用支持應(yīng)用定義優(yōu)先級調(diào)度的lighttpd 對每個HTTP 請求經(jīng)過后端處理后返回長度為1 MB 的響應(yīng),通過應(yīng)用定義傳輸層優(yōu)先級識別,根據(jù)擁塞控制模塊的RTT 統(tǒng)計及丟包統(tǒng)計,將網(wǎng)絡(luò)狀況好的TCP 流的請求標(biāo)記為高優(yōu)先級。
如表1 所示,網(wǎng)絡(luò)狀況較好的TCP 連接的請求的99th 響應(yīng)尾延遲有優(yōu)先級調(diào)度時相比沒有優(yōu)先級調(diào)度的情況下降低了2.14 s,由此帶來0.4的QoE提升,其代價是網(wǎng)絡(luò)狀況較差的TCP 連接的請求的99th QoE 下降了0.01。而在請求響應(yīng)的中位數(shù)(50th)上,網(wǎng)絡(luò)狀況較好的TCP 連接的響應(yīng)延遲在有優(yōu)先級調(diào)度時降低了1.05 s,由此帶來0.16 的QoE提升,而網(wǎng)絡(luò)延遲較差的請求的QoE會對應(yīng)下降0.06。由此可以得出結(jié)論,在Web 服務(wù)場景中,當(dāng)使用應(yīng)用定義的傳輸層優(yōu)先級識別根據(jù)網(wǎng)絡(luò)狀況為請求進(jìn)行優(yōu)先級調(diào)度時,可以顯著地提升網(wǎng)絡(luò)較好的用戶的服務(wù)體驗,并且不會對網(wǎng)絡(luò)較差的用戶的服務(wù)體驗產(chǎn)生較大影響。
面對數(shù)據(jù)中心混雜的請求負(fù)載,本文分析了對延遲敏感型請求響應(yīng)尾延遲產(chǎn)生干擾的2 種主要來源,即大量非延遲敏感請求產(chǎn)生的排隊延遲及復(fù)雜請求產(chǎn)生的阻塞延遲。針對這2 種混雜請求帶來的干擾,本文提出使用用戶態(tài)協(xié)議棧對數(shù)據(jù)中心請求進(jìn)行處理,并在用戶態(tài)協(xié)議棧上根據(jù)服務(wù)等級目標(biāo)對請求采取靈活優(yōu)先級調(diào)度是保障延遲敏感型請求的有效方法。本文提出通過支持上層應(yīng)用向用戶態(tài)協(xié)議棧驅(qū)動層與傳輸層注冊應(yīng)用定義的優(yōu)先級識別回調(diào)函數(shù),利用數(shù)據(jù)包、TCP 流等豐富的狀態(tài)信息,根據(jù)負(fù)載特征與應(yīng)用場景需求,在不修改網(wǎng)絡(luò)協(xié)議棧的情況下,對多種數(shù)據(jù)中心應(yīng)用及負(fù)載場景實(shí)現(xiàn)靈活的應(yīng)用定義優(yōu)先級識別與優(yōu)先級調(diào)度。實(shí)驗表明,該設(shè)計可以有效避免混合負(fù)載請求對延遲敏感型請求響應(yīng)尾延遲的干擾,保證用戶體驗。但是,應(yīng)用定義優(yōu)先級調(diào)度的用戶態(tài)協(xié)議棧還存在進(jìn)一步改進(jìn)的空間。例如,各個層次的優(yōu)先級識別與調(diào)度間可以實(shí)現(xiàn)更緊密的動態(tài)協(xié)同,應(yīng)用定義的優(yōu)先級調(diào)度需要有更靈活、更公平的策略與調(diào)度語義支持,需要考慮多種優(yōu)先級調(diào)度策略組合以及需要有更多的優(yōu)先級等級以適應(yīng)多場景組合時更復(fù)雜的優(yōu)先關(guān)系等。