spark jobserver设计[3]--状态监控

      jobserver在运行用户的作业时,需要提供相关的监控信息给用户,包括作业运行进度、各个阶段的运行诊断、节点的信息等。

      一 日志展示

      spark执行任务时按照宽窄依赖将任务划分为不同的stage,每个stage包含多个task,在此以stage和task的完成情况展示任务执行进度。spark提供了SparkListener抽象类,通过继承该类并且实现相关的抽象方法即可获取相关的执行信息。SparkListener的定义如下:

abstract class SparkListener extends SparkListenerInterface {
  override def onStageCompleted(stageCompleted: SparkListenerStageCompleted): Unit = { }

  override def onStageSubmitted(stageSubmitted: SparkListenerStageSubmitted): Unit = { }

  override def onTaskStart(taskStart: SparkListenerTaskStart): Unit = { }

  override def onTaskGettingResult(taskGettingResult: SparkListenerTaskGettingResult): Unit = { }

  override def onTaskEnd(taskEnd: SparkListenerTaskEnd): Unit = { }

  override def onJobStart(jobStart: SparkListenerJobStart): Unit = { }

  override def onJobEnd(jobEnd: SparkListenerJobEnd): Unit = { }

  override def onEnvironmentUpdate(environmentUpdate: SparkListenerEnvironmentUpdate): Unit = { }

  override def onBlockManagerAdded(blockManagerAdded: SparkListenerBlockManagerAdded): Unit = { }

  override def onBlockManagerRemoved(
      blockManagerRemoved: SparkListenerBlockManagerRemoved): Unit = { }

  override def onUnpersistRDD(unpersistRDD: SparkListenerUnpersistRDD): Unit = { }

  override def onApplicationStart(applicationStart: SparkListenerApplicationStart): Unit = { }

  override def onApplicationEnd(applicationEnd: SparkListenerApplicationEnd): Unit = { }

  override def onExecutorMetricsUpdate(
      executorMetricsUpdate: SparkListenerExecutorMetricsUpdate): Unit = { }

  override def onExecutorAdded(executorAdded: SparkListenerExecutorAdded): Unit = { }

  override def onExecutorRemoved(executorRemoved: SparkListenerExecutorRemoved): Unit = { }

  override def onExecutorBlacklisted(
      executorBlacklisted: SparkListenerExecutorBlacklisted): Unit = { }

  override def onExecutorUnblacklisted(
      executorUnblacklisted: SparkListenerExecutorUnblacklisted): Unit = { }

  override def onNodeBlacklisted(
      nodeBlacklisted: SparkListenerNodeBlacklisted): Unit = { }

  override def onNodeUnblacklisted(
      nodeUnblacklisted: SparkListenerNodeUnblacklisted): Unit = { }

  override def onBlockUpdated(blockUpdated: SparkListenerBlockUpdated): Unit = { }

  override def onOtherEvent(event: SparkListenerEvent): Unit = { }
}

      通过该类的定义可以看见,类中的很多方法都是对spark执行状态的监听,包括onStageSubmitted、onStageCompleted、

onTaskStart、onTaskEnd等,实现这些方法,可以在stage和task完成时得到通知,用户得到的日志格式如下:


      每个stage包含多个task,通过task的完成情况实时展现作业完成进度。

      二 作业诊断

      sparkListener提供了对stage和task的细粒度监控,应用程序可以获取到每个task的执行时间、输入数据大小、shuffle数据大小等,基于这些信息可以对stage的执行情况进行诊断,包括是否存在数据倾斜的情况、是否存在长尾task情况等。前端的UI汇总了各个stage的信息已经诊断信息等,如下图所示:



      三  executor信息获取

      由于executor是启在其它节点上,在driver端不能直接获取到相关信息,在此利用spark的metrics机制实现对executor所在节点的监控。spark metrics系统支持Sink和Source两种,其中Sink指定metrics信息发送到哪里,一个instance可以设置多个Sink,而Source指定信息的来源,这里采用JvmSource,它收集低级别的状态信息。

      自定义的Sink信息如下:

class JobServerSink(val property: Properties, val registry: MetricRegistry,
                    securityMgr: SecurityManager) extends Sink{

    val SERVER_KEY_PERIOD = "period"
    val SERVER_KEY_UNIT = "unit"
    val SERVER_KEY_URL = "url"

    val SERVER_DEFAULT_PERIOD = 10
    val SERVER_DEFAULT_UNIT = "SECONDS"
    val SERVER_DEFAULT_URL = "http://localhost:7002"

    val pollPeriod = Option(property.getProperty(SERVER_KEY_PERIOD)) match {
        case Some(s) => s.toInt
        case None => SERVER_DEFAULT_PERIOD
    }

    val pollUnit: TimeUnit = Option(property.getProperty(SERVER_KEY_UNIT)) match {
        case Some(s) => TimeUnit.valueOf(s.toUpperCase(Locale.ROOT))
        case None => TimeUnit.valueOf(SERVER_DEFAULT_UNIT)
    }

    MetricsSystem.checkMinimalPollingPeriod(pollUnit, pollPeriod)

    val pollURL = Option(property.getProperty(SERVER_KEY_URL)) match {
        case Some(s) => s
        case None => SERVER_DEFAULT_URL
    }

    val reporter = JobServerReport.forRegistry(registry)
        .convertDurationsTo(TimeUnit.MILLISECONDS)
        .convertRatesTo(TimeUnit.SECONDS).build(pollURL)

    override def start(): Unit = reporter.start(pollPeriod, pollUnit)

    override def stop(): Unit = reporter.stop()

    override def report(): Unit = reporter.report()

}
      其中JobServerReport类继承自ScheduledReporter类,在其report方法中可以采集executor的相关信息,包括jvm堆使用情况、线程堆栈,同时基于Sigar采集当前节点的信息,包括cpu使用率、内存使用情况、网络IO、磁盘IO等,采集的信息统一发送到driver端进行显示。

       为了使得配置生效,新建一个metrics.properties文件,内容如下:

executor.sink.server.class=org.apache.spark.metrics.sink.JobServerSink
executor.sink.server.period=5     //采集周期
executor.sink.server.unit=seconds //采集周期单位 秒
executor.sink.server.url = http://192.168.6.52:7002 //发送的driver地址

executor.source.jvm.class=org.apache.spark.metrics.source.JvmSource

      提交spark-submit时,添加参数--conf spark.metrics.conf=/home/admin/metrics.properties。这里的spark.metrics.conf指定的配置文件必须在本地,也就意味着必须把该文件拷贝到每个节点上,为了避免操作的繁琐,首先将配置文件拷贝到HDFS上,通过aspect拦截MetricsConfig的initialize方法,在加载该配置时,先从HDFS上下载到本地,再加载该文件。

      采集到的节点信息展示在前端,如图所示:



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值