在运行Spark Streaming程序时,有时我们需要并行化任务的执行。比如任务A需要每隔5s输出计算结果,任务B用到了时间窗口,每隔1hour计算一次并输出结果。如果全部串行运行的话,在运行任务B时,任务A就会被阻塞。可能B的执行需要3分钟,那这三分钟内A的计算结果就不能被实时看到了。在Spark程序内部(即每个Application中),任务是可以并行运行的。这个官网上有比较详细的介绍。但是Spark Streaming中,并行运行任务和上面官网中介绍的有些区别。
Scheduler Mode
首先,运行模式依然要设置为fair,这是必须的。但是Spark Streaming还有一个专用的参数用来设置可以并行的任务数:spark.streaming.concurrentJobs。这个参数的意思是可以同时运行多少任务,默认是1。如果我们需要同时运行1个以上的任务,就要把这个值调高。所以,如果我想并行运行A和B两个任务,就要这样配置:
val conf: SparkConf = new SparkConf().setAppName("parallel")
conf.set("spark.scheduler.mode","FAIR")
conf.set("spark.streaming.concurrentJobs","2")
把spark.streaming.concurrentJobs设置为2,就可以同时运行两个任务了。
Fair Scheduler Pools
虽然调整了可并行运行任务的数量,可是默认情况下,所有的任务都是以同样的权重运行的。如果我们去看Spark的WEB UI界面,会在Stage标签内看到default pool,所有的任务都运行在默认的pool中。可是如何调整不同类型任务占用资源的权重呢?这个在上面官网链接中也有比较详细的介绍。可是在官网的介绍中,要求在不同的线程提交任务才可以,那么Spark Streaming如何在不同线程提交任务呢?
答案也很简单,Spark Streaming不同的Action之间本来就是多线程执行的。所以可以使用这种方式设置:
dstream.foreachRDD(rdd =>
rdd.sparkContext.setLocalProperty("spark.scheduler.pool","pool_a")
)
这样就可以使用不同的pool了。这时候在WEB UI界面的Stage标签中就可以看到不同的pool了。而pool的资源分配权重和pool内部的调用方式依然在 $SPARK_HOME/conf/fairscheduler.xml 中配置,详情请参考上面的官网链接。