Ui相關流程
Spark集群啟動之后,我們可以通過Web觀查集群狀態等信息,這一部分工作是Spark WebUi 模塊實現。
Servlet容器啟動:
Master創建時,會通過val webUi = new MasterWebUI(this, webUiPort)創建webUi,
在啟動Master時(perStart()中)通過webUi.bind()啟動JettyServer,即Servlet容器。
Master的preStart()的源碼如下所示
又webUi.bind()的源碼如下所示:
WebUI頁面信息
創建的MasterWebUI初始化時會添加三個頁面和一個靜態資源處理器,其初始化代碼如下:
其中 attachPage方法代碼如下:
其在添加頁面時將初始化,頁面地址pagePath,創建并綁定請求處理器,以及指定響應方法page.render(request).
其中createServletHandler實現如下:
此函數中會掉用另一重載方法,其又會調用creatServlet方法,創建Servlet用于對外提供服務。createServlet方法代碼如下所示:
Servlet中doGet方法用來處理get請求, 具體業務邏加由傳入的servletParams提供。
下面以attachPage(new MasterPage(this))為例對servletParams進行說明,由上文源碼示例attachPage可知 (request: HttpServletRequest) => page.render(request)為servletParams。此參數意為使用page.render(request)對request進行處理。
MasterPage
MasterPage負責對master頁面的請求,請求路徑為http://master:webUiPort/或http://master:webUiPort/json.
下面http://master:webUiPort/json請求進行說明,當servlet接收到請求后,通過page.renderJson對其進行處理, renderJson源程序代碼如下:
通過分析源代碼可知:renderjson首先向master發送消息RequestMasterState,請求Master的狀態信息. 然后阻塞等待結果,然后將結果轉換成JSON格式、返回。
Master收到RequestMasterState消息后:
將其狀態信息封裝成MasterStateResponse對象發送給請求者。
Spark MetricsSystem 運行機制
Spark中的Metrics System 特殊的“實例”創建的,結合數據源、數據匯(接收點)的系統,其作用是定期將數據指標從數據源拉到數據匯。
實例(instance):創建Metrics的實例一般指使用Metrics System的角色。Spark中有多種角色,像master, worker, executor, client Driver,這些角色會創建Metrics System用于監控。所以這里所說的“實例”代表這些角色。當前,Spark中已實現的實例有:master,worker, executor,driver, applications.
數據源(source): 從哪里收集數據指標,在Metrics System中存在兩種類型的數據源:
Spark 內部源,像MasterSource, WorkerSource等,這些源會收集Spark組件的狀態,它們與Spark中角色相關,當Metrics System創建后,它們會在Metrics System中注冊。
共用源,通過配制文件配制并通過反射機制進行加載,會收集更底層的狀態指標,像JvmSource。
數據匯(sink):收集的數據指標輸出的目的地,目的地可以是控制臺,Servlet等。
下面以Master為入口對Metrics System工作機制做詳細說明:
伴隨Master的創建會創建MetricsSystem、MasterSource、WebUI等對象
在Master啟動時會執行以下動作:
綁定WebUI
將MasterSource注冊到Metrics中,
啟動MetricsSystem,并將其servlethandler綁定到WebUI.
MetricsConfig
創建MetricsConfig時會創建并初始化MetricsConfig, MetricsConfig將持有一個HashMap類型的propertyCategories,其用來存放處理過的屬性集合。再獲取MetricsConfig實例時都將會從此屬性中取相應的Metric sConfig配制.如下代碼所示:若存在指定key的屬性,則返回;否則返回默認值。
propertyCategories將在MetricsConfig初始化時(initialize()調用時)對其賦值,初始化過程如下:
防止沒有屬性文件,添加默認屬性。
檢測spark.metrics.conf是否設置,若未設置則試著去classpath下尋找”metrics.properties”文件。若存在配制文件,則將其屬性載入properties。
然后將properties中內容進行抽取、分類、歸并處理,其代碼如下:
若不存在配制文件的情況下,系統只有默認添加屬性,經上述代碼處理的結果為:
applications -> {sink.servlet.class=org.apache.spark.metrics.sink.MetricsServlet, sink.servlet.path=/metrics/applications/json}
master -> {sink.servlet.class=org.apache.spark.metrics.sink.MetricsServlet, sink.servlet.path=/metrics/master/json}
* -> {sink.servlet.class=org.apache.spark.metrics.sink.MetricsServlet, sink.servlet.path=/metrics/json}
其中subProperties()方法是對properties屬性進行抽取、規類。代碼如下:
注冊數據源: MetricsSystem啟動時
當MetricsSystem 在啟動時將會調用注冊數據源函數registerSources(),注冊實例相關的所有數據源。
上面是registerSources相關代碼,其通過getInstance()方法獲取該instance相關的配制屬性。然后通過subProperties方法進行抽取、歸類。然后取出key為class的屬性,利用java反射機制創建Source對象并進行注冊。默認情況下不存在Source相關屬性,所以此例中MasterSource唯一數據源。
其通過MetricsConfig的getInstance()方法。該方法會以傳入的instance做為key 去propertyCategories中取屬性值
注冊數據匯(目的地)
MetricsSystem的start()方法通過調用registerSinks()方法來注冊數據匯(數據指標接收點)。程序代碼如下所示:
通過分析此方法的源碼,若未通過配制文件指定MetricsConfig屬性,則將只通過反射創建MetricsServlet,其內部再創建ServletHander交付WebUI使用。但此MetricsServlet并未做為sink添加到sinks列表,至此 sinks列表仍為空,MetricsSystem的start()方法中調用sinks.foreach(_.start)時將不執行任何動作。換句話說,在默認情況下,registerSinks方法只是對MetricsServlet進行實例化用。
MetricsServlet的創建
MetricsSystem在注冊Sink時, 會創建MetricsServlet, MetricsServlet的映射地址為propertyCategories是path屬性對應項,其做為一個web服務,用于對相應請求進行處理。 MetricsServlet會通過調用jettyUtils的createServletHandler方法ServletContextHandler,創建Handler。其核心代碼如下:
此方法將創建以/metrics/master/json為請求路徑的httpServlet, 影響類型為JSON串。
然后并將創建的Hander賦值給通過MetircsSystem的getServletHander方法交由WebUi處理。
getServletHander方法程序代碼如下所示: