在SparkContext中可以看到初始化UI代码:
// Initialize the Spark UIprivate[spark] val ui: Option[SparkUI] = if (conf.getBoolean("spark.ui.enabled", true)) { Some(SparkUI.createLiveUI(this, conf, listenerBus, jobProgressListener, env.securityManager,appName)) } else { // For tests, do not enable the UI None }// Bind the UI before starting the task scheduler to communicate// the bound port to the cluster manager properlyui.foreach(_.bind())创建SparkUI对象:
def createLiveUI( sc: SparkContext, conf: SparkConf, listenerBus: SparkListenerBus, jobProgressListener: JobProgressListener, securityManager: SecurityManager, appName: String): SparkUI = { create(Some(sc), conf, listenerBus, securityManager, appName, jobProgressListener = Some(jobProgressListener))}
进入create方法:
进入SparkUI:
SparkUI 继承了WebUI:
而WebUI类定义了def initialize()方法
SparkUI的initialize()实现方法:
上面代码分析:增加页面的tab页面
1、JobsTab:
2、stagesTab:
3、StorageTab:
4、EnvironmentTab:
5、ExecutorsTab:
6、createStaticHandler:
7、createRedirectHandler:
当执行完initialize()方法后,我们回到SparkContext 的Initialize the spark UI:
bind port:
从上面代码可以看出来,启动了端口号为4040的本地JettyServer
上面代码分析:
1、创建ContextHandlerCollection并将handlers设置到ContextHandlerCollection中
2、增加一个filter:
3、创建Jetty Server并绑定端口号并创建一个QueuedThreadPool,设置到Server中:
4、启动Jetty server,如果启动失败,就抛出异常:
5、试着重试几次启动startServiceOnPort,如果启动失败,就更换新端口号(规则是1+oldPort),重新启动:
最终启动成功后,会把信息东西存放在ServerInfo中: