山东大学软件工程应用与实践: Spark(十一) 代码分析

本文深入探讨了Spark的MetricsSystem,介绍了如何启动测量系统,包括注册Sources、Sinks以及添加Jetty的ServletContextHandler。MetricsSystem使用Metrics库,区分了Master、Worker、Application、Driver和Executor等不同实例的角色。默认Sink MetricsServlet被用于输出测量数据,并在SparkUI中展示。
摘要由CSDN通过智能技术生成

2021SC@SDUSC


目录

启动测量系统MetricsSystem

1.注册Sources

2.注册Sinks

3.给Sinks增加Jetty的ServletContextHandler


启动测量系统MetricsSystem

MetricsSystem使用codahale提供的第三方测量仓库Metrics。MetricsSystem中有三个概念:

  • Instance:指定了谁在使用测量系统
  • Source:指定了从哪里收集测量数据
  • Sink:指定了往哪里输出测量数据、

Spark按照Instance的不同,区分为Master,Worker,Application,Driver和Executor。

Spark目前提供的Sink有ConsoleSink、CsvSink、JmxSink、MetricsServlet、GraphiteSink等。

Spark中使用MetricsServlet作为默认的Sink。

MetricsSystem的启动代码如下:
 

val metricsSystem = env.metricsSystem
    metricsSystem.start()

Metrics的启动过程包括如下步骤:

  1. 注册Sources
  2. 注册Sinks
  3. 给Sinks增加Jetty的ServletContextHandler

MetricsSystem启动完毕后,会遍历与Sinks有关的ServletContextHandler,并调用attachHandler将它们绑定到SparkUI上。

metricsSystem.getServletHandlers.foreach(handler => ui.foreach(_.attachHandler(handler)))

1.注册Sources

registerSources方法用于注册Sources,告诉测量系统从哪里收集测量数据,它的实现见代码 3-45。注册Sources的过程分为以下步骤:

  1. 从metricsConfig获取Driver的Properties,默认为创建MetricsSystem的过程中解析的{sink.servlet.class = org.apache.spark.metrics.sink.MetricsServlet, sink.servlet.path=/metrics/json}。
  2. 用正则匹配Driver的Properties中以source.开头的属性。然后将属性中的Source反射得到的实例加入ArrayBuffer[Source]。
  3. 将每个source的metricRegistry(也是MetricSet的子类型)注册到ConcurrentMap<String, Metric> metrics。
// code 3-45
private def registerSources() {
    val insConfig = metricsConfig.getinstance(instance)
    val sourceConfigs = metricsConfig.subProperties(instConfig,MetricsSystem.SOURCE_REGEX) 

    // Registerall the sources related to instance 
    sourceConfigs.foreach { kv => 
        val classPath = kv._2.getProperty("class") 
        try {
            val source = Class.forName(classPath).newinstance()
            registerSource(source.aslnstanceOf[Source]) 
        } catch { 
            case e: Exception=>logError("Source class "+class Path+" cannot be         
            instantiated", e)
        }
    }
}

2.注册Sinks

registerSinks方法用于注册Sinks,即告诉测量系统MetricsSystem往哪里输出测量数据, 它的实现见代码3-46,注册Sinks的步骤如下:

  1. 从Driver的Properties中用正则匹配以sink开头的属性,如{sink.servlet.class=org. apache.spark.metrics.sink.MetricsServlet, sink.servlet.path=/metrics/json},将其转换为Map(servlet -> {class=org.apache.spark.metrics.sink.MetricsServlet, path=/metrics/json})。
  2. 将子属性 class对应的类metricsServlet反射得到MetricsServlet 实例。 如果属性的key是servlet,将其设牲为metricsServlet;如果是Sink,则加入到ArrayBuffer[Sink]中。
// code 3-46
private def registerSinks () {
    val instConfig = metricsConfig.getinstance(instance) 
    val sinkConfigs = metricsConfig.subProperties(instConfig, MetricsSystem.SINK_REGEX) 
    sinkConfigs.foreach { kv => 
        val classPath = kv._2.getProperty("class") 
        if (null != classPath) { 
            try {
                val sink = Class.forName(classPath) 
                .getConstructor(classOf [Properties], classOf[MetricRegistry],
                    classOf[SecurityManager]) 
                .newinstance(kv._2, registry, securityMgr) 
            if (kv._l == "servlet” ) {
                metricsServlet = Some(sink.asinstanceOf[MetricsServlet])
            } else {
                sinks += sink.asInstanceOf(Sink)
            }
            } catch {
                case e: Exception => logError("Sink class "+ classPath + " cannot
                    be instantialized", e)
            }
        }
    }
}

3.给Sinks增加Jetty的ServletContextHandler

为了能够在SparkUI(网页)访问到测量数据, 所以需要给Sinks增加Jetty的Servlet­ContextHandler,这里主要用到MetricsSystem的getServletHandlers方法实现如下:

def getServletHandlers = {
    require(running, "Can only call getServletHandlers on a running MetricsSystem")         
    metricsServlet.map(_.getHandlers).getOrElse(Array())
}

可以看到调用了metricsServlet的getHandlers, 其实现如下:

def getHandlers = Array [ServletContextHandler] ( 
    createServletHandler(servletPath,
        new ServletParams(request => getMetricsSnapshot(request), "text/json"),
            securityMgr)
)

最终生成处理metrics/json请求的ServletConlextHandler,而请求的真正处理由get­MetricsSnapshot方法,利用fastjson解析。生成的ServletContextHandler通过SparkUI的 attachHandler方法也被绑定到SparkUI。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值