Spark任务的具体的启动通过rdd中的action来执行SparkContext中的runJob来对任务进行启动,一个action的动作就会生成一个job.如果rdd中没有现成可用的action来执行业务想要的操作时,可以直接使用这个runJob来进行自定义操作.
SparkContext中的runJob的定义:
def runJob[T, U: ClassTag](
rdd: RDD[T],
processPartition: Iterator[T] => U,
resultHandler: (Int, U) => Unit)
函数定义说明:
在函数定义的ClassTag的类型部分:T表示RDD中数据的类型,U表示这个JOB的返回数据类型
Rdd参数是表示要执行这个JOB的最后一个RDD的实例.
processPartition:这是一个用于在每个partition中执行数据集操作的函数,这个函数传入一个Iterator,返回的是一个U的类型的,这个返回的就是这个任务对应此task的返回值.
示例:(iter:Iterator[T]) => {
Val kv = iter.next
If kv._1 == 1
Return kv
}
resultHandler:这是对每个task(partition)的执行结果进行合并的操作函数,这个函数得到每个task的返回(在driver端),并根据结果进行相应的操作.这个函数传入参数为2个,第一个参数是task对应的partition的下标,第二个参数是这个partition的返回值.
示例:
Val results = new Array[U](rdd.partitions.length)
(index,result) => {
Results(index) = result
}
driver端的接收task结果的简单说明
在Driver端接收task的执行结果,根据action的不同,处理接收的内容可能也会不同,
下面根据不同的action来针对性分析driver如何接收数据.
Driver端接收到ResultTask的响应结果的数据主要是通过TASK中执行的最后一个RDD的function来决定的.所以不同的action,结果的响应到driver端也就会不相同.
在driver端,TaskResultGetter的实例中得到各个executor的结果的线程数通过spark.resultGetter.threads配置.默认为4个.
在TaskSchedulerImpl中根据生成的TaskResultGetter实例中的enqueueSuccessfulTask函数来进行处理.这个函数包含有两个重载,一个包含有TaskState的表示这是task执行失败时的调用.