我正在调查使用spark作为REST API后端的适用性。这个问题似乎是Spark的FIFO调度方法。这意味着如果正在执行大型任务,那么在完成繁重的任务之前,任何小任务都无法完成。根据{{3}},公平的调度程序应该解决这个问题。但是,我无法注意到这一切都在改变。我配置调度程序错了吗?
scheduler.xml:
<?xml version="1.0"?>
<allocations>
<pool name="test">
<schedulingMode>FAIR</schedulingMode>
<weight>1</weight>
<minShare>10</minShare>
</pool>
</allocations>
我的代码:
$ pyspark --conf spark.scheduler.mode=FAIR --conf spark.scheduler.allocation.file=/home/hadoop/scheduler.xml
>>> import threading
>>> sc.setLocalProperty("spark.scheduler.pool", "test")
>>> def heavy_spark_job():
# Do some heavy work
>>>
>>> def smaller_spark_job():
# Do something simple
>>>
>>> threading.Thread(target=heavy_spark_job).start()
>>> smaller_spark_job()
较小的火花作业只能在重火花作业的第一项任务不需要所有可用的CPU核心时启动。
答案 0 :(得分:0)
您只需要为您的任务设置一个不同的池:
默认情况下,每个池都获得群集的相等份额(也与默认池中的每个作业的份额相等),但在每个池中,作业以FIFO顺序运行。例如,如果您为每个用户创建一个池,则意味着每个用户将获得集群的平等份额,并且每个用户的查询将按顺序运行,而不是随后的查询从该用户的较早查询中获取资源。
https://spark.apache.org/docs/latest/job-scheduling.html#default-behavior-of-pools
此外,在PySpark中,子线程无法继承父线程的本地属性,您必须在线程目标函数内设置池。
答案 1 :(得分:0)
我相信,您已经正确地实施了公平调度。由于您没有将smaller_spark_job 作为线程运行,因此线程处理存在问题。因此,它首先等待 heavy_spark_job
完成。应该像下面这样。
threading.Thread(target=heavy_spark_job).start()
threading.Thread(target= smaller_spark_job).start()
此外,my post 可以帮助您从 Spark UI 验证 FAIR 调度。