圖片的價(jià)值就是它可以讓我們發(fā)現(xiàn)未曾預(yù)期的事情——John Tukey。
在過去,Spark UI一直是用戶應(yīng)用程序調(diào)試的幫手。而在最新版本的Spark 1.4中,我們很高興地宣布,一個(gè)新的因素被注入到Spark UI——數(shù)據(jù)可視化。在此版本中,可視化帶來的提升主要包括三個(gè)部分:
Spark events時(shí)間軸視圖
Execution DAG
Spark Streaming統(tǒng)計(jì)數(shù)字可視化
我們會(huì)通過一個(gè)系列的兩篇博文來介紹上述特性,本次則主要分享前兩個(gè)部分——Spark events時(shí)間軸視圖和Execution DAG。Spark Streaming統(tǒng)計(jì)數(shù)字可視化將在下一篇博文中解釋。
Spark events時(shí)間軸視圖
從Spark 初期版本至今,Spark events一直是面向用戶API的一部分。在最新的1.4版本,Spark UI將會(huì)把這些events在一個(gè)時(shí)間軸中顯示,讓用戶可以一眼區(qū)別相對和交叉順序。
時(shí)間軸視圖可以覆蓋3個(gè)等級(jí):所有Job,指定的某個(gè)Job,以及指定的某個(gè)stage。在下圖中,時(shí)間軸顯示了橫跨一個(gè)應(yīng)用程序所有作業(yè)中的Spark events。
這里的events順序相對簡單,在所有 executors 注冊后,在應(yīng)用程序并行運(yùn)行的4個(gè)job中,有一個(gè)失敗,其余成功。當(dāng)所有工作完成,并在應(yīng)用程序退出后,executors同樣被移除。下面不妨點(diǎn)擊關(guān)注其中的一個(gè)job:

該job在3個(gè)文件中做word count,最后join并輸出結(jié)果。從時(shí)間軸上看,很明顯, 3個(gè) word count stages 并行運(yùn)行,因?yàn)樗鼈儾换ハ嘁蕾?。同時(shí),最后一個(gè)階段需要依賴前3個(gè)文件word count的結(jié)果,所以相應(yīng)階段一直等到所有先行階段完成后才開始。下面著眼單個(gè)stage:

這個(gè)stage被切分為20個(gè)partitions,分別在4臺(tái)主機(jī)上完成(圖片并沒有完全顯示)。每段代表了這個(gè)階段的一個(gè)單一任務(wù)。從這個(gè)時(shí)間軸來看,我們可以得到這個(gè)stage上的幾點(diǎn)信息。
首先,partitions在機(jī)器中的分布狀態(tài)比較樂觀。其次,大部分的任務(wù)執(zhí)行時(shí)間分配在原始的計(jì)算上,而不是網(wǎng)絡(luò)或I/ O開銷。這并不奇怪,因?yàn)閭鬏數(shù)臄?shù)據(jù)很少。最后,我們可以通過給executors分配更多的核心來提升并行度;從目前來看,每個(gè)executors可以同時(shí)執(zhí)行不超過兩個(gè)任務(wù)。
借此機(jī)會(huì)展示一下Spark通過該時(shí)間軸獲得的另一個(gè)特性——?jiǎng)討B(tài)分配。該特性允許Spark基于工作負(fù)載來動(dòng)態(tài)地衡量executors 的數(shù)量,從而讓集群資源更有效地共享。不妨看向下張圖表:

首先要注意的是,這個(gè)應(yīng)用程序是在工作的過程中獲得executors ,而不是預(yù)先分配好。在個(gè)job結(jié)束后,用于該job的executors將閑置并返回到集群。因此在這個(gè)期間,同集群中運(yùn)行的其他應(yīng)用程序可以獲得這些資源,從而增加集群資源利用率。只有當(dāng)一個(gè)新的job執(zhí)行時(shí),Spark應(yīng)用程序才會(huì)獲取一組新的executors 來運(yùn)行它。
在一個(gè)時(shí)間軸中查看Spark events的能力有助于確定應(yīng)用程序瓶頸,從而在調(diào)試過程中進(jìn)行更有針對性的優(yōu)化。
Execution DAG
在新版本的Spark中,第二個(gè)可視化聚焦DAG執(zhí)行的每個(gè)作業(yè)。在Spark中,job與被組織在DAG中的一組RDD依賴性密切相關(guān),類似下圖:

這個(gè)job執(zhí)行一個(gè)簡單的word cout。首先,它執(zhí)行一個(gè)textFile從HDFS中讀取輸入文件,然后進(jìn)行一個(gè)flatMap操作把每一行分割成word,接下來進(jìn)行一個(gè)map操作,以形成form(word,1)對,最后進(jìn)行一個(gè)reduceByKey操作總結(jié)每個(gè)word的數(shù)值。
可視化的藍(lán)色陰影框?qū)?yīng)到Spark操作,即用戶調(diào)用的代碼。每個(gè)框中的點(diǎn)代表對應(yīng)操作下創(chuàng)建的RDDs。操作本身由每個(gè)流入的stages劃分。
通過可視化我們可以發(fā)現(xiàn)很多有價(jià)值的地方。首先,根據(jù)顯示我們可以看出Spark對流水線操作的優(yōu)化——它們不會(huì)被分割。尤其是,從HDF S讀取輸入分區(qū)后,每個(gè)executor隨后即對相同任務(wù)上的partion做flatMap和map,從而避免與下一個(gè)stage產(chǎn)生關(guān)聯(lián)。
其次,RDDs在個(gè)stage中會(huì)進(jìn)行緩存(用綠色突出表示),從而避免對HDFS(磁盤)相關(guān)讀取工作。在這里,通過緩存和最小化文件讀取可以獲得更高的性能。
DAG可視化的價(jià)值在復(fù)雜jobs中體現(xiàn)的尤為明顯。比如下圖中的ALS計(jì)算,它會(huì)涉及到大量的map、join、groupByKey操作。

值得注意的是,在ALS中,緩存準(zhǔn)確性將對性能產(chǎn)生的影響非常大,因?yàn)樵撍惴ㄔ诿看蔚袝?huì)重度使用之前步驟產(chǎn)生的結(jié)果。如今通過DAG可視化,用戶和開發(fā)人員可以一目了然地查明RDDS是否被恰當(dāng)?shù)鼐彺?,如果沒有,可以快速理理解實(shí)現(xiàn)緩慢的原因。
與時(shí)間軸視圖一樣,DAG可視化允許用戶點(diǎn)擊進(jìn)入一個(gè)stage進(jìn)行更詳細(xì)地觀察。下圖描述了ALS中一個(gè)獨(dú)立的stage。

在stage視圖中,屬于這個(gè)stage的所有RDDS細(xì)節(jié)被自動(dòng)展開。當(dāng)前,用戶可以快速地找到具體的RDDS信息,而不必job頁面通過懸停各個(gè)點(diǎn)來猜測和檢查。
最后,在這里突出一下DAG可視化和 SparkSQL之間的一個(gè)初步的集成。對比更接近物理實(shí)體層面的Spark操作,Spark SQL用戶顯然更熟悉一些高級(jí)操作,因此一些高級(jí)操作更需要被可視化。其結(jié)果類似將一個(gè)SQL查詢計(jì)劃映射到底層執(zhí)行的DAG。

與SparkStreaming的整合在Spark 1.4版本中同樣有所實(shí)現(xiàn),這里在下一篇博文中會(huì)詳細(xì)介紹。
在不久的將來,Spark UI可以更理解一些更高級(jí)別的函數(shù)庫語義,以提供更多相關(guān)細(xì)節(jié)。 同時(shí),Spark SQL將與Spark Streaming一樣獲得類似的標(biāo)簽。而在Spark Core中,當(dāng)用戶查看RDD時(shí),類似partitions數(shù)量、調(diào)用點(diǎn)、緩存率都將會(huì)被可視化。
在此感謝社區(qū)中所有對可視化工作有所貢獻(xiàn)的組織和個(gè)人,更特別感謝NTT Data的@sarutak在時(shí)間軸可視化特性中的主要貢獻(xiàn)。