Spark HistoryServer WebUI交互过程


发布于 2024-06-10 / 25 阅读 / 0 评论 /
本文基于Spark3.4.1

Spark WebUI是Spark HistoryServer提供的网页服务,可以展示Spark任务相关的历史记录信息,方便用户对任务进行分析和问题的排查。

1.Spark WebUI后端请求服务器初始化过程

Spark HistoryServer在启动过程中,会启动一个Jetty容器,容器中运行的servlet服务可以接收Web端的请求,并返回网页内容用于浏览器渲染页面。

Jetty容器的启动过程如下所示:

HistoryServer#main
    historyServer = new HistoryServer() extends WebUI(name = "HistoryServerUI", poolSize = 1000) // 定义了线程名称
    historyServer.bind()
        WebUI.bind()
            WebUI.initServer()
                WebUI.startJettyServer(name, poolSize)
                    pool = new org.eclipse.jetty.util.thread.QueuedThreadPool(poolSize) // 设置线程池最多线程大小,最小线程数为Math.min(8, poolSize)
                    pool.setName(name) // 设置线程名称
                    pool.setDaemon(true) // 设置为守护线程
                    server = new org.eclipse.jetty.server.Server(pool)
                    server.start()

这里可以看到,接收请求的线程名称前缀为HistoryServerUI,而且对于最大和最小线程数有一个明确的设置。

2.Spark WebUI页面定义

每个Spark WebUI页面都对应一个Scala类,共有21种页面,如下所示:

WebUIPage
    AllExecutionsPage
    AllJobsPage
    AllStagesPage
    ApplicationPage
    BatchPage
    EnvironmentPage
    ExecutionPage
    ExecutorThreadDumpPage
    ExecutorsPage
    HistoryPage
    JobPage
    LogPage
    MasterPage
    PoolPage
    RDDPage
    StagePage
    StoragePage
    StreamingPage
    StreamingQueryPage
    StreamingQueryStatisticsPage
    WorkerPage

这些Page类需继承org.apache.spark.ui.WebUIPage这个抽象类,WebUIPage中定义了需要实现的方法:

// prefix表示页面的path
private[spark] abstract class WebUIPage(var prefix: String) {
  // 用于返回渲染页面的html内容
  def render(request: HttpServletRequest): Seq[Node]

  // 用于获取页面的数据信息
  def renderJson(request: HttpServletRequest): JValue = JNothing
}

页面定义有了后,至于页面与url的映射关系是怎么样的呢?要回答这个问题,需要进入到WebUITab的设计中。

3.WebUITab页面管理

WebUITab就是一些WebUIPage的集合,可以更好地管理这些WebUIPage。WebUITab中定义了prefix,与WebUIPage中的prefix一起决定了这个页面的url path。下面是当前WebUITab与WebUIPage的映射关系。

WebUITab
    SparkUITab
        EnvironmentTab(prefix = "environment")
            EnvironmentPage(prefix = "") // page path /environment
        ExecutorsTab(prefix = "executors")
            ExecutorsPage(prefix = "") // page path /executors
            ExecutorThreadDumpPage(prefix = "threadDump") // page path /executors/threadDump
            ExecutorHeapHistogramPage(prefix = "heapHistogram") // page path /executors/heapHistogram
        JobsTab(prefix = "jobs")
            AllJobsPage(prefix = "") // page path /jobs
            JobPage(prefix = "job") // page path /jobs/job
        SQLTab(prefix = "SQL")
            AllExecutionsPage(prefix = "") // page path /SQL
            ExecutionPage(prefix = "execution") // page path /SQL/execution
        SparkConnectServerTab(prefix = "connect")
            SparkConnectServerPage(prefix = "") // page path /connect
            SparkConnectServerSessionPage(prefix = "session") // page path /connect/session
        StagesTab(prefix = "stages")
            AllStagesPage(prefix = "") // page path /stages
            StagePage(prefix = "stage") // page path /stages/stage
            PoolPage(prefix = "pool") // page path /stages/pool
        StorageTab(prefix = "storage")
            StoragePage(prefix = "") // page path /storage
            RDDPage(prefix = "rdd") // page path /storage/rdd
        StreamingQueryTab(prefix = "StreamingQuery")
            StreamingQueryPage(prefix = "") // page path /StreamingQuery
            StreamingQueryStatisticsPage(prefix = "statistics") // page path /StreamingQuery/statistics
        StreamingTab(prefix = "streaming")
            StreamingPage(prefix = "") // page path /streaming
            BatchPage(prefix = "batch") // page path /streaming/batch