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