天天看點

Spark UI (基于Yarn) 分析與定制

有時候我們希望能對spark ui進行一些定制化增強。并且我們希望盡可能不更改spark的源碼。為了達到此目标,我們會從如下三個方面進行闡述:

了解spark ui的處理流程

現有executors頁面分析

自己編寫一個helloword頁面

spark ui 在sparkcontext 對象中進行初始化,對應的代碼:

這裡做了兩個動作,

通過sparkui.createliveui 建立一個sparkui執行個體 _ui

通過 _ui.foreach(_.bind())啟動jetty。bind 方法是繼承自webui,該類負責和真實的jetty server api打交道。

和傳統的web服務不一樣,spark并沒有使用什麼頁面模闆引擎,而是自己定義了一套頁面體系。我們把這些對象分成兩類:

架構類,就是維護各個頁面關系,和jetty api有關聯,負責管理的相關類。

頁面類,比如頁面的tab,頁面渲染的内容等

架構類有:

sparkui,該類繼承子webui,中樞類,負責啟動jetty,儲存頁面和url path之間的關系等。

webui

頁面類:

sparkuitab(繼承自webuitab) ,就是首頁的标簽欄

webuipage,這個是具體的頁面。

sparkui 負責整個spark ui建構是,同時它是一切頁面的根對象。

對應的層級結構為:

在sparkcontext初始化的過程中,sparkui會啟動一個jetty。而建立起jetty 和webuipage的橋梁是org.apache.spark.ui.webui類,該類有個變量如下:

這個org.eclipse.jetty.servlet.servletcontexthandler是标準的jetty容器的handler,而

pagetohandlers 則維護了webuipage到servletcontexthandler的對應關系。

這樣,我們就得到了webuipage 和 jetty handler的對應關系了。一個http請求就能夠被對應的webuipage給承接。

從 mvc的角度而言,webuipage 更像是一個controller(action)。内部實作是webuipage被包括進了一個匿名的servlet. 是以實際上spark 實作了一個對servlet非常mini的封裝。如果你感興趣的話,可以到org.apache.spark.ui.jettyutils 詳細看看。

目前spark 支援三種形态的http渲染結果:

text/json

text/html

text/plain

一般而言一個webuipage會對應兩個handler,

在頁面路徑上,html和json的差別就是html的url path 多加了一個"/json"字尾。 這裡可以看到,一般一個page最好實作

render

renderjson

兩個方法,以友善使用。

另外值得一提的是,上面的代碼也展示了url path和對應的處理邏輯(controller/action)是如何關聯起來的。其實就是pagepath -> page的render函數。

我們以 executors 顯示清單頁 為例子,來講述怎麼自定義開發一個page。

首先你需要定義個tab,也就是executorstab,如下:

executorstab會作為一個标簽顯示在spark首頁上。接着定義一個executorspage,作為标簽頁的呈現内容,并且通過

關聯上 executorstab 和  executorspage。

executorspage 的定義如下:

實作executorspage.render方法:

最後一步調用

輸出設定頁面頭并且輸出content頁面内容。

這裡比較有意思的是,spark 并沒有使用類似freemarker或者velocity等模闆引擎,而是直接利用了scala對html/xml的文法支援。類似這樣,寫起來也蠻爽的。

如果想使用變量,使用{}即可。

那最終這個tag是怎麼添加到頁面上的呢?如果你去翻看了源碼,會比較心疼,他是在sparkui的initialize方法裡定義的:

那我們新增的該怎麼辦?其實也很簡單啦,通過sparkcontext擷取到 sparkui對象,然後調用attachtab方法即可完成,具體如下:

如果你是在spark-streaming裡,則簡單通過如下代碼就能把你的頁面頁面添加進去:

添加新的tab可能會報錯,scala報的錯誤比較讓人困惑,可以試試加入下面依賴:

實作新增一個helloword頁面

我們的例子很簡單,類似下面的圖:

Spark UI (基于Yarn) 分析與定制

無标題.png

按前文的描述,我們需要一個tab頁,以及一個展示tab對應内容的page頁。其實就下面兩個類。

org.apache.spark.streaming.ui2.kktab:

org.apache.spark.streaming.ui2.ttpage 如下:

記得添加上面提到的jetty依賴。

繼續閱讀