spark源码学习(七);task任务的提交分析

                              spark入门学(七)task任务的提交分析



           spark虽然在计算速度上比hadoop要强势很多,但是这两个框架在底层的数据流都要经过shuffle。由此,shuffle把spark的job分成两个阶段,一个叫做shuffleMaptask,另外一个是resultTask。前者主要是把运算所得的数据结果写到指定的位置,后者是从对应的位置读取数据然后再把运行的结果提交给客户端,为了详细,我们看看官方的源码介绍。
     shufflemaptask
A ShuffleMapTask divides the elements of an RDD into multiple buckets (based on a partitioner
* specified in the ShuffleDependency

       resulttask
A task that sends back the output to the driver application.

              那么问题是,这些任务到底是怎样提交的呢?我们知道task的最终运行时在executor中运行的。再standalone模式下,executor和driver的通信只要是依靠CoarseGrained-ExecutorBackend来维护的,他继承于ExecutorBackend这个特质,ExecutorBackend这个类的说明如下,也就是driver和executor交互的接口,executor在接受任务和执行完任务都要进行状态的更新,就是实现了statusUpdate这个方法。
A pluggable interface used by the Executor to send updates to the cluster scheduler.

          在CoarseGrained-ExecutorBackend的onstart方法实现如下;我们会看到和driver互动的信息。
override def onStart() {
    logInfo("Connecting to driver: " + driverUrl)
    ......
      ref.ask[RegisteredExecutor.type](//向driver发送注册命令
        RegisterExecutor(executorId, self, hostPort, cores, extractLogUrls))
    }(ThreadUtils.sameThread).onComplete {
      case Success(msg) => 
      case Failure(e) => 

          另外还要注意onstart方法中的信息,new executor和launchtask函数
override def receive: PartialFunction[Any, Unit] = {
    case RegisteredExecutor =>
      logInfo("Successfully registered with driver")
      val (hostname, _) = Utils.parseHostPort(hostPort)
	  //最关键的代码信息,只有在driver回复注册信息成功之后,才会开始创建executor
      executor = new Executor(executorId, hostname, env, userClassPath, isLocal = false)
    // 从driver收到的回复信息
    case RegisterExecutorFailed(message) =>
    case LaunchTask(data) =>
    case KillTask(taskId, _, interruptThread) =>
    <span style="white-space:pre">	</span>executor.launchTask(this, taskId = taskDesc.taskId, attemptNumber = taskDesc.attemptNumber,
          taskDesc.name, taskDesc.serializedTask)          
    case StopExecutor =>
 }
          我们进入launchtask函数,他是属于task的函数进入task。launchtask函数看看;其中创造一个taskrunner类。我们可以认为taskrunner是在executor中负责任务的运行的。之后把tr放到runningtask集合中,继而在线程池中运行任务

        
           那就进去taskrunner去看看吧,他也是executor的一个内部类嘛。taskrunner是一个进程类,实现了runnable接口,这个时候当然要去看看它里面的run函数啦,对吧。


        下面进入run函数,有些地方进行的缩减
 override def run(): Unit = {
      
      logInfo(s"Running $taskName (TID $taskId)")//开始运行task
      execBackend.statusUpdate(taskId, TaskState.RUNNING, EMPTY_BYTE_BUFFER)//状态的更新为running
	  updateDependencies(taskFiles, taskJars)//下载任务所需的文件和jar包
      try {
        ...各种反序列化
        logDebug("Task " + taskId + "'s epoch is " + task.epoch)
        env.mapOutputTracker.updateEpoch(task.epoch)//主要是更新次数和清除由于失败map任务产生的mapstatus
        //最核心的地方,看看,task.run终于为运行任务啦
        val value = try {
          task.run(taskAttemptId = taskId, attemptNumber = attemptNumber)
        } 
 
     
          进入这里的task.run方法,就会进入task.scala类中,哈哈,看看这里的run方法,最重要的就是其中runtask函数,runtask函数是一个被子类实现的函数,例如在shufflemaptask和resulttask中都有自己的实现。前者是先把数据划分到不同的bucket种,然后是写数据到指定的文件中去。后者读特定文件取数据之后把执行的结果提交给driver端。具体的如下图所示,分别是两种任务的runtask函数;

 


         仔细的话,你会看到rdd.iterator这两个迭代器,他是什么呢?iterator主要就是在对rdd的每个partition上没别执行任务,一个partition对应一个task嘛。具体的就来看看源码;


           细心的话,你会看到有两个特别特别重要的方法,getorcompute函数和computeorreadcheckpoint函数。第一个函数getorcompute就是在没有定义存级别的时候我们去重新计算,定义的话就直接get啦。computeorreadcheckpoint就是再有checkpoint的时候直接读取,否则执行compute函数。具体如下;



         getorcompute函数在get的时候,从远程和本地得到blockid,然后再判断是否得到了 blockResult还是non。没有得到partition的话就去用上面的那个函数进行运算。


        上面的这些也就仅仅谈到了task提交的大致运行过程,其中我们也就是了解基本的框架,要是层层递归,的确有些麻烦。说了这么多,来看看一副图片吧,就可以包含上面的一切:

             上面还有和shuffle数据的写入和读取等一些细节的分析,下次再具体分析。


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: Spark submit任务提交是指将用户编写的Spark应用程序提交到集群中运行的过程。在Spark中,用户可以通过命令行工具或API方式提交任务Spark submit命令的基本语法如下: ``` ./bin/spark-submit \ --class <main-class> \ --master <master-url> \ --deploy-mode <deploy-mode> \ --conf <key>=<value> \ <application-jar> \ [application-arguments] ``` 其中,`--class`指定应用程序的主类,`--master`指定集群的URL,`--deploy-mode`指定应用程序的部署模式,`--conf`指定应用程序的配置参数,`<application-jar>`指定应用程序的jar包路径,`[application-arguments]`指定应用程序的命令行参数。 在Spark中,任务提交的过程主要包括以下几个步骤: 1. 创建SparkConf对象,设置应用程序的配置参数; 2. 创建SparkContext对象,连接到集群; 3. 加载应用程序的主类; 4. 运行应用程序的main方法; 5. 关闭SparkContext对象,释放资源。 在任务提交的过程中,Spark会自动将应用程序的jar包和依赖的库文件上传到集群中,并在集群中启动Executor进程来执行任务任务执行完成后,Spark会将结果返回给Driver进程,并将Executor进程关闭。 总之,Spark submit任务提交Spark应用程序运行的关键步骤,掌握任务提交的原理和方法对于开发和调试Spark应用程序非常重要。 ### 回答2: Spark 作为一款强大的分布式计算框架,提供了很多提交任务的方式,其中最常用的方法就是通过 spark-submit 命令来提交任务spark-submit 是 Spark 提供的一个命令行工具,用于在集群上提交 Spark 应用程序,并在集群上运行。 spark-submit 命令的语法如下: ``` ./bin/spark-submit [options] <app jar | python file> [app arguments] ``` 其中,[options] 为可选的参数,包括了执行模式、执行资源等等,<app jar | python file> 为提交的应用程序的文件路径,[app arguments] 为应用程序运行时的参数。 spark-submit 命令会将应用程序的 jar 文件以及所有的依赖打包成一个 zip 文件,然后将 zip 文件提交到集群上运行。在运行时,Spark 会根据指定的主类(或者 Python 脚本文件)启动应用程序。 在提交任务时,可以通过设置一些参数来控制提交任务的方式。例如: ``` --master:指定该任务运行的模式,默认为 local 模式,可设置为 Spark Standalone、YARN、Mesos、Kubernetes 等模式。 --deploy-mode:指定该任务的部署模式,默认为 client,表示该应用程序会在提交任务的机器上运行,可设置为 cluster,表示该应用程序会在集群中一台节点上运行。 --num-executors:指定该任务需要的 executor 数量,每个 executor 会占用一个计算节点,因此需要根据集群配置与任务要求确定该参数的值。 --executor-memory:指定每个 executor 可用的内存量,默认为 1g,可以适当调整该值以达到更好的任务运行效果。 ``` 此外,还有一些参数可以用来指定应用程序运行时需要传递的参数: ``` --conf:指定应用程序运行时需要的一些配置参数,比如 input 文件路径等。 --class:指定要运行的类名或 Python 脚本文件名。 --jars:指定需要使用的 Jar 包文件路径。 --py-files:指定要打包的 python 脚本,通常用于将依赖的 python 包打包成 zip 文件上传。 ``` 总之,spark-submit 是 Spark 提交任务最常用的方法之一,通过该命令能够方便地将应用程序提交到集群上运行。在提交任务时,需要根据实际场景调整一些参数,以达到更好的任务运行效果。 ### 回答3: Spark是一个高效的分布式计算框架,其中比较重要的组成部分就是任务提交。在Spark中,任务提交主要通过spark-submit来实现。本文将从两方面,即任务提交之前的准备工作和任务提交过程中的细节进行探讨。 一、任务提交之前的准备工作 1.环境配置 在执行任务提交前,需要确保所在的计算机环境已经配置好了SparkSpark的环境配置主要包括JAVA环境、Spark的二进制包、PATH路径配置、SPARK_HOME环境变量配置等。 2.编写代码 Spark任务提交是基于代码的,因此在任务提交前,需要编写好自己的代码,并上传到集群中的某个路径下,以便后续提交任务时调用。 3.参数设置 在任务提交时,需要对一些关键的参数进行设置。例如,任务名、任务对应的代码路径、任务需要的资源、任务需要的worker节点等。 二、任务提交过程中的细节 1.启动Driver 当使用spark-submit命令提交任务时,Spark会启动一个Driver来运行用户的代码。这个Driver通常需要连接到Spark集群来执行任务。 2.上传文件 Spark支持在任务提交时上传所需的文件。这些文件可以用于设置Spark的环境变量、为任务提供数据源等。 3.资源需求 Spark任务执行依赖于一定的资源。每个任务可以指定自己的资源需求,例如需要多少内存、需要多少CPU等。这些资源需求通常与提交任务时需要的worker节点数量有关系。 4.监控和日志 在任务执行的过程中,Spark会收集任务的监控数据和日志信息。这些数据可用于后续的调试和性能优化。 总之,在Spark任务提交过程中,需要充分考虑任务的资源需求和监控日志信息的收集,以便更好地完成任务和优化Spark运行效率。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值