Hadoop Yarn的資源隔離是指為運(yùn)行著不同任務(wù)的“Container”提供可獨(dú)立使用的計(jì)算資源,以避免它們之間相互干擾捐晶。目前支持兩種類型的資源隔離:CPU和內(nèi)存栖袋,對于這兩種類型的資源恨憎,Yarn使用了不同的資源隔離方案钞支。
對于CPU而言,它是一種“彈性”資源魁蒜,使用量大小不會直接影響到應(yīng)用程序的存亡囊扳,因此CPU的資源隔離方案采用了Linux Kernel提供的輕量級資源隔離技術(shù)Cgroup吩翻;對于內(nèi)存而言,它是一種“限制性”資源锥咸,使用量大小直接決定著應(yīng)用程序的存亡狭瞎,Cgroup會嚴(yán)格限制應(yīng)用程序的內(nèi)存使用上限,一旦使用量超過預(yù)先定義的上限值搏予,就會將該應(yīng)用程序“殺死”熊锭,因此無法使用Cgroup進(jìn)行內(nèi)存資源隔離,而是選擇了線程監(jiān)控的方式雪侥。
需要解釋一下:為什么應(yīng)用程序的內(nèi)存會超過預(yù)先定義的上限值碗殷?Java程序(Container)為什么需要內(nèi)存資源隔離速缨?
(1)為什么應(yīng)用程序的內(nèi)存會超過預(yù)先定義的上限值仿粹?
這里的應(yīng)用程序特指Yarn Container,它是Yarn NodeManager通過創(chuàng)建子進(jìn)程的方式啟動的贮预;Java創(chuàng)建子進(jìn)程時(shí)采用了“fork() + exec()”的方案滑频,子進(jìn)程啟動瞬間,它的內(nèi)存使用量與父進(jìn)程是一致的绘搞,然后子進(jìn)程的內(nèi)存會恢復(fù)正常;也就是說蒿褂,Container(子進(jìn)程)的創(chuàng)建過程中可能會出現(xiàn)內(nèi)存使用量超過預(yù)先定義的上限值的情況(取決于父進(jìn)程,也就是NodeManager的內(nèi)存使用量)近速;此時(shí),如果使用Cgroup進(jìn)行內(nèi)存資源隔離,這個(gè)Container就可能會被“kill”。
(2)Java程序(Container)為什么需要內(nèi)存資源隔離?
對于MapReduce而言挂捅,各個(gè)任務(wù)被運(yùn)行在獨(dú)立的Java虛擬機(jī)中无蜂,內(nèi)存使用量可以通過“-Xms训桶、-Xmx”進(jìn)行設(shè)置,從而達(dá)到內(nèi)存資源隔離的目的。然而箱叁,Yarn考慮到用戶應(yīng)用程序可能會創(chuàng)建子進(jìn)程的情況,如Hadoop Pipes(或者Hadoop Streaming),編寫的MapReduce應(yīng)用程序中每個(gè)任務(wù)(Map Task若河、Reduce Task)至少由Java進(jìn)程和C++進(jìn)程兩個(gè)進(jìn)程組成辈赋,這難以通過創(chuàng)建單獨(dú)的虛擬機(jī)達(dá)到資源隔離的效果悟民,因此竭业,即使是通過Java語言實(shí)現(xiàn)的Container仍需要使用內(nèi)存資源隔離做鹰。
Yarn Container支持兩種實(shí)現(xiàn):DefaultContainerExecutor和LinuxContainerExecutor炕桨;其中DefaultContainerExecutor不支持CPU的資源隔離,LinuxContainerExecutor使用Cgroup的方式支持CPU的資源隔離,兩者內(nèi)存的資源隔離都是通過“線程監(jiān)控”的方式實(shí)現(xiàn)的立叛。
基于線程監(jiān)控的內(nèi)存隔離方案
1.配置參數(shù)
(1)應(yīng)用程序配置參數(shù)
不同的應(yīng)用程序?qū)?nèi)存的需求不同顶考,可以根據(jù)具體情況定義自己的參數(shù),以MapReduce為例:
mapreduce.map.memory.mb:MapReduce Map Task需要使用的內(nèi)存量(單位:MB);
mapreduce.reduce.memory.mb:MapReduce Reduce Task需要使用的內(nèi)存量(單位:MB);
(2)Hadoop Yarn NodeManager配置參數(shù)
yarn.nodemanager.pmem-check-enabled:NodeManager是否啟用物理內(nèi)存量監(jiān)控,默認(rèn)值:true幻工;
yarn.nodemanager.vmem-check-enabled:NodeManager是否啟用虛擬內(nèi)存量監(jiān)控,默認(rèn)值:true;
yarn.nodemanager.vmem-pmem-ratio:NodeManager Node虛擬內(nèi)存與物理內(nèi)存的使用比例,默認(rèn)值2.1,表示每使用1MB物理內(nèi)存,最多可以使用2.1MB虛擬內(nèi)存;
yarn.nodemanager.resource.memory-mb:NodeManager Node最多可以使用多少物理內(nèi)存(單位:MB),默認(rèn)值:8192捞烟,即8GB;
2.實(shí)現(xiàn)原理
Yarn NodeManager Container的內(nèi)存監(jiān)控是由ContainersMonitorImpl(org.apache.hadoop.yarn.server.nodemanager.containermanager.monitor.ContainersMonitorImpl)實(shí)現(xiàn)的竞思,內(nèi)部的MonitoringThread線程每隔一段時(shí)間就會掃描所有正在運(yùn)行的Container進(jìn)程,并按照以下步驟檢查它們的內(nèi)存使用量是否超過其上限值惦界。
2.1構(gòu)造進(jìn)程樹
如前所述灾搏,Container進(jìn)程可能會創(chuàng)建子進(jìn)程(可能會創(chuàng)建多個(gè)子進(jìn)程泉哈,這些子進(jìn)程可能也會創(chuàng)建子進(jìn)程)烫沙,因此Container進(jìn)程的內(nèi)存(物理內(nèi)存您访、虛擬內(nèi)存)使用量應(yīng)該表示為:以Container進(jìn)程為根的進(jìn)程樹中所有進(jìn)程的內(nèi)存(物理內(nèi)存识虚、虛擬內(nèi)存)使用總量。
在Linux /proc目錄下浩考,有大量以整數(shù)命名的目錄怜俐,這些整數(shù)是某個(gè)正在運(yùn)行的進(jìn)程的PID,而目錄/proc/下面的那些文件分別表示著進(jìn)程運(yùn)行時(shí)的各方面信息蕾哟,這里我們只關(guān)心/proc//stat文件即可。
文件/proc//stat僅僅包含一行(多列)文本莲蜘,可以通過正則表達(dá)式從中抽取進(jìn)程的運(yùn)行時(shí)信息谭确,包括:進(jìn)程名稱、父進(jìn)程PID票渠、父進(jìn)程用戶組ID逐哈、Session ID、用戶態(tài)運(yùn)行的時(shí)間(單位:jiffies)问顷、核心態(tài)運(yùn)行的時(shí)間(單位:jiffies)昂秃、占用虛擬內(nèi)存大小(單位:page)和占用物理內(nèi)存大卸耪(單位:page)等肠骆。
ContainersMonitorImpl內(nèi)部維護(hù)著每個(gè)Container進(jìn)程的PID,通過遍歷/proc下各個(gè)進(jìn)程的stat文件內(nèi)容(父進(jìn)程PID塞耕、占用虛擬內(nèi)存大小和占用物理內(nèi)存大惺赐取)荚藻,我們可以構(gòu)建出每個(gè)Container的進(jìn)程樹亦镶,從而得出每個(gè)進(jìn)程樹的虛擬內(nèi)存、物理內(nèi)存使用總量进萄。
2.2判斷Container進(jìn)程樹的內(nèi)存使用量(物理內(nèi)存筛谚、虛擬內(nèi)存)是否超過上限值
雖然我們已經(jīng)可以獲得各個(gè)Container進(jìn)程樹的內(nèi)存(物理內(nèi)存磁玉、虛擬內(nèi)存)使用量,但是我們不能僅憑進(jìn)程樹的內(nèi)存使用量(物理內(nèi)存驾讲、虛擬內(nèi)存)是否超過上限值就決定是否“殺死”一個(gè)Container蚊伞,因?yàn)椤白舆M(jìn)程”的內(nèi)存使用量是有“波動”的席赂,為了避免“誤殺”的情況出現(xiàn),Hadoop賦予每個(gè)進(jìn)程“年齡”屬性厚柳,并規(guī)定剛啟動進(jìn)程的年齡是1氧枣,MonitoringThread線程每更新一次沐兵,各個(gè)進(jìn)程的年齡加一别垮,在此基礎(chǔ)上,選擇被“殺死”的Container的標(biāo)準(zhǔn)如下:如果一個(gè)Contaier對應(yīng)的進(jìn)程樹中所有進(jìn)程(年齡大于0)總內(nèi)存(物理內(nèi)存或虛擬內(nèi)存)使用量超過上限值的兩倍扎谎;或者所有年齡大于1的進(jìn)程總內(nèi)存(物理內(nèi)存或虛擬內(nèi)存)使用量超過上限值碳想,則認(rèn)為該Container使用內(nèi)存超量,可以被“殺死”毁靶。(注意:這里的Container泛指Container進(jìn)程樹)
綜上所述胧奔,Yarn的內(nèi)存資源隔離實(shí)際是內(nèi)存使用量監(jiān)控。
3.源碼分析
3.1MonitoringThread
線程監(jiān)控的核心工作主要是由MonitoringThread(org.apache.hadoop.yarn.server.nodemanager.containermanager.monitor.ContainersMonitorImpl.MonitoringThread)完成的预吆,內(nèi)部就是一個(gè)“while”循環(huán)龙填,以指定的時(shí)間間隔進(jìn)行監(jiān)控:
其中,時(shí)間間隔monitoringInterval由參數(shù)yarn.nodemanager.container-monitor.interval-ms指定拐叉,默認(rèn)值:3000岩遗,單位:ms。
下面介紹“while”循環(huán)的處理邏輯凤瘦。
3.2 將新啟動的Container加入監(jiān)控列表以及將已完成的Container移出監(jiān)控列表宿礁;
每次監(jiān)控開始之前都需要更新監(jiān)控列表:trackingContainers,將新啟動的Container加入監(jiān)控列表蔬芥,由containersToBeAdded表示梆靖;將已完成的Container移出監(jiān)控列表,由containersToBeRemoved表示笔诵。
containersToBeAdded和containersToBeRemoved都是通過“事件”由org.apache.hadoop.yarn.server.nodemanager.containermanager.monitor.ContainersMonitorImpl.handle負(fù)責(zé)更新的返吻,如下:
對于事件START_MONITORING_CONTAINER,它表示有新的Container進(jìn)程乎婿,為其構(gòu)建一個(gè)ProcessTreeInfo實(shí)例测僵,用于保存Container的進(jìn)程樹信息,也就是說次酌,這里考慮的不僅僅是Container進(jìn)程恨课,而是以Container進(jìn)程為父進(jìn)程的整個(gè)進(jìn)程樹,構(gòu)造函數(shù)參數(shù)含義依次如下:
containerId:Container ID岳服;
pid:Container進(jìn)程的PID剂公;
pTree:Container進(jìn)程樹內(nèi)存使用量計(jì)算器實(shí)例,不同的Hadoop運(yùn)行平臺(Windows吊宋、Linux)因?yàn)榻y(tǒng)計(jì)內(nèi)存使用量的方式不同纲辽,因此需要不同的計(jì)算器實(shí)例;通過該計(jì)算器實(shí)例,可以獲得當(dāng)前Container進(jìn)程樹的內(nèi)存使用量拖吼;
vmemLimit:Container進(jìn)程樹可使用的虛擬內(nèi)存上限值鳞上;
pmemLimit:Container進(jìn)程樹可使用的物理內(nèi)存上限值;
注意:pid吊档、pTree的初始值為Null篙议。
更新監(jiān)控列表trackingContainers之后,下一步就是對監(jiān)控列表中的Container進(jìn)程樹的內(nèi)存使用量進(jìn)行監(jiān)控怠硼。
3.3遍歷監(jiān)控列表trackingContainers鬼贱,逐個(gè)處理其中的進(jìn)程樹;
可以看出香璃,監(jiān)控列表trackingContainers中的每一個(gè)進(jìn)程樹元素是由ContainerId和ProcessTreeInfo共同表示的这难。
下面介紹單獨(dú)一個(gè)進(jìn)程樹的內(nèi)存監(jiān)控過程。
3.4初始化進(jìn)程樹信息ProcessTreeInfo葡秒;
如3.2所述姻乓,進(jìn)程樹監(jiān)控列表trackingContainers是被不斷更新的,而新加入監(jiān)控的Container進(jìn)程樹信息是由ProcessTreeInfo表示的眯牧,
其中pid蹋岩、pTree的初始值為Null,因此監(jiān)控過程中如果發(fā)現(xiàn)進(jìn)程樹信息ProcessTreeInfo的pid炸站、pTree為Null星澳,要對其進(jìn)行初始化。
(1)獲取進(jìn)程樹元素旱易,由containerId和ptInfo表示禁偎;
(2)判斷如果ptInfo(進(jìn)程樹信息)中的pId(Container進(jìn)程的PID)為null,則表示需要初始化ptInfo阀坏;
(3)獲取ProcessTreeInfo pid如暖,將其保存至pId;
Container進(jìn)程PID(pid)可以通過ContainerId(ptInfo.getContainerId())從ContainerExecutor(containerExecutor)中獲燃商谩盒至;如果獲取不到相應(yīng)的PID,可能是因?yàn)镃ontainer進(jìn)程尚沒有被啟動或者ContainerExecutor已將其移除士修,也意味著此進(jìn)程樹無需監(jiān)控枷遂。
(4)獲取ProcessTreeInfo pTree,將其保存至pt棋嘲;
這里需要介紹一下ResourceCalculatorProcessTree(org.apache.hadoop.yarn.util.ResourceCalculatorProcessTree)的作用酒唉。
每一次對ProcessTreeInfo進(jìn)行監(jiān)控時(shí),我們都必須獲取該進(jìn)程樹內(nèi)所有進(jìn)程的運(yùn)行狀態(tài)(這里我們僅關(guān)心物理沸移、虛擬內(nèi)存使用情況等)痪伦,也就是說侄榴,我們需要一個(gè)“計(jì)算器”,能夠?qū)⑦M(jìn)程樹內(nèi)所有進(jìn)程的運(yùn)行狀態(tài)計(jì)算出來网沾,ResourceCalculatorProcessTree就是用來充當(dāng)“計(jì)算器”角色的癞蚕,如下注釋所示:
ResourceCalculatorProcessTree是一個(gè)抽象類,也就意味著它可以有多種實(shí)現(xiàn)辉哥,具體選取哪一種實(shí)現(xiàn)取決于ResourceCalculatorProcessTree.getResourceCalculatorProcessTree:
其中桦山,processTreeClass由參數(shù)yarn.nodemanager.container-monitor.process-tree.class指定,默認(rèn)值為null证薇。
因?yàn)閭魅氲膮?shù)clazz值為null度苔,所以我們僅僅關(guān)注上圖紅色箭頭所指的邏輯即可。
ProcfsBasedProcessTree和WindowsBasedProcessTree分別對應(yīng)著ResourceCalculatorProcessTree在Linux平臺和Windows平臺的實(shí)現(xiàn)浑度,通常我們關(guān)注ProcfsBasedProcessTree即可,也就是說鸦概,Linux平臺下pTree的實(shí)例類型為ProcfsBasedProcessTree箩张。
(5)將pId、pt更新至ptInfo窗市,初始化過程完成先慷;
3.5根據(jù)ResourceCalculatorProcessTree(ProcfsBasedProcessTree)更新進(jìn)程樹的運(yùn)行狀態(tài)(這里僅關(guān)注物理、虛擬內(nèi)存)咨察,并獲取相關(guān)的監(jiān)控信息论熙;
(1)獲取當(dāng)前進(jìn)程樹的ResourceCalculatorProcessTree實(shí)例pTree,并更新其內(nèi)部狀態(tài)updateProcessTree()摄狱,實(shí)際就是更新進(jìn)程樹中的進(jìn)程信息(詳細(xì)處理邏輯見后)脓诡;
(2)獲取當(dāng)前進(jìn)程樹中所有進(jìn)程的虛擬內(nèi)存使用總量(currentVmemUsage)、物理內(nèi)存使用總量(currentPmemUsage)媒役;
(3)獲取當(dāng)前進(jìn)程樹中所有年齡大于1的進(jìn)程的虛擬內(nèi)存使用總量(curMemUsageOfAgedProcesses)祝谚、物理內(nèi)存使用總是(curRssMemUsageOfAgedProcesses);
(4)獲取當(dāng)前進(jìn)程樹的虛擬內(nèi)存使用總量上限值(vmemLimit)酣衷、物理內(nèi)存使用總量上限值(pmemLimit)交惯;
3.6判斷進(jìn)程樹的內(nèi)存使用量是否超過上限值,虛擬內(nèi)存與物理內(nèi)存需要分別處理穿仪;
isMemoryOverLimit的值用于表示進(jìn)程樹的內(nèi)存使用量是否超過上限值席爽,值為true表示超量(虛擬內(nèi)存或物理內(nèi)存兩者至少有其一超量);值為false表示未超量(虛擬內(nèi)存和物理內(nèi)存兩者均未超量)啊片;初始值設(shè)置為false只锻。
(1)如果開啟虛擬內(nèi)存監(jiān)控,則判斷進(jìn)程樹虛擬內(nèi)存使用總量是否超過其上限值钠龙;
(2)如果開啟物理內(nèi)存監(jiān)控炬藤,則判斷進(jìn)程樹物理內(nèi)存使用總量是否超過其上限值御铃;
虛擬、物理內(nèi)存監(jiān)控選項(xiàng)的開啟分別由參數(shù)yarn.nodemanager.vmem-check-enabled沈矿、yarn.nodemanager.pmem-check-enabled指定上真,默認(rèn)值均為true,表示兩者均開啟監(jiān)控羹膳。
判斷虛擬睡互、物理內(nèi)存使用總量是否超過上限值由isProcessTreeOverLimit()(詳細(xì)處理邏輯見后)統(tǒng)一處理,兩者僅傳入的參數(shù)值不同陵像,參考上圖代碼就珠。
3.7如果isMemoryOverLimit值為true,則表示進(jìn)程樹的內(nèi)存使用量超量(或者虛擬內(nèi)存醒颖、或者物理內(nèi)存)妻怎,執(zhí)行“kill”并從監(jiān)控列表移除;
至此泞歉,進(jìn)程樹內(nèi)存使用總量監(jiān)控處理邏輯完成逼侦。
3.8ResourceCalculatorProcessTree(ProcfsBasedProcessTree) updateProcessTree
updateProcessTree用于更新當(dāng)前Container進(jìn)程的進(jìn)程樹:
(1)獲取所有的進(jìn)程列表;
其中腰耙,procfsDir的值為/proc/榛丢,numberPattern表示的正則表達(dá)式為[1-9][0-9]*(用于匹配進(jìn)程PID)。對于Linux系統(tǒng)而言挺庞,所以運(yùn)行著的進(jìn)程都對應(yīng)著目錄“/proc/”下的一個(gè)子目錄晰赞,子目錄名稱即為進(jìn)程PID,子目錄中包含著進(jìn)程的運(yùn)行時(shí)信息选侨。所謂的進(jìn)程列表掖鱼,實(shí)際就是Linux目錄“/proc/”下的這些進(jìn)程子目錄名稱。
進(jìn)程列表processList包含的信息:1锨用、10隘谣、100、...寻歧。
(2)更新進(jìn)程樹processTree;
因?yàn)镃ontainer進(jìn)程樹中的進(jìn)程隨時(shí)都可能啟動或停止猾封,因此每次監(jiān)控開始之前都需要更新該Container進(jìn)程的進(jìn)程樹;而且為了方便處理進(jìn)程的年齡(加一)噪珊,將該Container進(jìn)程“舊”的進(jìn)程樹processTree緩存至oldProcs晌缘,然后清空processTree(詳情見后)齐莲。
(3)遍歷(1)中進(jìn)程列表,為每一個(gè)進(jìn)程構(gòu)建ProcessInfo磷箕,并將其保存至allProcessInfo选酗;
ProcessInfo的構(gòu)建過程由方法constructProcessInfo()完成,處理邏輯很簡單:
a.讀取“procfsDir//stat”(即“/proc//stat”)的文件內(nèi)容岳枷,實(shí)際內(nèi)容只有一行芒填;
b.通過正則表達(dá)式抽取其中的信息,并更新至pInfo空繁;
可以看出殿衰,ProcessInfo保存著一個(gè)進(jìn)程的以下信息:
name:進(jìn)程名稱;
ppid:父進(jìn)程PID盛泡;
pgrpId:父進(jìn)程所屬用戶組ID闷祥;
session:進(jìn)程所屬會話組ID;
utime:進(jìn)程用戶態(tài)占用時(shí)間饭于;
stime:進(jìn)程內(nèi)核態(tài)占用時(shí)間蜀踏;
vsize:進(jìn)程虛擬內(nèi)存使用量;
rss:進(jìn)程物理內(nèi)存使用量掰吕;
遍歷構(gòu)建的過程中,如果發(fā)現(xiàn)“我”進(jìn)程(即當(dāng)前的Container進(jìn)程)颅痊,則將“我”保存至進(jìn)程樹processTree殖熟,因?yàn)楫?dāng)前的Container進(jìn)程必須是此Container進(jìn)程樹中的一員;如果沒有發(fā)現(xiàn)“我”進(jìn)程斑响,則表示Container進(jìn)程(樹)已經(jīng)運(yùn)行結(jié)束菱属,無需監(jiān)控。
(4)維護(hù)進(jìn)程之間的父子關(guān)系舰罚;
allProcessInfo中保存著所有的進(jìn)程信息纽门,其中key為PID,value為對應(yīng)的ProcessInfo营罢,我們通過ProcessInfo的ppid(父進(jìn)程PID)蝙搔,即可以維護(hù)出這些進(jìn)程之間的父子關(guān)系考传。
對于每一個(gè)ProcessInfo(進(jìn)程)pInfo:
a.根據(jù)pInfo ppid找出其父進(jìn)程的ProcessInfo:parentPInfo勤晚;
b.將pInfo加入parentPInfo的子進(jìn)程列表中(ProcessInfo addChild)赐写;
(5)構(gòu)建當(dāng)前Container進(jìn)程(即(3)中的me)的進(jìn)程樹血淌;
a.將pInfoQueue初始化為me癌淮;
b.如果pInfoQueue不為空乳蓄,執(zhí)行以下操作:
b1.取出pInfoQueue的頭元素pInfo虚倒,將其加入進(jìn)程樹processTree(注意重復(fù)檢測)魂奥;
b2.將pInfo的所有子進(jìn)程加入pInfoQueue耻煤;
c.執(zhí)行b哈蝇;
上述流程執(zhí)行完畢之后炮赦,processTree中保存著當(dāng)前Container進(jìn)程的進(jìn)程樹吠勘。
(6)更新當(dāng)前Container進(jìn)程的進(jìn)程樹中所有進(jìn)程的年齡看幼;
處理邏輯很簡單:遍歷進(jìn)程樹诵姜,對于其中的每一個(gè)ProcessInfo暇赤,如果它是一個(gè)“老”進(jìn)程(即出現(xiàn)在“老”進(jìn)程樹oldInfo中)鞋囊,則將其年齡加一溜腐。(注:ProcessInfo age初始值為一)
到此挺益,進(jìn)程樹更新完畢望众。
我們以虛擬內(nèi)存為例說明進(jìn)程樹的虛擬內(nèi)存使用總量是如何計(jì)算的烂翰,如下:
其實(shí)就是根據(jù)進(jìn)程年齡做過濾,然后疊加ProcessInfo中的相關(guān)值(虛擬內(nèi)存:vmem)竿滨。
3.9ContainersMonitorImpl.isProcessTreeOverLimit
isProcessTreeOverLimit用于判斷內(nèi)存使用量是否超過上限值,虛擬內(nèi)存和物理內(nèi)存共用此方法曙砂。
currentMemUsage:進(jìn)程樹中所有進(jìn)程的虛擬或物理內(nèi)存使用總量鸠澈;
curMemUsageOfAgedProcesses:進(jìn)程樹中所有年齡大于1的進(jìn)程的虛擬或物理內(nèi)存使用總量笑陈;
vmemLimit:進(jìn)程樹虛擬或物理內(nèi)存使用上限涵妥;
滿足以下二個(gè)條件之一蓬网,則認(rèn)為進(jìn)程樹內(nèi)存使用超過上限:
(1)currentMemUsage大于vmemLimit的兩倍帆锋,這樣做的目錄主要是為了防止誤判(見本文開篇所述)锯厢;
(2)curMemUsageOfAgedProcesses大于vmemLimit(年齡大于一的進(jìn)程可以認(rèn)內(nèi)存使用比較“穩(wěn)定”)捺氢;
至此徙菠,Hadoop Yarn基于線程監(jiān)控的內(nèi)存隔離方案介紹完畢
文章來源:https://www.2cto.com/net/201701/583588_2.html