張博
(每銳軟件(上海)有限公司(Marin Software)上海市 200011)
信息化社會(huì)中的信息爆炸引發(fā)了數(shù)據(jù)量的大幅增長(zhǎng)。傳統(tǒng)數(shù)據(jù)處理器已經(jīng)很難快速高效地在經(jīng)濟(jì)實(shí)用的條件下完成數(shù)據(jù)實(shí)時(shí)運(yùn)算。服務(wù)器聯(lián)同協(xié)作成為大規(guī)模數(shù)據(jù)處理的發(fā)展方向。在此背景之下,大數(shù)據(jù)運(yùn)算平臺(tái)應(yīng)運(yùn)而生,其中以Apache 基金會(huì)旗下的Hadoop 項(xiàng)目最為知名。得益于其開源特性,Hadoop 被許多大學(xué)、研究所與商業(yè)公司廣泛采用,在大數(shù)據(jù)領(lǐng)域已經(jīng)成為廣為接受的基準(zhǔn)平臺(tái)。與此同時(shí),為了方便使用者更簡(jiǎn)便快捷的在Hadoop 平臺(tái)上實(shí)現(xiàn)分布式運(yùn)算,許多分布式運(yùn)算框架被研發(fā)與發(fā)行,其中Spark 以其突出的基于內(nèi)存存取的高性能運(yùn)算,自推出之時(shí),便成為了學(xué)術(shù)界與工業(yè)界重要的關(guān)注與應(yīng)用對(duì)象。
然而,大規(guī)模數(shù)據(jù)集所帶來(lái)的問(wèn)題并不止于數(shù)據(jù)量的大幅增長(zhǎng),數(shù)據(jù)結(jié)構(gòu)的復(fù)雜性與差異性導(dǎo)致各個(gè)數(shù)據(jù)之間運(yùn)算量差異亦十分明顯。直接的結(jié)果就是導(dǎo)致了Spark 工作集的多樣化。不同種類的Spark 工作,其生存周期與資源消耗各不相同。當(dāng)大量多種類Spark工作同時(shí)出現(xiàn)在同一個(gè)Hadoop 平臺(tái)上時(shí),運(yùn)算資源的不當(dāng)分配極易導(dǎo)致大量微型工作被阻塞,等待資源,直至超時(shí)。當(dāng)數(shù)據(jù)量極大,例如運(yùn)算峰值階段的平臺(tái)資源緊張時(shí)期,各個(gè)Spark 工作會(huì)因?yàn)橘Y源爭(zhēng)搶,導(dǎo)致相互阻塞,數(shù)據(jù)運(yùn)算因?yàn)楦鱾€(gè)Spark 工作均無(wú)法取得足夠資源而停頓,致使整個(gè)Hadoop 平臺(tái)產(chǎn)生系統(tǒng)死鎖,工作流停頓。
問(wèn)題產(chǎn)生的根源是Spark 工作多樣性與單一的資源分配規(guī)則之間的矛盾。故而,在Hadoop 平臺(tái)搭配Spark 框架支持大規(guī)模數(shù)據(jù)運(yùn)算的實(shí)踐中,Spark 工作集應(yīng)該被系統(tǒng)化分類,采用不同的分配原則,避免數(shù)據(jù)流高峰時(shí)刻因資源爭(zhēng)搶而導(dǎo)致的相互阻塞。此外,Hadoop 平臺(tái)資源高利用率階段出現(xiàn)性能下降是正常的反應(yīng),與工作流完全阻塞相比,兩者在短時(shí)間內(nèi)會(huì)呈現(xiàn)相同現(xiàn)象,而長(zhǎng)時(shí)間的人工觀測(cè)在此情境下并不經(jīng)濟(jì)可取。因此,固定的監(jiān)控規(guī)則需要進(jìn)行動(dòng)態(tài)化改良,使其可以根據(jù)平臺(tái)負(fù)載量與工作流阻塞的特定現(xiàn)象自動(dòng)調(diào)整監(jiān)控閾值,從而大幅降低監(jiān)控系統(tǒng)的誤報(bào)率,盡力削減非必要的運(yùn)維成本。在大數(shù)據(jù)平臺(tái)運(yùn)算資源的合理分配與動(dòng)態(tài)監(jiān)控系統(tǒng)的配合之下,大數(shù)據(jù)平臺(tái)可以更加穩(wěn)定、健壯、高效的承受大規(guī)模多樣化Spark 工作流帶來(lái)的系統(tǒng)壓力。
本文后續(xù)篇章將主要分為幾個(gè)部分:Hadoop 平臺(tái)與Spark 框架的架構(gòu)介紹,工作流阻塞問(wèn)題的生成機(jī)理,資源分配規(guī)則與動(dòng)態(tài)監(jiān)控,與最終的經(jīng)驗(yàn)總結(jié)。
本章節(jié)將由兩個(gè)部分組成:
(1)Hadoop2.0/YARN 平臺(tái)與相關(guān)系統(tǒng)的架構(gòu)介紹;
(2)Spark 框架與各Spark 工作集種類的介紹。
圖1:Hadoop 2.0 架構(gòu)
作為被廣泛應(yīng)用的大數(shù)據(jù)平臺(tái)與分布式框架,Hadoop 與Spark其本身內(nèi)部的架構(gòu)缺陷并不會(huì)對(duì)使用者造成嚴(yán)重影響。然而當(dāng)多套系統(tǒng)與框架需要協(xié)同工作、合并運(yùn)行時(shí),兩者結(jié)構(gòu)上的不同便會(huì)在極端條件下產(chǎn)生嚴(yán)重的負(fù)面影響。對(duì)于Hadoop 平臺(tái)與Spark 工作流內(nèi)部架構(gòu)與種類的理解將會(huì)成為重要的知識(shí)背景,在其幫助下,讀者會(huì)更加容易和有條理地理解這種協(xié)作系統(tǒng)下問(wèn)題的產(chǎn)生根源。
自2013年推出Hadoop2.0 以來(lái),Hadoop 平臺(tái)已經(jīng)擺脫了MapReduce 框架的束縛,從單一的HDFS+MapReduce 模式,變得更為開放與多元化。其中最大的改變,就是將工作調(diào)度元件從MapReduce 框架中分離出來(lái),成為了獨(dú)立的Hadoop 構(gòu)件,被命名為YARN?;A(chǔ)的Hadoop 架構(gòu)從此變成了三級(jí)結(jié)構(gòu)(如圖1 所示)。本段落將著重介紹工作調(diào)度與資源監(jiān)控構(gòu)件YARN 的內(nèi)部結(jié)構(gòu)與單/多租戶條件下的資源使用規(guī)則。
2.1.1 YARN 的系統(tǒng)結(jié)構(gòu)
作為Hadoop2.0 的核心構(gòu)件之一,YARN 的主要目的是實(shí)現(xiàn)跨服務(wù)器平臺(tái)的整體資源監(jiān)控與分布其上的工作調(diào)度,其監(jiān)控管理的主要資源類型是內(nèi)存。YARN 采取了經(jīng)典的主從式(Master-Slave)分布式結(jié)構(gòu)。這種結(jié)構(gòu)實(shí)現(xiàn)方法簡(jiǎn)單明了,架構(gòu)清晰,算法簡(jiǎn)明扼要。缺點(diǎn)亦十分明顯,主控節(jié)點(diǎn)的單點(diǎn)故障容易導(dǎo)致整個(gè)平臺(tái)癱瘓。然而,隨著多個(gè)版本的更新,Hadoop2.0 平臺(tái)已經(jīng)可以通過(guò)待機(jī)節(jié)點(diǎn)切換的高可用模式來(lái)規(guī)避單點(diǎn)故障,從而被業(yè)界所接受并將其放心地用于生產(chǎn)環(huán)境。
(1)從系統(tǒng)層級(jí)來(lái)看, 它由一個(gè)平臺(tái)級(jí)監(jiān)控中心ResourceManager(RM)和各個(gè)服務(wù)器各自獨(dú)有的托管代理模塊NodeManager(NM)構(gòu)成。通過(guò)這樣的架構(gòu),YARN 可以全面掌控整個(gè)平臺(tái)內(nèi)各個(gè)服務(wù)器的健康與資源消耗情況,并為工作調(diào)度提供了充足的信息支持。YARN 將整個(gè)平臺(tái)的資源視為一個(gè)整體,再根據(jù)客戶請(qǐng)求與配置,將資源切割為一個(gè)個(gè)獨(dú)立的資源塊分配給其進(jìn)行數(shù)據(jù)處理。
(2)從客戶請(qǐng)求工作層級(jí)來(lái)看,每一個(gè)工作請(qǐng)求,都實(shí)際上由一組資源塊構(gòu)成。每個(gè)資源塊各包含(有且只有)一個(gè)模塊。在眾多模塊中,有一個(gè)為主控模塊(ApplicationMaster:AM),其余都是受其監(jiān)控管理的工作模塊(YarnChild:YC)。在客戶請(qǐng)求工作期間,這些資源塊統(tǒng)一由AM 監(jiān)控管理,不再受系統(tǒng)約束,直至請(qǐng)求完成,將它們歸還系統(tǒng)。
圖2:YARN 雙層分布式系統(tǒng)與客戶請(qǐng)求的生命周期
圖3:Oozie 工作層級(jí)與YARN 的邏輯關(guān)系
綜上所述,YARN 的內(nèi)部結(jié)構(gòu)其實(shí)是一個(gè)雙層主從式分布式系統(tǒng),其包含了系統(tǒng)級(jí)(RM+NM)與依賴其上的客戶請(qǐng)求工作級(jí)(AM+YC)兩部分,如圖2 所示。本文主旨所要討論的問(wèn)題便與客戶請(qǐng)求工作層級(jí)密切相關(guān)。
2.1.2 YARN 中單/多租戶條件下的資源使用規(guī)則
YARN 中的資源使用規(guī)則主要由客戶請(qǐng)求中各資源塊的生命周期,既客戶請(qǐng)求的工作流程,所決定。其工作流程可以分為8 個(gè)階段(圖2,序號(hào)標(biāo)示):
(1)客戶向RM 提交請(qǐng)求;
(2)RM 尋找空閑的NM;
(3)NM 在RM 的要求下,為客戶請(qǐng)求創(chuàng)建AM;
(4)基于對(duì)客戶請(qǐng)求的分析,AM 聯(lián)系RM,以取得用于數(shù)據(jù)處理的運(yùn)算資源;
(5)依照AM 提出的要求,RM 尋找合適的NM;
(6)NM 根據(jù)RM 的要求,創(chuàng)建多個(gè)YC 以滿足AM 的需求;
(7)YC 完成數(shù)據(jù)處理,并將各自的結(jié)果返回給AM;
(8)AM 對(duì)收集到的分散結(jié)果進(jìn)行總結(jié)合并,然后將最終結(jié)果返回客戶。
由此工作流程,YARN 中的資源使用規(guī)則可以被總結(jié)為以下幾點(diǎn):
(1)被單租客客戶請(qǐng)求消耗的資源Rrequest,可分為RAM和RYC,其關(guān)系如公式1 所示(n 表示YC 的數(shù)量)。
(2)在多租戶多請(qǐng)求并行狀態(tài)下,YARN 集群的資源RYARN分配如公式2 所示,其中Ridle表示空閑資源,m 表示客戶請(qǐng)求的數(shù)量,n 表示YC 工作模塊的數(shù)量。
(3)每一個(gè)客戶請(qǐng)求,有且只有一個(gè)AM,而且其生命周期貫穿整個(gè)運(yùn)算過(guò)程。
(4)YC才是數(shù)據(jù)處理的主要模塊,其數(shù)量n由AM的需求決定,生命周期亦不固定,只取決于各自的數(shù)據(jù)處理工作是否完成。
2.1.3 Oozie 的介紹與應(yīng)用
Oozie 是Hadoop 2.0 大數(shù)據(jù)平臺(tái)生態(tài)環(huán)境中的一個(gè)附屬構(gòu)件,同屬Apache 基金會(huì)旗下。其主旨是幫助使用者實(shí)現(xiàn)大規(guī)模Hadoop工作流的順序調(diào)度。通過(guò)應(yīng)用有向無(wú)環(huán)圖(DAG)算法,Oozie可以實(shí)現(xiàn)Hadoop 工作流中復(fù)雜邏輯關(guān)系的編排。在Oozie 中,工作流分為三個(gè)層級(jí):Bundle 工作級(jí),Coordinator 工作級(jí),和Workflow 工作級(jí)(如圖3 所示)。其中,只有workflow 工作級(jí)和YARN 有交互關(guān)系,Bundle 和Coordinator 兩個(gè)級(jí)別都只是一個(gè)邏輯層級(jí)存在于Oozie 中,既Bundle 工作和Coordinator 工作最終都會(huì)落實(shí)到子Workflow 工作中,并由其最后在YARN 中實(shí)現(xiàn)。
在使用Oozie 編排Spark 工作流時(shí),Workflow 工作會(huì)先在YARN 中啟動(dòng)一個(gè)MapReduce 工作,其被命名為Oozie_launcher。Oozie_launcher 是相關(guān)Spark 工作在YARN 中的母進(jìn)程,它將依據(jù)Oozie 中的設(shè)定與配置實(shí)時(shí)監(jiān)控Spark 工作的進(jìn)度并保證其始終遵循Oozie 的邏輯順序運(yùn)行;在Spark 工作因意外中止時(shí),亦由Oozie_launcher 負(fù)責(zé)其錯(cuò)誤信息的收集與工作的重啟。
得益于Oozie 的協(xié)作,使用者可以批量管理并行工作,并實(shí)現(xiàn)工作流間復(fù)雜的邏輯運(yùn)行關(guān)系。然而,這種架構(gòu)的劣勢(shì)也很明顯。除了Spark 工作流外,Oozie 會(huì)為每個(gè)Spark 工作都另外創(chuàng)建一個(gè)MapReduce 工作,這就使工作流在數(shù)量上翻升了一倍,其資源使用分布如公式3 與公式4 所示。在處理大型數(shù)據(jù)集的工作流中,既∑0mRspark遠(yuǎn)遠(yuǎn)大于∑0mRoozie_launcher時(shí),這樣的負(fù)面影響并不明顯;但在中小微型數(shù)據(jù)集工作流中時(shí)),非工作模塊的資源占比r(公式(5)所示)會(huì)大幅上升,當(dāng)Hadoop 平臺(tái)遇到足夠大規(guī)模的工作流負(fù)載時(shí),平臺(tái)的運(yùn)算與資源壓力將會(huì)變得更加巨大,為系統(tǒng)死鎖埋下隱患。
由圖1 可知,Hadoop2.0 不僅支持 MapReduce,Spark 也成為可用框架之一。在對(duì)于運(yùn)算性能有要求的情境下,Spark 成為了更受歡迎的選項(xiàng)而被廣泛應(yīng)用在測(cè)試與生產(chǎn)環(huán)境中。Spark 框架在結(jié)構(gòu)上完全遵守YARN 的客戶請(qǐng)求工作層級(jí)架構(gòu),采用主從分布式結(jié)構(gòu)。一個(gè)運(yùn)行的Spark 工作由一個(gè)主控模塊SparkAM和一組受其監(jiān)控的工作模塊SparkYC組成,其資源消耗亦符合公式1 所示。
Spark 工作的原生種類大體可分為兩種:流式數(shù)據(jù)作業(yè)模式與存儲(chǔ)式數(shù)據(jù)作業(yè)模式
(1)流式數(shù)據(jù)作業(yè)模式:此種模式下的Spark 工作是一種長(zhǎng)期運(yùn)行的微服務(wù)類工作,它們長(zhǎng)期運(yùn)行于Hadoop 集群上,實(shí)時(shí)于內(nèi)存中處理網(wǎng)絡(luò)上傳輸來(lái)的流式數(shù)據(jù),并將最終結(jié)果存于HDFS 以備后用或?qū)崟r(shí)反饋給客戶。
(2)存儲(chǔ)式數(shù)據(jù)作業(yè)模式:此類Spark 工作的處理對(duì)象并非網(wǎng)絡(luò)實(shí)時(shí)傳輸?shù)牧魇綌?shù)據(jù),而是HDFS 中的預(yù)存數(shù)據(jù)。這類工作的工作原理與MapReduce 類似,但得益于純內(nèi)存間數(shù)據(jù)運(yùn)算與傳輸,相較于MapReduce 工作中Map 與Reduce 任務(wù)之間shuffle 階段的落磁盤操作,其性能更為強(qiáng)大。其早期版本與Hadoop1.0 系統(tǒng)的性能對(duì)比中,就有近100 倍[1]的性能優(yōu)勢(shì)。
Spark 框架的兩種工作模式搭配上Oozie 的編排服務(wù),便可以衍生出了多種工作種類。在互聯(lián)網(wǎng)企業(yè)中,使用較多的工作種類主要包含以下四種:
(1)流式數(shù)據(jù)工作:此類工作主要便是針對(duì)網(wǎng)絡(luò)中傳輸?shù)牧魇綌?shù)據(jù),是典型的資源密集型工作種類。其特點(diǎn)為,長(zhǎng)時(shí)間運(yùn)行,資源消耗量大且穩(wěn)定,不會(huì)輕易釋放占有的運(yùn)算資源。
(2)微型存儲(chǔ)式數(shù)據(jù)工作:微型存儲(chǔ)式數(shù)據(jù)工作大多是基于事件而誘發(fā)的微小型工作。單個(gè)工作資源用量小,運(yùn)行時(shí)間短,相較于大數(shù)據(jù)平臺(tái),幾乎可以忽略不計(jì)。但此類工作往往成群出現(xiàn),且數(shù)量極大,非常容易在Hadoop 平臺(tái)中造成短時(shí)間內(nèi)負(fù)載高峰。然而,在平臺(tái)負(fù)載出現(xiàn)擁堵時(shí),此類工作群的出現(xiàn),會(huì)大幅加劇資源的爭(zhēng)搶力度。平臺(tái)擁堵大都由工作量的提升而引起,此時(shí)工作群的數(shù)量也大概率會(huì)出現(xiàn)提升,資源使用總量相較平時(shí)也會(huì)增加,可用資源在現(xiàn)有運(yùn)行工作間的爭(zhēng)搶力度,既平臺(tái)擁堵程度,會(huì)出現(xiàn)驟增。同時(shí),由于各個(gè)工作均無(wú)法獲得足夠的運(yùn)算資源,導(dǎo)致運(yùn)行時(shí)間加長(zhǎng),使得平臺(tái)的擁堵時(shí)段亦被延長(zhǎng)。此外,由于其巨大的工作數(shù)量,一旦出現(xiàn)此情況,平臺(tái)的等待工作數(shù)量與等待時(shí)間,都會(huì)大幅增長(zhǎng)。
(3)編排預(yù)設(shè)工作:此類工作本身也屬于存儲(chǔ)式數(shù)據(jù)工作,其資源使用量一般小于流式數(shù)據(jù)工作,但遠(yuǎn)高于微型工作。與前兩者的最大區(qū)別在于,在Oozie 的編排服務(wù)輔助下,它可以根據(jù)用戶的需求,預(yù)設(shè)工作時(shí)段。既不需要長(zhǎng)期運(yùn)行于平臺(tái)上占用資源;也并非完全基于事件,不可預(yù)控;而是將一個(gè)預(yù)設(shè)時(shí)間段內(nèi)的請(qǐng)求積累起來(lái),定時(shí)啟動(dòng)一個(gè)工作將其批次處理。而其缺點(diǎn)相較于流式數(shù)據(jù)工作也十分明顯,客戶的請(qǐng)求不會(huì)被馬上處理,結(jié)果并非實(shí)時(shí)反饋。此外,當(dāng)一個(gè)時(shí)間段內(nèi)工作量積累過(guò)多,無(wú)法按時(shí)完成時(shí),會(huì)造成工作積壓延后,延遲后續(xù)時(shí)段工作的運(yùn)行。
(4)資源池工作:此類工作與編排預(yù)設(shè)工作類似。其區(qū)別在于,編排預(yù)設(shè)工作直接處理數(shù)據(jù)或是客戶請(qǐng)求;而資源池工作會(huì)根據(jù)時(shí)段內(nèi)積累的工作量,觸發(fā)一系列子工作,并將工作切割分配給它們,所以資源池工作并非只有一個(gè)工作被定期重啟,而是一組工作群。其優(yōu)點(diǎn)十分明顯,既工作子集的規(guī)模會(huì)隨時(shí)段內(nèi)工作量的變化而變化;但其運(yùn)算結(jié)果亦并非實(shí)時(shí)數(shù)據(jù),且并行子工作群使得實(shí)現(xiàn)難度大幅上升。
本章節(jié)就Hadoop2.0 系統(tǒng)的架構(gòu)與Spark 框架中的工作種類進(jìn)行了解釋說(shuō)明。下一章節(jié)會(huì)就系統(tǒng)資源的不當(dāng)分配,在平臺(tái)資源緊張時(shí)期,大概率造成系統(tǒng)死鎖這一問(wèn)題的產(chǎn)生機(jī)理進(jìn)行分析與說(shuō)明。
本章節(jié)將會(huì)對(duì)多樣化Spark 工作集在Hadoop2.0 平臺(tái)上,于平臺(tái)高負(fù)載資源緊張時(shí),極易出現(xiàn)的兩種系統(tǒng)死鎖問(wèn)題及其產(chǎn)生機(jī)理進(jìn)行系統(tǒng)地分析說(shuō)明。這兩種系統(tǒng)死鎖分別為:
(1)Oozie/YARN 死鎖;
(2)AM/YC 死鎖。
根據(jù)2.1.3 章節(jié)的介紹可知,Oozie 會(huì)為每一個(gè)運(yùn)行于Hadoop2.0 平臺(tái)上的Spark 工作創(chuàng)建一個(gè)監(jiān)控程序Oozie_launcher。Oozie_launcher 作為Oozie 啟動(dòng)的監(jiān)控程序,Spark 工作其本質(zhì)是由Oozie_launcher 啟動(dòng)的子工作。這其中有幾個(gè)特征非常重要:
(1)Oozie_launcher 必定先于Spark 工作被啟動(dòng);
(2)Oozie_launcher 啟動(dòng)后,才會(huì)與YARN 商榷以獲取新資源,用以啟動(dòng)Spark 工作。倘若此時(shí)平臺(tái)空閑資源不足,Oozie_launcher 無(wú)法獲取足夠資源,則Spark 工作無(wú)法被啟動(dòng)。此時(shí),Oozie_launcher 會(huì)一直與YARN 保持通信,等待分配資源;
(3)Oozie_launcher 會(huì)一直保持運(yùn)行狀態(tài),并在整個(gè)Spark 工作的生命周期期間對(duì)其進(jìn)行持續(xù)的監(jiān)控。其只有確保Spark 工作結(jié)束后,才會(huì)結(jié)束,并釋放被自己占用的資源。
由公式(3)已知,在Oozie 參與編排的Spark 工作流于Hadoop2.0 平臺(tái)上運(yùn)行時(shí),其系統(tǒng)總資源RYARN是由Oozie_launcher占用的總資源∑0mRoozie_launcher,Spark 工作群占用的總資源∑0mRspark,與系統(tǒng)空閑資源Ridle三個(gè)部分構(gòu)成。當(dāng)平臺(tái)遇到一個(gè)巨大的負(fù)載高峰時(shí),Oozie 會(huì)于極短時(shí)間內(nèi)啟動(dòng)大量Oozie_launcher,占用大量系統(tǒng)資源。當(dāng)Ridle小于Rspark時(shí),公式(3)可演化為公式(6)。
當(dāng)公式6 所描述的現(xiàn)象在Hadoop2.0 平臺(tái)中出現(xiàn)時(shí),根據(jù)之前介紹的特征2 可知,Oozie_launcher 會(huì)一直保持運(yùn)行狀態(tài),等待其他工作結(jié)束并釋放資源,而后平臺(tái)為其分配空閑資源以啟動(dòng)相關(guān)的Spark 工作。然而由特征3 亦可知,任何Oozie_launcher 都不會(huì)在相關(guān)Spark 工作結(jié)束前,釋放資源。于是,在此情況下,Oozie/YARN 死鎖生成:所有Oozie_launcher 都在等待其他Oozie_launcher 結(jié)束并釋放資源來(lái)啟動(dòng)自有Spark 工作,但任一Oozie_launcher 都不會(huì)在自有Spark 工作結(jié)束前釋放資源。
除了Oozie/YARN 死鎖這種情況外,還存在另外一種死鎖現(xiàn)象,既AM/YC 死鎖。顧名思義,這是發(fā)生在每個(gè)工作的AM 與YC 模塊之間因資源爭(zhēng)搶而發(fā)生的死鎖現(xiàn)象。
由公式4 可知,在多租戶條件下工作層級(jí)粒度中,平臺(tái)總資源RYARN由Oozie_launcher 的AM和YC分別消耗的總資源以及Spark 工作的AM 和YC 分別消耗的總資源外加空閑資源Ridle,五個(gè)部分構(gòu)成。其中,由公式(5)可知,Oozie_launcher 工 作與Spark 工作的AM 部分都不會(huì)涉及到真實(shí)的數(shù)據(jù)處理,而只負(fù)責(zé)相關(guān)工作系統(tǒng)級(jí)與工作內(nèi)的監(jiān)控與調(diào)度;只有Spark 工作的YC 模塊會(huì)在Hadoop2.0 平臺(tái)上并行地處理客戶的實(shí)際請(qǐng)求。
由圖2 的工作啟動(dòng)流程中可知,每個(gè)工作的AM 模塊都是第一個(gè)被啟動(dòng)的,而后由AM 來(lái)啟動(dòng)、監(jiān)控YC 模塊,分配作業(yè),并在YC 模塊結(jié)束后收集整合結(jié)果,既AM 模塊的生命周期會(huì)覆蓋整個(gè)工作流程(所有YC 模塊的生命周期)。當(dāng)平臺(tái)遇到一個(gè)巨大的負(fù)載高峰時(shí),在所有Oozie_launcher 啟動(dòng)后,部分Spark 工作的AM模塊也被創(chuàng)建出來(lái),而后,平臺(tái)的空閑資源不足以讓任何Spark 工作啟動(dòng)任一YC 模塊時(shí),AM/YC 死鎖便出現(xiàn)了。Oozie_launcher在等待Spark 工作結(jié)束,Spark 工作的AM 模塊在等待YC 模塊結(jié)束并返回結(jié)果;然而YC 模塊因空閑資源不足,只能等待Oozie_launcher 和Spark 工作的AM 模塊釋放資源,才能夠得以啟動(dòng)。此情況如公式(7)所示。
其實(shí)YARN 中提供了一系列參數(shù)(例如AMFairShare),以控制AM 模塊的資源消耗量,為YC 模塊留出足夠資源余量以避免此種死鎖現(xiàn)象。在種類單一的Hadoop 工作流中,這一機(jī)制運(yùn)行良好,幾乎完美地規(guī)避了AM/YC 死鎖現(xiàn)象。然而如2.2 章節(jié)中所展示,在Oozie 參與的Spark 工作流中,工作種類并不單一,甚至許多種類間的資源消耗與運(yùn)行模式差異極大。這就使得AMFairShare 這類簡(jiǎn)單的資源劃分規(guī)則,無(wú)法有效阻止AM/YC 死鎖以及與之類似的現(xiàn)象在復(fù)雜多樣性高負(fù)載工作流運(yùn)行期間頻繁出現(xiàn)。
假設(shè)一個(gè)Spark 工作流中包含流式數(shù)據(jù)(SparkStreaming)與微型存儲(chǔ)式數(shù)據(jù)(SparkStorage)兩種工作類型(為了簡(jiǎn)化案例,此例中的所有Oozie_launcher 工作均被剔除)。那么正常情況下,Hadoop2.0平臺(tái)的資源消耗應(yīng)當(dāng)如公式8 所示??墒峭ǔA魇綌?shù)據(jù)工作資源消耗量極大,即便在所有AM 模塊的資源消耗總量依然小于AMFairShare 設(shè)定的閾值時(shí),整個(gè)平臺(tái)的空閑資源可能已經(jīng)無(wú)法為微型存儲(chǔ)式數(shù)據(jù)工作的YC 模塊提供足夠資源,如公式(9)所示。由于流式數(shù)據(jù)工作會(huì)長(zhǎng)期運(yùn)行并占用資源,這就導(dǎo)致與其伴生的微型存儲(chǔ)式數(shù)據(jù)工作流只要數(shù)量強(qiáng)度達(dá)到一定范圍,AM/YC 死鎖現(xiàn)象便會(huì)出現(xiàn)。而Oozie_launcher 工作的加入,只會(huì)使問(wèn)題更為嚴(yán)峻。
以上所闡述的兩種死鎖問(wèn)題,都是(1)運(yùn)行中的工作/模塊等待尚未啟動(dòng)的工作/模塊返回結(jié)果才可以結(jié)束,(2)而未啟動(dòng)工作/模塊等待運(yùn)行中的工作/模塊釋放資源才可以啟動(dòng),這兩者相互沖突而造成的系統(tǒng)死鎖。其本質(zhì)上相同,都是整體平臺(tái)缺乏對(duì)資源的合理科學(xué)分配而引起的混亂資源爭(zhēng)搶行為所導(dǎo)致的結(jié)果。此類問(wèn)題在平臺(tái)空閑或非繁忙時(shí)段不會(huì)產(chǎn)生任何影響,但在平臺(tái)高負(fù)載時(shí)段,卻極有可能導(dǎo)致整個(gè)平臺(tái)系統(tǒng)死鎖,運(yùn)算服務(wù)中止。此外,因?yàn)橄到y(tǒng)死鎖的產(chǎn)生原因并非Hadoop 平臺(tái)構(gòu)件問(wèn)題導(dǎo)致,也非Spark 框架內(nèi)部缺陷引起,這就使得系統(tǒng)死鎖發(fā)生時(shí),所有系統(tǒng)部件與工作日志都顯示正常,與平臺(tái)實(shí)際工作狀態(tài)不符。
以下兩個(gè)章節(jié)將重點(diǎn)講解用以解決此問(wèn)題的按隊(duì)列分配資源原理,以及依托第三方監(jiān)控軟件Nagios 及其腳本插件所實(shí)現(xiàn)的動(dòng)態(tài)監(jiān)控。經(jīng)長(zhǎng)時(shí)間應(yīng)用得以證明,正確有效的資源管理可以大幅降低系統(tǒng)死鎖的發(fā)生概率。即便在系統(tǒng)死鎖發(fā)生初期,得益于對(duì)YARN資源隊(duì)列的動(dòng)態(tài)監(jiān)控,系統(tǒng)本身也可以正確有效地預(yù)警此類問(wèn)題。
由第三章節(jié)的論述可知,Hadoop2.0 大數(shù)據(jù)集平臺(tái)在面對(duì)多樣性大規(guī)模Spark 工作流負(fù)載時(shí),極易產(chǎn)生系統(tǒng)死鎖。而產(chǎn)生的核心本質(zhì)就是平臺(tái)運(yùn)算資源在各種Spark 工作間的不合理分配,導(dǎo)致資源爭(zhēng)搶,進(jìn)而產(chǎn)生系統(tǒng)死鎖。本文中所指出的資源不合理分配行為包含兩點(diǎn):
(1)所有種類的Spark 工作被推送入同一運(yùn)行隊(duì)列,并未按照特定規(guī)則分類管理;
(2)在可用資源劃分上也只是簡(jiǎn)單劃分為兩部分,并不能有效保證在各種情況下運(yùn)算資源對(duì)特定工作/模塊的可用性。
Spark 工作流的隊(duì)列分類規(guī)則主要按照其工作種類劃分制定,但是平臺(tái)運(yùn)算資源在各個(gè)工作流分列的分配原則卻必須依照其工作性質(zhì)與重要程度決定。
此小節(jié)將主要依據(jù)各類Spark 工作的實(shí)時(shí)性與工作量來(lái)分析其重要程度并排序。
(1)最重要的工作類型便是流式數(shù)據(jù)工作(SparkStreaming)。此類工作資源消耗量極大且長(zhǎng)久,主要因?yàn)樗鼈冃枰獙?shí)時(shí)處理網(wǎng)絡(luò)中傳輸?shù)牧魇綌?shù)據(jù),并在服務(wù)質(zhì)量限定的范圍內(nèi)盡快給出結(jié)果。此類工作大多可被視為長(zhǎng)效運(yùn)行于Hadoop 平臺(tái)上的微服務(wù),為內(nèi)部其他構(gòu)件甚至外部客戶提供穩(wěn)定高效的運(yùn)算服務(wù)。在此情況下,YARN 需要優(yōu)先滿足此類工作的資源需求。
(2)編排預(yù)設(shè)工作(SparkOrchestration)與資源池工作(SparkThread-pool)的重要程度僅次于流式數(shù)據(jù)工作。這兩類工作的本質(zhì),都是將預(yù)設(shè)時(shí)間段內(nèi)的工作量積累起來(lái),于事先設(shè)定好的時(shí)間節(jié)點(diǎn)啟動(dòng)一個(gè)大型或一組微型工作進(jìn)行集體處理,所以實(shí)時(shí)性遜于流式數(shù)據(jù)工作,甚至弱于微型存儲(chǔ)式數(shù)據(jù)工作。然而,由于此二類工作的負(fù)載積累模式,每次工作啟動(dòng)時(shí)平臺(tái)都已經(jīng)堆積了數(shù)量相當(dāng)可觀的待處理請(qǐng)求或數(shù)據(jù)。而且鑒于盡量降低平臺(tái)資源爭(zhēng)搶,提高資源利用率的考量,預(yù)設(shè)時(shí)段的設(shè)定往往會(huì)在安全閾值范圍內(nèi)盡可能貼近服務(wù)質(zhì)量下限。這些特性就導(dǎo)致此類工作啟動(dòng)時(shí),YARN 必須盡快安排其開始運(yùn)行,并在不影響高優(yōu)先級(jí)工作服務(wù)質(zhì)量的前提下,盡量滿足其資源需求。
(3)微型存儲(chǔ)式數(shù)據(jù)工作(SparkStorage),此類工作本質(zhì)上也是實(shí)時(shí)運(yùn)算。然而,由于其資源需求量通常極小且運(yùn)行時(shí)間往往很短,在數(shù)量龐大的情況下也可以實(shí)現(xiàn)快速迭代。除極端情況下,純粹此類工作組成的高負(fù)載峰值并不會(huì)發(fā)生擁堵。故將此類工作置于獨(dú)立工作隊(duì)列內(nèi)并保證其擁有少量的固定資源以使用,其造成系統(tǒng)死鎖的概率幾乎為零。因此,與其他種類的Spark 工作相比,此類工作的重要性最低。
綜上所述,四大類Spark 工作的重要性I 排序如下所示:
大規(guī)模多種類混合Spark 工作流在單一資源隊(duì)列中很容易于高負(fù)載資源緊張時(shí)期遭遇系統(tǒng)死鎖威脅。因此,此類復(fù)雜工作流在Hadoop2.0 平臺(tái)上運(yùn)行時(shí),需要被拆開剝離,不同種類的工作分流至適當(dāng)隊(duì)列中去以避免潛在威脅。同時(shí),在Hadoop2.0/YARN 中,提出了資源彈性[2]的概念。一個(gè)隊(duì)列的資源被分為穩(wěn)定資源(Steady Fair Share)與瞬時(shí)資源(Instantaneous Fair Share)兩類。這兩類資源并無(wú)實(shí)際聯(lián)系。其中穩(wěn)定資源是一個(gè)隊(duì)列獨(dú)有且不容侵占的,是經(jīng)由YARN 配置的固定值。瞬時(shí)資源則會(huì)根據(jù)整個(gè)平臺(tái)的資源總量與隊(duì)列的數(shù)量和權(quán)重而實(shí)時(shí)產(chǎn)生相應(yīng)變化,隊(duì)列數(shù)量越多,權(quán)重越大,所得瞬時(shí)資源便會(huì)越多,但是瞬時(shí)資源在特定條件下可以被其他隊(duì)列占用,既當(dāng)某隊(duì)列資源使用率接近滿負(fù)荷時(shí),如果其他隊(duì)列的瞬時(shí)資源多余穩(wěn)定資源且相對(duì)空閑,那么此隊(duì)列可以超負(fù)荷占用其他隊(duì)列的瞬時(shí)資源。然而,當(dāng)穩(wěn)定資源大于瞬時(shí)資源時(shí),此隊(duì)列的資源彈性消失,既任何情況下,此隊(duì)列的資源不可被其他隊(duì)列占用。
根據(jù)上一章節(jié)的分析,Spark 工作依據(jù)種類劃分的重要程度有三個(gè)等級(jí),故而隊(duì)列規(guī)則的制定與其相對(duì)應(yīng),亦有三個(gè)種類:
4.2.1 擁有足量資源的專有隊(duì)列
此類隊(duì)列專供流式數(shù)據(jù)工作使用,并根據(jù)用戶的配置為其預(yù)留足夠的運(yùn)算資源。當(dāng)YARN 發(fā)現(xiàn)流式數(shù)據(jù)工作被提交后,此類工作的所有組件都會(huì)被調(diào)度在此隊(duì)列之內(nèi)。此隊(duì)列所擁有的穩(wěn)定資源總量應(yīng)與所有流式數(shù)據(jù)工作的資源需求總量相當(dāng)。這種隊(duì)列設(shè)置有兩點(diǎn)優(yōu)勢(shì):
(1)在任何情況下,都能優(yōu)先保證流式數(shù)據(jù)工作的資源需求以滿足其服務(wù)質(zhì)量的要求;
(2)這種資源強(qiáng)制劃分會(huì)使此類隊(duì)列的穩(wěn)定資源大于瞬時(shí)資源,有效降低了其他隊(duì)列在資源規(guī)劃調(diào)控階段對(duì)于此隊(duì)列彈性資源的依賴。
4.2.2 專有隊(duì)列
此類隊(duì)列主要應(yīng)對(duì)編排預(yù)設(shè)工作和資源池工作。專有隊(duì)列的優(yōu)勢(shì)在于,獨(dú)立的隊(duì)列就會(huì)有獨(dú)立的穩(wěn)定資源被預(yù)留下來(lái)。當(dāng)工作被觸發(fā)時(shí),這些穩(wěn)定資源可以確保Oozie_launcher 與Spark 工作的正常啟動(dòng)。在平臺(tái)資源空閑時(shí),此類隊(duì)列中的工作可以通過(guò)Hadoop2.0 的資源彈性機(jī)制通過(guò)獲取其他同類隊(duì)列的瞬時(shí)資源以滿足自身需求;而當(dāng)平臺(tái)出現(xiàn)高負(fù)載資源緊張狀況時(shí),此類隊(duì)列中工作的啟動(dòng)行為亦不會(huì)受到負(fù)面影響,同時(shí)盡可能維持工作的運(yùn)行而不會(huì)出現(xiàn)長(zhǎng)時(shí)間吊起等待的阻塞現(xiàn)象。
4.2.3 共享隊(duì)列
此類隊(duì)列專供微型存儲(chǔ)式數(shù)據(jù)工作。根據(jù)微型存儲(chǔ)式數(shù)據(jù)工作的特點(diǎn),此類隊(duì)列會(huì)包含兩個(gè)子隊(duì)列,分別為Oozie_launcher 專有隊(duì)列與Spark 專用隊(duì)列。顧名思義,在此類工作流到來(lái)時(shí),其Oozie_launcher 工作與附屬的Spark 工作會(huì)運(yùn)行在各自的專有隊(duì)列中,從而有效防止了這兩類工作之間的資源爭(zhēng)搶。與此同時(shí),對(duì)于每種工作單獨(dú)而言,又被轉(zhuǎn)化為了單種類單隊(duì)列問(wèn)題,Hadoop 系統(tǒng)默認(rèn)的資源分割機(jī)制可以完美避免AM/YC 死鎖問(wèn)題。
通過(guò)如上的隊(duì)列資源管理規(guī)則,當(dāng)Oozie 參與編排的復(fù)雜大規(guī)模Spark 工作流運(yùn)行于Hadoop2.0 平臺(tái)上時(shí),系統(tǒng)潛在的死鎖問(wèn)題被專有隊(duì)列與種類篩選分離機(jī)制轉(zhuǎn)化為一組簡(jiǎn)單的單種類單隊(duì)列問(wèn)題,從而得以被Hadoop 系統(tǒng)的原生安全機(jī)制覆蓋。
作為一個(gè)開發(fā)社區(qū)極為活躍的開源監(jiān)控軟件,Nagios 為監(jiān)控腳本提供了充足的定制化空間。相對(duì)于其他固定規(guī)則的監(jiān)控軟件(例如Cloudera[3]),擁有動(dòng)態(tài)閾值的自定義監(jiān)控腳本在Nagios 上更容易實(shí)現(xiàn)。因?yàn)镠adoop 平臺(tái)的資源被劃分為不同的子隊(duì)列,且工作流亦被分配至相應(yīng)隊(duì)列,這個(gè)動(dòng)態(tài)監(jiān)控腳本將基于子隊(duì)列監(jiān)控,而非整個(gè)Hadoop 平臺(tái)的總隊(duì)列。
動(dòng)態(tài)監(jiān)控腳本包含兩個(gè)部分:
監(jiān)控系統(tǒng)死鎖需要拉取大量平臺(tái)數(shù)據(jù),包含每個(gè)隊(duì)列中等待工作數(shù)量,此隊(duì)列支持的每個(gè)運(yùn)行工作中AM 與YC 模塊的運(yùn)行狀態(tài)與數(shù)量等。這會(huì)對(duì)Hadoop 平臺(tái)造成額外的工作負(fù)擔(dān),進(jìn)而影響平臺(tái)性能,而且頻繁的監(jiān)控?cái)?shù)據(jù)篩選累加也會(huì)對(duì)Nagios 本身提出很高的性能要求。故而應(yīng)盡量降低系統(tǒng)死鎖的檢測(cè)頻率。根據(jù)章節(jié)三的介紹可知,系統(tǒng)死鎖只會(huì)于平臺(tái)資源緊張時(shí)發(fā)生。因此,隊(duì)列阻塞預(yù)警被引入動(dòng)態(tài)監(jiān)控腳本,既當(dāng)隊(duì)列于資源緊張時(shí)期發(fā)生阻塞時(shí),Nagios 才會(huì)對(duì)當(dāng)前隊(duì)列進(jìn)行死鎖檢測(cè);否則跳過(guò)。根據(jù)當(dāng)前隊(duì)列中等待的工作數(shù)量Ncurrent,Nagios 將實(shí)時(shí)地計(jì)算出一個(gè)當(dāng)前預(yù)警閾值Tcurrent,其與基準(zhǔn)閾值Tbaseline的關(guān)系由Ncurrent與基準(zhǔn)等待數(shù)量Nbaseline決定,如公式(10)所示。當(dāng)任一等待工作的滯留時(shí)間長(zhǎng)于Tcurrent時(shí),Nagios 便會(huì)向運(yùn)維人員預(yù)警隊(duì)列阻塞。而Tcurrent的意義在于,在高負(fù)載時(shí)期,使用者可以容忍有限度的工作超時(shí)現(xiàn)象。
當(dāng)確認(rèn)隊(duì)列出現(xiàn)阻塞現(xiàn)象后,Nagios 會(huì)開始對(duì)當(dāng)前隊(duì)列進(jìn)行系統(tǒng)死鎖檢測(cè)。這里使用的預(yù)警閾值為Tbaseline,既在符合死鎖特征的條件下,只要有超時(shí)等待的工作/模塊,即示警。檢測(cè)規(guī)則步驟如下:
(1)Oozie/YARN 死鎖檢測(cè):
1.是否有Spark 工作處于等待狀態(tài);
2.若是,是否有Spark 工作處于工作狀態(tài);
3.若否,是否存在任一等待狀態(tài)的Spark 工作,其滯留時(shí)間長(zhǎng)于Tbaseline;
4.若是,隊(duì)列可能出現(xiàn)Oozie/YARN 死鎖,Nagios 發(fā)出預(yù)警。
(2)AM/YC 死鎖
1.是否每個(gè)運(yùn)行工作都只有一個(gè)模塊處于運(yùn)行狀態(tài)(只有AM運(yùn)行);
2.若是,是否存在任一等待狀態(tài)的模塊,其滯留時(shí)間長(zhǎng)于Tbaseline;
3.若是,隊(duì)列可能出現(xiàn)AM/YC 死鎖,Nagios 發(fā)出預(yù)警。
基于如上腳本,Nagios 可以持續(xù)對(duì)Hadoop 平臺(tái)每個(gè)隊(duì)列的阻塞狀態(tài)與系統(tǒng)死鎖進(jìn)行持續(xù)監(jiān)控和預(yù)警,并盡可能避免大幅增加平臺(tái)系統(tǒng)的運(yùn)算負(fù)擔(dān)。
MarinOne 是Marin Software(每銳軟件)公司推出的新一代數(shù)碼廣告平臺(tái)系統(tǒng),其基于Hadoop2.0 大數(shù)據(jù)平臺(tái)、微服務(wù)框架與虛擬化技術(shù)為客戶提供更直觀與專業(yè)的數(shù)據(jù)展示與廣告建議。在公司內(nèi)部測(cè)試平臺(tái)QA2 上經(jīng)過(guò)檢驗(yàn),證明此動(dòng)態(tài)監(jiān)控與資源分列配置不會(huì)對(duì)系統(tǒng)造成任何負(fù)面影響后,生產(chǎn)環(huán)境的Hadoop 平臺(tái)得以應(yīng)用如上更改。此Hadoop平臺(tái)的YARN部分由200臺(tái)大型服務(wù)器構(gòu)成,總共擁有37.37 TB 的內(nèi)存資源,長(zhǎng)期保持大約130 個(gè)工作同時(shí)運(yùn)行,最多時(shí)會(huì)有超過(guò)230 個(gè)工作并行運(yùn)行,其最高內(nèi)存資源利用率超過(guò)91%。
在應(yīng)用本文介紹的內(nèi)存資源隊(duì)列分配規(guī)則與動(dòng)態(tài)監(jiān)控之前,平臺(tái)一旦出現(xiàn)高負(fù)載就會(huì)發(fā)生阻塞現(xiàn)象,耗費(fèi)大量人力與時(shí)間成本后可以斷定基本是由系統(tǒng)死鎖引發(fā)。在應(yīng)用這項(xiàng)技術(shù)后,僅2020年一年間,Nagios 成功預(yù)警隊(duì)列阻塞143 次,系統(tǒng)死鎖26 次。系統(tǒng)死鎖的發(fā)生概率降低了81.8%,僅剩約18.2%。其他的系統(tǒng)阻塞大都是由于工作流過(guò)于巨大而導(dǎo)致等待時(shí)間過(guò)長(zhǎng)所觸發(fā),期間系統(tǒng)并未死鎖,但是阻塞的成功預(yù)警也使人工干預(yù)得以及時(shí)介入,從而避免了系統(tǒng)服務(wù)質(zhì)量的下降。
作為被廣為接受的大數(shù)據(jù)運(yùn)算平臺(tái),學(xué)術(shù)界與工業(yè)界已經(jīng)圍繞Hadoop2.0 系統(tǒng)進(jìn)行了非常多的相關(guān)研究與改良工作。例如AROMA[4]和FMEM[5]都主張?jiān)贖adoop 系統(tǒng)之上嵌套一層新的自動(dòng)化系統(tǒng)以實(shí)現(xiàn)平臺(tái)資源的合理配置,Gunther[6]更是將遺傳基因算法引入系統(tǒng)監(jiān)控與資源管理中。Filip K?ikava 等與本人也曾于15-16年發(fā)表文章[7-8]展示了基于內(nèi)存監(jiān)控的自適應(yīng)配置優(yōu)化工具。Gil Jae Lee 等也發(fā)表多篇文章[9-10]提出了基于CPU 運(yùn)算資源的Hadoop系統(tǒng)優(yōu)化建議。Jenn-Wei[11]也提出了新的依據(jù)工作重要性與預(yù)設(shè)截止時(shí)間等相關(guān)屬性進(jìn)行資源分配管理的調(diào)度器。但這些研究的應(yīng)用環(huán)境相對(duì)苛刻,穩(wěn)定性與可行性并未得到業(yè)界的深入驗(yàn)證,并不適合在短時(shí)間內(nèi)應(yīng)用于生產(chǎn)環(huán)境。相反,基于Hadoop 已經(jīng)提供的調(diào)配接口與成熟的監(jiān)控軟件,本文所論述的資源配置方法與動(dòng)態(tài)監(jiān)控腳本擁有可靠的穩(wěn)定性與可行性,這一點(diǎn)也在Marin 的生產(chǎn)平臺(tái)上已經(jīng)得以驗(yàn)證。
本文系統(tǒng)化地介紹了Hadoop2.0 系統(tǒng)中由于復(fù)雜大規(guī)模Spark工作流引發(fā)的系統(tǒng)死鎖與其生成機(jī)理。并據(jù)此提出了切實(shí)可行的大數(shù)據(jù)平臺(tái)資源分配規(guī)則,既依據(jù)Spark 工作種類與重要程度將平臺(tái)整體資源劃分為不同類型隊(duì)列的分配原則。再輔以基于Nagios 系統(tǒng)的動(dòng)態(tài)監(jiān)控腳本,運(yùn)維團(tuán)隊(duì)可以對(duì)平臺(tái)系統(tǒng)阻塞與死鎖進(jìn)行實(shí)時(shí)監(jiān)控及快速準(zhǔn)確的反應(yīng)排查。最終使系統(tǒng)的可靠性與基于此大數(shù)據(jù)平臺(tái)的服務(wù)質(zhì)量都得到切實(shí)保證。相較于其他已有資源管理方式與研究,本文介紹的系統(tǒng)資源分配規(guī)則與動(dòng)態(tài)監(jiān)控實(shí)現(xiàn)相對(duì)簡(jiǎn)單,對(duì)應(yīng)用環(huán)境沒(méi)有特殊要求,現(xiàn)均已應(yīng)用于Marin Software(每銳軟件)的實(shí)際生產(chǎn)環(huán)境(MarinOne)并得到了良好反饋。