天天看點

《深入了解Spark:核心思想與源碼分析》——3.4節SparkUI詳解

本節書摘來自華章社群《深入了解spark:核心思想與源碼分析》一書中的第3章,第3.4節sparkui詳解,作者耿嘉安,更多章節内容可以通路雲栖社群“華章社群”公衆号檢視

3.4 sparkui詳解

任何系統都需要提供監控功能,用浏覽器能通路具有樣式及布局并提供豐富監控資料的頁面無疑是一種簡單、高效的方式。sparkui就是這樣的服務,它的架構如圖3-1所示。

在大型分布式系統中,采用事件監聽機制是最常見的。為什麼要使用事件監聽機制?假如sparkui采用scala的函數調用方式,那麼随着整個叢集規模的增加,對函數的調用會越來越多,最終會受到driver所在jvm的線程數量限制而影響監控資料的更新,甚至出現監控資料無法及時顯示給使用者的情況。由于函數調用多數情況下是同步調用,這就導緻線程被阻塞,在分布式環境中,還可能因為網絡問題,導緻線程被長時間占用。将函數調用更換為發送事件,事件的處理是異步的,目前線程可以繼續執行後續邏輯,線程池中的線程還可以被重用,這樣整個系統的并發度會大大增加。發送的事件會存入緩存,由定時排程器取出後,配置設定給監聽此事件的監聽器對監控資料進行更新。

《深入了解Spark:核心思想與源碼分析》——3.4節SparkUI詳解

我們先簡單介紹圖3-1中的各個元件:dagscheduler是主要的産生各類sparklistener-event的源頭,它将各種sparklistenerevent發送到listenerbus的事件隊列中,listenerbus通過定時器将sparklistenerevent事件比對到具體的sparklistener,改變sparklistener中的統計監控資料,最終由sparkui的界面展示。從圖3-1中還可以看到spark裡定義了很多監聽器sparklistener的實作,包括jobprogresslistener、environmentlistener、storagelistener、executorslistener,它們的類繼承體系如圖3-2所示。

《深入了解Spark:核心思想與源碼分析》——3.4節SparkUI詳解

3.4.1 listenerbus詳解

listenerbus的類型是livelistenerbus。livelistenerbus實作了監聽器模型,通過監聽事件觸發對各種監聽器監聽狀态資訊的修改,達到ui界面的資料重新整理效果。livelistenerbus由以下部分組成:

事件阻塞隊列:類型為linkedblockingqueue[sparklistenerevent],固定大小是10 000;

監聽器數組:類型為arraybuffer[sparklistener],存放各類監聽器sparklistener。

事件比對監聽器的線程:此thread不斷拉取linkedblockingqueue中的事件,周遊監聽器,調用監聽器的方法。任何事件都會在linkedblockingqueue中存在一段時間,然後thread處理了此事件後,會将其清除。是以使用listenerbus這個名字再合适不過了,到站就下車。listenerbus的實作見代碼清單3-15。

代碼清單3-15 livelistenerbus的事件處理實作

3.4.2 構造jobprogresslistener

我們以jobprogresslistener為例來講解sparklistener。jobprogresslistener是sparkcontext中一個重要的組成部分,通過監聽listenerbus中的事件更新任務進度。sparkstatustracker和sparkui實際上也是通過jobprogressli

stener來實作任務狀态跟蹤的。建立jobprogresslistener的代碼如下。

jobprogresslistener 實作了onjobstart、onjobend、onstagecompleted、onstagesubmitted、ontaskstart、ontaskend等方法,這些方法正是在listenerbus的驅動下,改變jobprogress-listener中的各種job、stage相關的資料。

3.4.3 sparkui的建立與初始化

sparkui的建立,見代碼清單3-18。

代碼清單3-18 sparkui的聲明

3.4.4 spark ui的頁面布局與展示

sparkui究竟是如何實作頁面布局及展示的?jobstab展示所有job的進度、狀态資訊,這裡我們以它為例來說明。jobstab會複用sparkui的killenabled、sparkcontext、job-progresslistener,包括alljobspage和jobpage兩個頁面,見代碼清單3-22。

代碼清單3-22 jobstab的實作

alljobspage由render方法渲染,利用jobprogresslistener中的統計監控資料生成激活、完成、失敗等狀态的job摘要資訊,并調用jobstable方法生成表格等html元素,最終使用uiutils的headersparkpage封裝好css、js、header及頁面布局等,見代碼清單3-23。

代碼清單3-23 alljobspage的實作

由于代碼清單3-27所在的類中使用import org.apache.spark.ui.jettyutils._導入了jettyutils的靜态方法,是以createservlethandler方法實際是jettyutils 的靜态方法createservlethandler。createservlethandler實際建立了javax.servlet.http.httpservlet的匿名内部類執行個體,此執行個體實際使用(request: httpservletrequest) => page.render(request)函數參數來處理請求,進而渲染頁面呈現給使用者。有關createservlethandler的實作及jetty的相關資訊,請參閱附錄c。

3.4.5 sparkui的啟動

sparkui建立好後,需要調用父類webui的bind方法,綁定服務和端口,bind方法中主要的代碼實作如下。

serverinfo = some(startjettyserver("0.0.0.0", port, handlers, conf, name))

jettyutils的靜态方法startjettyserver的實作請參閱附錄c。最終啟動了jetty提供的服務,預設端口是4040。