陳鮑孜,吳慶波,譚郁松
(國防科學技術大學計算機學院,湖南 長沙410073)
云計算是繼20世紀80年代大型機到客戶端-服務器的大轉變后的又一次巨變,它基于互聯(lián)網(wǎng)的計算方式,將共享的軟硬件資源和信息按需提供給計算機和其他設備。與傳統(tǒng)高性能計算應用長時間滿負荷的系統(tǒng)負載相比,云計算的系統(tǒng)負載會隨著事件而波動,服務器利用率通常在10%~50%。
云計算一方面對服務資源進行聚合并統(tǒng)一調配,另一方面又對應用程序透明并表現(xiàn)出一定程度的虛擬化。進行資源聚合的一種重要方式是將不同用戶、不同特征的應用聚合起來進行混合部署、同時運行。如何更有效地提高云計算中大規(guī)模數(shù)據(jù)中心的服務器資源利用率,降低基礎架構運營開銷,始終是云計算基礎架構所重點考慮的問題。
云計算環(huán)境下,應用程序混合部署與同時運行要求操作系統(tǒng)能夠有效地進行資源管理。有效的資源管理應該包括五個方面的內容:資源限制、資源隔離、優(yōu)先級、資源統(tǒng)計與資源控制。其中,最關鍵的因素是資源限制,它包括了以下兩個方面的內容:
(1)限制應用對資源的消費額度;
(2)當資源消費接近額度時,系統(tǒng)采取的相應操作。
研究表明,將內存回收工作部分提交到應用程序的層面來完成會帶來兩大優(yōu)勢:首先,應用程序進行垃圾回收比系統(tǒng)級的頁面回收所需要的代價相對較??;其次,應用程序對所維護緩存頁的冷熱程度更加清楚,回收釋放時更加具有針對性。對于內存資源的管理,操作系統(tǒng)與應用協(xié)同進行管理的模式能夠有效地提升系統(tǒng)的效率。
為了降低運營成本,云計算平臺通常需要在保證服務質量QoS(Quality of Service)的前提下盡可能地進行資源聚合。常用的資源聚合方式之一是使用虛擬化技術將不同的服務整合到同一個物理節(jié)點中,并通過內存超售(Overcommit)技術進一步提高物理資源的使用效率。
資源的高度整合使得不同應用之間對資源產(chǎn)生競爭。但是,如果采用經(jīng)典操作系統(tǒng)的內存管理方式,容易造成不同應用之間的性能抖動。為了保證應用程序的QoS,人們通常使用系統(tǒng)級虛擬化技術(如Xen、KVM等)對單獨應用程序所消費的內存資源進行一定程度的隔離,通過氣球驅動(Balloon Driver)[1]等內存管理技術,使得內存資源可以彈性地根據(jù)需求進行動態(tài)分配。Schwidefsky M等人[2]在Linux系統(tǒng)上實現(xiàn)了一種協(xié)作式的內存管理方法,宿主操作系統(tǒng)與客戶操作系統(tǒng)通過交換共享內存頁面的使用與駐留集大小的信息,降低了換頁的概率,提高了系統(tǒng)整體性能。然而,在某些高度聚合云計算應用場景中,由于單節(jié)點內的應用實例不斷增加,系統(tǒng)級虛擬化自身的開銷占總體資源消耗的比重越來越大,因此人們開始尋找更輕量級的解決方案。
同時,為了進一步降低應用實例之間競爭內存資源時帶來的性能抖動,許多研究者提出了操作系統(tǒng)與應用程序相互協(xié)同的內存管理策略。
Iyer S等人[3]指出,在多數(shù)情況下,操作系統(tǒng)內核對應用程序實際的內存資源使用情況并非十分精確,以至于用戶態(tài)應用程序實際上并不總是能夠最優(yōu)化地自動對內存進行申請與釋放。Yang T等人[4]設計實現(xiàn)了CRAMM系統(tǒng),該系統(tǒng)由操作系統(tǒng)內核與改進后的用戶態(tài)JVM虛擬機兩個重要的部分構成。CRAMM的操作系統(tǒng)內核負責收集、統(tǒng)計系統(tǒng)內存資源使用情況并反饋到用戶態(tài)的JVM虛擬機中。用戶態(tài)JVM虛擬機根據(jù)內核反饋的信息進行有針對性的垃圾回收工作,使得應用程序的堆維持在合適大小,提高系統(tǒng)整體吞吐效率。Hines M R等人[5]設計實現(xiàn)了Ginkgo,將內存使用的信息與應用程序性能進行關聯(lián)建模,通過在JVM虛擬機實例之間合理地對內存資源進行重新部署與分配,以較小的性能回退代價節(jié)約了大約27%的內存消耗,有效的提升了系統(tǒng)整體聚合能力。
本文在總結前人研究的基礎之上,結合Linux內核中成熟的進程控制組機制以及eventfd事件通知機制,設計實現(xiàn)了一個簡單高效的應用協(xié)同分組內存管理的內核支撐機制。通過該機制,可進一步提升云計算基礎架構中內存資源利用率。
在Linux內核發(fā)展的歷史上,人們做了許多關于進程資源分組管理的工作。這些工作可以劃分為兩個方面的內容:一類為資源的監(jiān)控,另一類為利用名字空間進行隔離。從另一個角度看,這兩方面的工作實際上也是緊密相關的,它們都試圖防止進程不受限制地消耗所有的系統(tǒng)資源,從而獲得更高的系統(tǒng)利用率與更好的QoS。
早期UNIX操作系統(tǒng)關于資源限制與管理的手段有限,主要是通過XSI擴展中所規(guī)定的getrlimit()與setrlimit()系統(tǒng)調用對內核中struct rlimit結構體所描述的資源進行的配置。但是,rlimit機制主要是針對單個進程的資源,無法對進程組進行約束。
隨著內核級容器虛擬化技術的出現(xiàn),人們開始關注對進程組資源進行統(tǒng)一管理的機制與策略。在Linux內核2.2版本中,由Cox A與Savochkin A共同開發(fā)了User Beancounter機制,用于彌補setlimit()限制與管理進程組的不足。在此基礎上,Emelianov P等人[6]改良了Beancounter的機制,并將其作為Linux內核級容器虛擬化Open VZ項目的核心技術應用到實際的工程領域。在Open VZ的實現(xiàn)中,Beancounter代表了進程組消費資源的統(tǒng)計,它由一個ID號以及一組資源限制參數(shù)組成。而進程分組則依賴于Linux內核的名字空間。Open VZ通過將進程統(tǒng)一劃分到某個名字空間來實現(xiàn)容器間的隔離,同時完成對容器內進程集合的內存資源限制。
然而,Open VZ作為Linux內核級容器虛擬化技術的代表,更加關注不同VE(Virtual Environment)之間的隔離性以及對包括vma與kmem在內的各種內存資源的精確審計。由于不同VE之間需要用名字空間隔離開來,Open VZ中進程組實際上以不同的VE為組織單位。而一個VE是一個完整的操作系統(tǒng)用戶空間,包含了必要的運行時環(huán)境及守護進程。因此,作為通用的基于進程組的內存管理技術,Beancounter顯得不夠靈活。
為了使Linux內核具備通用的進程組容器機制,Google公司的 Menage P B[7]設計實現(xiàn)了控制組(Cgroup)?;贚inux內核中的控制組機制,人們可以更方便地實現(xiàn)關于進程內存資源的分組管理。
Linux內核控制組的設計目標是為資源管理提供一個統(tǒng)一的框架,包括整合已有的cpuset等子系統(tǒng),并為未來開發(fā)新的資源管理子系統(tǒng)提供基本的接口。
按照Linux內核中的實現(xiàn),控制組的設計如圖1所示,包含以下三個重要的概念:
(1)Cgroup,即控制組Control group的簡稱,它是具體控制進程行為的分組。Linux內核控制組機制中與進程分組相關的資源控制均以其為單位實現(xiàn)。
(2)Hierarchy為一個具有樹狀結構的Cgroup集合,系統(tǒng)中的每一個進程都會對應到某個Hierarchy中的某個Cgroup。
(3)Subsystem為具體某一類資源控制器的子系統(tǒng),例如Memory Subsystem為分組內存資源管理的一類控制器。其作為Cgroup中可以動態(tài)添加/刪除的模塊,在Cgroup框架下提供多種行為的控制策略。Subsystem必須通過“附屬”(attach)操作關聯(lián)到具體的Hierarchy上才能產(chǎn)生作用。
這三個概念與各個任務之間的對應關系如圖2所示,包括以下幾個方面:
(1)每次在系統(tǒng)中創(chuàng)建新的Hierarchy時,該系統(tǒng)中的所有任務都是其根節(jié)點的初始成員。
Figure 1 Concepts of Cgroup,Hierarchy,Subsystem圖1 Cgroup、Hierarchy、Subsystem概念示意圖
(2)一個Subsystem只能被附屬到一個Hierarchy之上。
(3)一個Hierarchy可以附屬多個Subsystem。
(4)一個任務可以是多個Cgroup的成員,但必須屬于不同的Hierarchy。
(5)當系統(tǒng)中的任務創(chuàng)建子任務時,該子任務將自動成為其父任務所在的Cgroup成員。系統(tǒng)管理員可以根據(jù)需求將該子任務遷移到不同的Cgroup中,但在初始創(chuàng)建時它總是繼承其父進程所在的控制組。
Figure 2 Relationship of Cgroup components and task圖2 Cgroup各個概念與任務之間的關系示意圖
內存控制組允許系統(tǒng)以進程組為粒度限制管理用戶態(tài)應用程序內存的消費。相比Beancounter機制,內存控制組主要關心用戶空間頁面。對于隔離性要求不高的應用場景,內存控制組能夠提供更好的靈活性和相對較低的開銷。
對于每一個內存控制組,系統(tǒng)允許管理員設置該組進程的內存使用硬上限、軟上限、swappiness等參數(shù),并提供組內OOM(Out of Memory)等行為控制。Linux內核在原有基礎上的重新設計與實現(xiàn),以更好地完成內存控制組所帶來的新機制。下文將從內核的設計與實現(xiàn)兩個角度分別闡述新機制帶來的挑戰(zhàn)。
在設計層面,主要面臨的是如何處理共享頁面和線程組共享地址空間的問題。為了簡化邏輯,減少統(tǒng)計計數(shù)給系統(tǒng)所帶來的性能回退,內存控制組在實現(xiàn)時將多個進程組共享的頁面計數(shù)歸屬到第一個訪問該頁面的進程組中。同時,為了兼顧公平性,當持有共享頁面的進程組釋放該頁面時,該頁面的計數(shù)將遷移到其他某個持有該頁面的進程組中。由于Linux內核中線程是作為一種輕量級的進程來處理,因此實際上會存在屬于同一進程的不同線程處于不同的Cgroup分組當中。而這些線程實際上是共享了相同的地址空間,因此其中相關的所有頁面的計數(shù)在嚴格意義上應該被不同的分組所共享。但是,內核為了簡化實現(xiàn)邏輯,將內存的使用計數(shù)僅歸屬于線程組主線程所在的Cgroup分組中。
在實現(xiàn)層面的主要問題是如何高效處理任務在分組間遷移時的相關頁面統(tǒng)計計數(shù)。為了提高系統(tǒng)的性能,內核在處理相關邏輯時進行了簡化。當任務進行遷移時,內核僅將任務本身遷移到新分組當中,而之前的統(tǒng)計計數(shù)仍保留在舊分組。當原先計數(shù)所代表的內存頁面被釋放時,內核再在原分組內減去對應的計數(shù)。在遷移之后產(chǎn)生的新計數(shù),內核會自動統(tǒng)計到新的分組記錄中。
同時,為了盡量減少對內核數(shù)據(jù)結構struct page的改動并最大程度地降低開銷,內存控制組在實現(xiàn)時將原先全局LRU鏈表劃分為每進程組的LRU鏈表,各個組之間的LRU鏈表通過所在Hierarchy的樹狀結構關聯(lián)起來。因此,當內核進行全局內存回收時,將從單一遍歷全局LRU鏈表轉變?yōu)閺腃group根節(jié)點開始遍歷各組局部LRU鏈表,進行頁面交換與頁面回收。這種設計雖然帶來了一部分額外的開銷,但簡化了對原有頁面回收實現(xiàn)的修改。
為了能夠更直觀地了解內存控制組在實際應用中的性能,本文將其與Beancounter機制進行了對比測試。由于Beancounter是Open VZ的核心組成機制之一,因此需要通過Open VZ的虛擬機性能反映。為此,本文選取了LXC(Linux Container)內核級虛擬化項目作為內存控制組的參照環(huán)境。這兩個項目均基于Linux內核,采用相同名字空間機制隔離不同的VE;并且,LXC與Open VZ可以使用相同的用戶態(tài)環(huán)境(即VE的根文件系統(tǒng))。不同之處在于,LXC項目使用控制組機制進行資源限制,而Open VZ使用Beancounter機制。
對比測試的實驗平臺為Intel雙路Xeon E5620(16核)、24 GB(6×4 GB)內存,采用麒麟Linux 3.2服務器操作系統(tǒng)(內核版本2.6.32),使用Open VZ官方提供的VE根文件系統(tǒng),共16個VE,每個VE分配1.5 GB物理內存配額,測試用例為Unixbench,結果如圖3所示。
Figure 3 Performance comparison of open VZ and LXC圖3 Open VZ與LXC性能對比測試結果
從Unixbench的結果觀察,使用內存控制組的LXC平均性能要高于使用Beancounter的Open VZ,但其VE間性能波動相對較大,隔離性相比較而言不如Open VZ。當以提升系統(tǒng)整體吞吐量為主要目標時,內存控制組相對而言更加合適。
用程序混合部署與同時運行要求系統(tǒng)軟件能夠有效地進行資源管理。目前,Linux內核使用內存控制組時,主要是通過限制組內內存分配的硬上限(Limits)與軟上限(Soft Limit)來進行管理。當組內內存申請失敗時,在組內私有的LRU鏈表上觸動組內回收,如果回收失敗,將會觸發(fā)組內OOM。當應用程序充分競爭造成全局內存緊張時,系統(tǒng)首先試圖將各組使用內存量回收到軟上限,然后再由kswapd內核守護線程進行全局頁面回收。
研究表明,使用用戶態(tài)協(xié)同的內存垃圾回收機制,能進一步提升系統(tǒng)整體性能。其主要原因有兩個方面:首先,系統(tǒng)換頁的代價少則只需要進行一次IO,多則需要進行兩次,而應用程序進行垃圾回收的代價通常更?。黄浯?,軟上限應該設定的值在實際應用中沒有客觀計算標準,而應用程序對所維護的緩存頁的冷熱程度更加清楚,回收釋放時更加具有針對性,降低了抖動發(fā)生的概率。
可應用于傳統(tǒng)UNIX進程間的通信機制包括管道、套接字、信號等等。一般情況下,管道機制常被編程者作為通知機制來異步喚醒select(或等價的poll/epoll)調用。
eventfd是Linux內核中一個新的高效線程間事件通知機制,一方面它比傳統(tǒng)的管道少用一個文件描述符;另一方面,eventfd的緩沖區(qū)管理相對簡單,全部緩沖僅有8字節(jié)。利用該通知機制,編程者只需要通過eventfd系統(tǒng)調用獲得關于事件的文件描述符,然后使用經(jīng)典的IO函數(shù)監(jiān)聽從該文件描述符傳遞過來的通知事件。
實現(xiàn)應用感知的內存管理,在操作系統(tǒng)內核一級關鍵是需要具備兩方面的能力。一方面,資源聚合要求在單一節(jié)點上聚合多個應用實例,并且內核能為應用實例之間提供一定程度的資源隔離與QoS。通過內存控制組的支持,資源隔離與QoS能夠在一定程度上得到保障。另一方面,為了能夠進一步高效利用系統(tǒng)資源環(huán)境,需要操作系統(tǒng)具備將進程組內存壓力通知相關用戶態(tài)應用的能力。同時,系統(tǒng)應該提供靈活的機制供應用程序將對內存資源的具體需求反饋給操作系統(tǒng),以便系統(tǒng)能夠做出更精確的資源控制。
為了達到以上目標,本文完成了以下兩個方面的工作。首先,將eventfd的機制與Linux內核控制組相結合,通過向Cgroup虛擬文件系統(tǒng)中指定的控制文件進行配置將兩種機制關聯(lián)起來,實現(xiàn)針對各個控制組的事件通知機制的框架。然后,在前者的基礎上,為每個內存控制組增加內存使用閾值數(shù)組。分組內的應用根據(jù)自身的特點將預期的閾值通過Cgroup文件系統(tǒng)寫到該數(shù)組中。當進程組所消耗的內存數(shù)量超過閾值時,內核將通過eventfd機制通知相關應用進行用戶態(tài)的內存垃圾回收。詳細設計的示意圖如圖4所示。
Figure 4 Processes group notification mechanism圖4 進程組通知機制示意圖
通過Cgroup虛擬文件系統(tǒng)進行關聯(lián),避免了增加新的系統(tǒng)調用所帶來的復雜度。應用程序利用傳統(tǒng)的編程接口申請創(chuàng)建并獲得eventfd,并將該eventfd描述符、對應的Cgroup控制文件(即cgroup_subsys_state在Cgroup虛擬文件系統(tǒng)中關聯(lián)的文件描述符)以及語義相關的參數(shù)同時寫入指定的Cgroup控制文件中。內核處理該文件的寫入操作時,啟動其對應的Cgroup中相關事件監(jiān)聽與處理邏輯,完成Cgroup與eventfd的關聯(lián)。
內存控制組在分組進行charge/uncharge、組內頁面進行遷移時進行閾值檢測,如果超過閾值則通過先前注冊的eventfd向應用程序發(fā)送通知。應用程序在接到通知后即可進行相應的處理邏輯。在一個內存控制組中,本文設置了多個閾值的槽位。應用程序可以根據(jù)需要在同一個控制組中對多個閾值進行監(jiān)聽。為了能夠進一步加快處理速度,在向控制組注冊通知的時候,內核對存儲閾值的數(shù)組進行重新排序,并設置當前閾值指針為不大于當前內存使用量的最大槽位。
這種設計盡可能地利用了Linux的已有成熟機制,降低了引進新機制后對系統(tǒng)穩(wěn)定性帶來的風險,實現(xiàn)了一種簡單可靠的內存組臨界通知機制。
本文的主要工作基于麒麟Linux 3.2服務器操作系統(tǒng)穩(wěn)定版的2.6.32內核,主要目標是對新機制所帶來的潛在性能回退進行評估。評估的實驗平臺為開啟Virtio機制的KVM虛擬化客戶端操作系統(tǒng),虛擬機配置為六個CPU核心,2 GB物理內存。實驗結果如圖5和圖6所示。
Figure 5 Comparison of latency圖5 延遲對比
Figure 6 Memory access bandwidth comparison of mmap圖6 mmap訪存帶寬對比
實驗結果表明,以Cgroup與eventfd為基礎的進程組內存臨界通知機制是資源聚合環(huán)境下一種簡單實用的內存管理方法,且新機制的引入未對現(xiàn)有的穩(wěn)定版內核帶來明顯的性能回退。
在大規(guī)模云計算的環(huán)境下,如何提高系統(tǒng)資源利用率是學術界與工業(yè)界一直關注的重點。本文在前人的研究基礎上,設計了一種可以由應用程序主動向內核注冊觸發(fā)內存回收條件的機制,兼顧了應用對自身內存資源了解與系統(tǒng)對全局內存資源規(guī)劃兩方面的優(yōu)勢。通過該機制,系統(tǒng)管理員能很容易地完成進程組范圍內存資源限制,并可以通過eventfd事件通知相關應用在用戶態(tài)進行垃圾回收。
下一步的工作,將在這個機制的基礎上實現(xiàn)用戶態(tài)應用自主事件的注冊,以及根據(jù)內核通知進行自主垃圾回收。
[1] Waldspurger C A.Memory resource management in VMware ESX server[C]∥Proc of the 5th Symposium on Operating Systems Design and Implementation,2002:181-194.
[2] Schwidefsky M,F(xiàn)ranke H,Mansell R,et al.Collaborative memory management in hosted Linux environments[C]∥Proce of Ottawa Linux Symposium,2007:313-328.
[3] Iyer S,Navarro J,Druschel P.Application-assisted physical memory management for general-purpose operating systems[R].Huston,TX 77005,USA:Rice University,2004.
[4] Yang T,Berger E D,Kaplan S F,et al.CRAMM:Virtual memory support for garbage-collected applications[C]∥Proc of the 7th USENIX Symposium on Operating Systems Design and Implementation,2006:103-116.
[5] Hines M R,Gordon A,Silva M,et al.Application know best:Performance-driven memory overcommit with ginkgo[C]∥Proc of the 3rd International Conference on Cloud Computing Technology and Science,2011:1.
[6] Emelianov P,Lunev D,Korotaev K.Resource management:Beancounters[C]∥Proc of Ottawa Linux Symposium,2007:285-292.
[7] Menage P B.Adding generic process containers to the Linux kernel[C]∥Proc of Ottawa Linux Symposium,2007:46-57.