您好,登錄后才能下訂單哦!
原文鏈接
作者: 祝威廉
Mesos 和 Yarn 都是非常優(yōu)秀的資源調(diào)度框架,社區(qū)也有很多的人分析二者的區(qū)別以及使用場(chǎng)景。之前 InfoQ 也有發(fā)問(wèn)聊過(guò)二者的關(guān)系。目前業(yè)界用的較多的是 Mesos,這篇文章就是為了解釋為什么作者選擇使用 Yarn 而不是 Mesos,并介紹了如何基于 Yarn 開(kāi)發(fā)分布式程序。本文首發(fā)于祝威廉的博客,經(jīng)授權(quán)由 InfoQ 轉(zhuǎn)載發(fā)布。
Mesos 其實(shí)我不是非常熟悉,所以有些內(nèi)容可能會(huì)有失偏頗,帶有個(gè)人喜好。大家也還是需要有自己的鑒別能力。
Mesos 和 Yarn 都非常棒,都是可編程的框架。一個(gè)硬件,不能編程,就是死的,一旦可以編程就活了,就可以各種折騰,有各種奇思妙想可以實(shí)現(xiàn),同樣的,一個(gè)軟件,只要是可編程的,基本也就活了,容易形成生態(tài)。
我先說(shuō)說(shuō)在做容器調(diào)度引擎的時(shí)候,為什么選擇 Yarn 而不是 Mesos。
先說(shuō)明下,這里探討的是 Yarn 或者 Mesos 集群的部署,不涉其上的應(yīng)用。Yarn 除了依賴 JDK,對(duì)操作系統(tǒng)沒(méi)有任何依賴,基本上放上去就能跑。Mesos 因?yàn)槭?C/C++ 開(kāi)發(fā)的,安裝部署可能會(huì)有庫(kù)依賴。 這點(diǎn)我不知道大家是否看的重,反正我是看的相當(dāng)重的。軟件就應(yīng)該是下下來(lái)就可以 Run。所以 12 年的時(shí)候我就自己開(kāi)發(fā)了一套 Java 服務(wù)框架,開(kāi)發(fā)完之后運(yùn)行個(gè) main 方法就行。讓?xiě)?yīng)用包含容器,而不是要把應(yīng)用丟到 Tomcat 這些容器,太復(fù)雜,不符合直覺(jué)。
Yarn 對(duì) Java/Scala 工程師而言,只是個(gè) Jar 包,類似索引開(kāi)發(fā)包 Lucene,你可以把它引入項(xiàng)目,做任何你想要的包裝。 這是其一。
其二,Yarn 提供了非常多的擴(kuò)展接口,很多實(shí)現(xiàn)都是可插拔??商鎿Q的,在 XML 配置下,可以很方便的用你的實(shí)現(xiàn)替換掉原來(lái)的實(shí)現(xiàn),沒(méi)有太大的侵入性,所以就算是未來(lái) Yarn 升級(jí),也不會(huì)有太大問(wèn)題。
相比較而言,Mesos 更像是一個(gè)已經(jīng)做好的產(chǎn)品,部署了可以直接用,但是對(duì)二次開(kāi)發(fā)并不友好。
Yarn 誕生于 Hadoop 這個(gè)大數(shù)據(jù)的“始作俑者”項(xiàng)目,所以在大數(shù)據(jù)領(lǐng)域具有先天優(yōu)勢(shì)。
底層天然就是分布式存儲(chǔ)系統(tǒng) HDFS,穩(wěn)定高效。
其上支撐了 Spark、MR 等大數(shù)據(jù)領(lǐng)域的扛頂之座,久經(jīng)考驗(yàn)。
社區(qū)強(qiáng)大,最近發(fā)布版本也明顯加快,對(duì)于長(zhǎng)任務(wù)的支持也越來(lái)越優(yōu)秀。
談及長(zhǎng)任務(wù)(long running services)的支持,有人認(rèn)為早先 Yarn 是為了支持離線短時(shí)任務(wù)的,所以可能對(duì)長(zhǎng)任務(wù)的支持有限。其實(shí)大可不必?fù)?dān)心,譬如現(xiàn)在基于其上的 Spark Streaming 就是 7x24 小時(shí)運(yùn)行的,跑起來(lái)也沒(méi)啥問(wèn)題。一般而言,要支持長(zhǎng)任務(wù),需要考慮如下幾個(gè)點(diǎn):
Fault tolerance,主要是 AM 的容錯(cuò)。
Yarn Security,如果開(kāi)啟了安全機(jī)制,令牌等的失效時(shí)間也是需要注意的。
日志收集到集群。
還有就是資源隔離和優(yōu)先級(jí)。如果資源隔離做的太差,會(huì)對(duì)長(zhǎng)時(shí)任務(wù)產(chǎn)生影響。
大家感興趣可以先參考Jira。我看這個(gè) Jira 13 年就開(kāi)始了,說(shuō)明這事很早就被重視起來(lái)了。下面我們隊(duì)提到的幾個(gè)點(diǎn)做下解釋。
Yarn 自身高可用。目前 Yarn 的 Master 已經(jīng)實(shí)現(xiàn)了 HA。
AM 容錯(cuò),我看從 2.4 版本(看的源碼,也可能更早的版本就已經(jīng)支持)就已經(jīng)支持 keep containers across attempt 的選項(xiàng)了。什么意思呢?就是如果 AM 掛掉了,在 Yarn 重新啟動(dòng) AM 的過(guò)程中,所有由 AM 管理的容器都會(huì)被保持而不會(huì)被殺掉。除非 Yarn 多次嘗試都沒(méi)辦法把 AM 再啟動(dòng)起來(lái)(默認(rèn)兩次)。 這說(shuō)明從底層調(diào)度上來(lái)看,已經(jīng)做的很好了。
日志收集在 2.6 版本已經(jīng)是邊運(yùn)行邊收集了。
資源隔離的話,Yarn 做的不好,目前有效的是內(nèi)存,對(duì)其他方面一直想做支持,但一直有限。這估計(jì)也是很多人最后選擇 Mesos 的緣由。但是現(xiàn)在這點(diǎn)優(yōu)勢(shì) Mesos 其實(shí)已經(jīng)蕩然無(wú)存,因?yàn)?Docker 容器在資源隔離上已經(jīng)做的足夠好。Yarn 和 Docker 一整合,就互補(bǔ)了。
Mesos 和 Yarn 都是非常優(yōu)秀的調(diào)度框架,各有其優(yōu)缺點(diǎn),彈性調(diào)度,統(tǒng)一的資源管理是未來(lái)平臺(tái)的一個(gè)趨勢(shì),類似的這種資源管理調(diào)度框架必定會(huì)大行其道。
脫胎于 Hadoop,繼承了他的光環(huán)和生態(tài),然而這也會(huì)給其帶來(lái)一定的困惑,首先就是光環(huán)一直被 Hadoop 給蓋住了,而且由于固有的慣性,大家會(huì)理所當(dāng)然的認(rèn)為 Yarn 只是 Hadoop 里的一個(gè)組件,有人會(huì)想過(guò)把 Yarn 拿出來(lái)單獨(dú)用么?
然而,就像我在之前的一篇課程里,反復(fù)強(qiáng)調(diào),Hadoop 是一個(gè)軟件集合,包含分布式存儲(chǔ),資源管理調(diào)度,計(jì)算框架三個(gè)部分。他們之間沒(méi)有必然的關(guān)系,是可以獨(dú)立開(kāi)來(lái)的。而 Yarn 就是一個(gè)資源管理調(diào)度引擎,其一開(kāi)始的設(shè)計(jì)目標(biāo)就是為了通用,不僅僅是跑 MR?,F(xiàn)在基于 Yarn 之上的服務(wù)已經(jīng)非常多,典型的比如 Spark。
這里還有另外一個(gè)誤區(qū),MR 目前基本算是離線批量的代名詞,這回讓人誤以為 Yarn 也只是適合批量離線任務(wù)的調(diào)度。其實(shí)不然,我在上面已經(jīng)給出了分析,Yarn 是完全可以保證長(zhǎng)任務(wù)的穩(wěn)定可靠的運(yùn)行的。
本文不會(huì)具體教你如何使用 Yarn 的 API,不過(guò)如果你想知道 Yarn 的 API,但是又覺(jué)得官方文檔太過(guò)簡(jiǎn)略,我這里倒是可以給出兩個(gè)建議:
代碼使用范例可以參看 Spark Yarn 相關(guān)的代碼。算的上是一個(gè)非常精簡(jiǎn)的 Yarn 的 adaptor。
買(mǎi)本 Yarn 相關(guān)的書(shū),了解其體系結(jié)構(gòu)也有助于你了解其 API 的設(shè)計(jì)。
接下來(lái)的內(nèi)容會(huì)探討以下兩個(gè)主題:
基于 Yarn 開(kāi)發(fā)分布式程序需要做的一些準(zhǔn)備工作
基于 Yarn 開(kāi)發(fā)容器調(diào)度系統(tǒng)的一些基本思路
肯定不能擼起袖子就開(kāi)始干。開(kāi)始動(dòng)手前,我們需要知道哪些事情呢?
如果你想愉快的開(kāi)發(fā) Yarn 的應(yīng)用,那么對(duì) Yarn 的 API 進(jìn)行一次封裝,是很有必要的。 Yarn 為了靈活,或者為了能夠滿足開(kāi)發(fā)者大部分的需求,底層交互的 API 就顯得比較原始了。自然造成開(kāi)發(fā)難度很大。這個(gè)也不是我一個(gè)人覺(jué)得,現(xiàn)在 Apache 的 Twill,以及 Hulu 他們開(kāi)發(fā)的時(shí)候 Adaptor 那一層,其實(shí)都是為了解決這個(gè)問(wèn)題。那為什么我沒(méi)有用 Twill 呢,第一是文檔實(shí)在太少,第二是有點(diǎn)復(fù)雜,我不需要這么復(fù)雜的東西。我覺(jué)得,Twill 與其開(kāi)發(fā)這么多功能,真的不如好好寫(xiě)寫(xiě)文檔。
Yarn 只是一個(gè)底層的資源管理和調(diào)度引擎。一般你需要基于之上開(kāi)發(fā)一套解決特定問(wèn)題的 Framework。以 Spark 為例,他是解決分布式計(jì)算相關(guān)的一些問(wèn)題。而以我開(kāi)發(fā)的容器調(diào)度程序,其實(shí)是為了解決動(dòng)態(tài)部署 Web 應(yīng)用的。在他們之上,才是你的應(yīng)用。比如你要統(tǒng)計(jì)日志,你只要在 Spark 上開(kāi)發(fā)一個(gè) Application 。 比如你想要提供一個(gè)推薦系統(tǒng),那么你只要用容器包裝下,就能被容器調(diào)度程序調(diào)度部署。
所以通常而言,基于 Yarn 的分布式應(yīng)用應(yīng)該符合這么一個(gè)層次:
Yarn -> Adapter -> Framework -> Application
Adapter 就是我第一條說(shuō)的,你自個(gè)封裝了 Yarn 的 API。 Framework 就是解決一類問(wèn)題的編程框架,Application 才是你真正要解決業(yè)務(wù)的系統(tǒng)。通過(guò)這種解耦,各個(gè)層次只要關(guān)注自己的核心功能點(diǎn)即可。
Spark 是個(gè)典型,他可以跑在 Mesos 上,也可以跑在 Yarn 上,還可以跑在自己上面(Standalone),實(shí)時(shí)上,泡在 Yarn 上的,以及跑 Standalone 模式的,都挺多的。這得益于 Spark 本身不依賴于底層的資源管理調(diào)度引擎。
這其實(shí)也是我上面說(shuō)的兩條帶來(lái)的好處,因?yàn)橛辛?Adaptor,上層的 Framework 可以不用綁死在某個(gè)資源調(diào)度引擎上。而 Framework 則可以讓 Applicaiton 無(wú)需關(guān)注底層調(diào)度的事情,只要關(guān)注業(yè)務(wù)即可。
另外,你費(fèi)盡心機(jī)開(kāi)發(fā)的 Framework 上,你自然是希望它能跑在更多的平臺(tái)上,已滿足更多的人的需求,對(duì)吧。
首先我們需要了解兩個(gè)概念:
啞應(yīng)用。所謂啞應(yīng)用指的是無(wú)法和分布式系統(tǒng)直接進(jìn)行交互,分布式系統(tǒng)也僅僅透過(guò)容器能進(jìn)行生命周期的控制,比如關(guān)閉或者開(kāi)啟的應(yīng)用。典型的比如 MySQL、Nginx 等這些基礎(chǔ)應(yīng)用。他們一般有自己特有的交互方式,譬如命令行或者 socket 協(xié)議或者 HTTP 協(xié)議。
伴生組件。因?yàn)橛辛藛?yīng)用的存在,分布式系統(tǒng)為了能夠和這些應(yīng)用交互,需要有一個(gè)代理。而這個(gè)代理和被代理的啞應(yīng)用,具有相同的生命周期。典型的比如,某個(gè)服務(wù)被關(guān)停后,該事件會(huì)被分布式系統(tǒng)獲知,分布式系統(tǒng)會(huì)將該事件發(fā)送給 Nginx 的伴生組件,伴生組件轉(zhuǎn)化為 Nginx 能夠識(shí)別的指令,將停止的服務(wù)從 Nginx 的 ProxyBackend 列表中剔除。
在容器調(diào)度系統(tǒng)中,如果 Yarn 的 NodeManager 直接去管理 Docker 則需要 Yarn 本身去做支持,我覺(jué)得這是不妥的。Yarn 的職責(zé)就是做好資源管理,分配,調(diào)度即可,并不需要和特定的某個(gè)技術(shù)耦合,畢竟 Yarn 是一個(gè)通用型的資源調(diào)度管理框架。
那基于上面的理論,我們基于 Yarn,開(kāi)發(fā)一套框架,這個(gè)框架會(huì)是典型的 master-slave 結(jié)構(gòu)(這是 Yarn 決定的)。這個(gè)框架的 slaves 其實(shí)都是 Docker 的伴生對(duì)象。master 可以通過(guò)這些 Slave 對(duì)容器實(shí)現(xiàn)間接的管理。
?我們簡(jiǎn)單描述下他們的流程:
用戶提交 Application,申請(qǐng)資源;
Yarn 啟動(dòng) Framework 的 master;
Yarn 啟動(dòng) Framework 的 slave;
slave 連接上 master,并且發(fā)送心跳,從而 master 知道 slave 的狀況 slave 啟動(dòng) Docker,slave 與被啟動(dòng)的這個(gè) docker container 一一對(duì)應(yīng);
slave 定時(shí)監(jiān)控 Container;
slave 發(fā)現(xiàn) container crash,slave 自動(dòng)退出,Yarn 獲得通知,收回資源;
master 發(fā)現(xiàn)有節(jié)點(diǎn)失敗,發(fā)出新的節(jié)點(diǎn)要求,重新在另外一臺(tái)服務(wù)器上啟動(dòng) slave,重復(fù)從 2 開(kāi)始的步驟。
這里還有一個(gè)問(wèn)題,如果 slave 被正常殺掉,可以通過(guò) JVM ShudownHook 順帶把 Container 也關(guān)掉。 但是如果 slave 被 kill -9 或者異常 crash 掉了,那么就可能導(dǎo)致資源泄露了。目前是這個(gè)信息是由 master 上報(bào)給集群管理平臺(tái),該平臺(tái)會(huì)定時(shí)清理。你也可以存儲(chǔ)該信息,譬如放到 Redis 或者 MySQL 中,然后啟動(dòng)后臺(tái)清理任務(wù)即可。
了解了這個(gè)思路后,具體實(shí)施就變得簡(jiǎn)單了,就是開(kāi)發(fā)一個(gè)基于 Yarn 的 master-slave 程序即可,然后 slave 去管理對(duì)應(yīng)的 Docker 容器,包括接受新的指令。master 提供管理界面展示容器信息,運(yùn)行狀態(tài)即可。
當(dāng)然,你還可以再開(kāi)發(fā)一套 Framework B 專門(mén)和 Nginx 交互,這樣比如上面的系統(tǒng)做了節(jié)點(diǎn)變更,通知 B 的 master,然后 B 的 master 通過(guò)自己的伴生組件 Slave 完成 Nginx 的更新,從而實(shí)現(xiàn)后端服務(wù)的自動(dòng)變更和通知。
現(xiàn)在看來(lái),是不是這種概念完美的覆蓋了應(yīng)用之間的交互呢?
免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如果涉及侵權(quán)請(qǐng)聯(lián)系站長(zhǎng)郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。