如何在单个Apache Spark应用内限制每个作业的核心数?
单个Spark应用内作业资源限制的可行方案
1. 利用Fair Scheduler配置资源池
Spark的Fair调度器支持将资源划分到不同调度池,每个池可配置资源占比、最小保障资源和最大并发任务数,完美匹配你的需求:
第一步:创建调度池配置文件
编写fairscheduler.xml,定义两个资源池,确保每个池最多占用50核资源:<?xml version="1.0"?> <allocations> <pool name="job-pool-1"> <schedulingMode>FAIR</schedulingMode> <weight>1</weight> <minShare>50</minShare> <maxConcurrency>50</maxConcurrency> </pool> <pool name="job-pool-2"> <schedulingMode>FAIR</schedulingMode> <weight>1</weight> <minShare>50</minShare> <maxConcurrency>50</maxConcurrency> </pool> </allocations>weight=1:两个池资源分配比例相等,总核100时各占50;minShare=50:保证每个池至少能拿到50核资源;maxConcurrency=50:限制作业最多同时运行50个任务(默认每个任务占1核,刚好对应50核)。
第二步:配置Spark应用启用Fair调度器
在SparkConf中指定调度模式和配置文件路径:val sparkConf = new SparkConf() .setAppName("MultiJobParallelApp") .set("spark.scheduler.mode", "FAIR") .set("spark.scheduler.allocation.file", "/your/local/path/fairscheduler.xml") val spark = SparkSession.builder().config(sparkConf).getOrCreate()第三步:为每个作业绑定调度池
在启动作业的独立线程中,设置当前线程的调度池属性,作业会自动分配到对应池执行:// 作业1线程 new Thread(() => { spark.sparkContext.setLocalProperty("spark.scheduler.pool", "job-pool-1") // 执行作业1的action操作 df1.write.parquet("/path/to/job1/output") }).start() // 作业2线程 new Thread(() => { spark.sparkContext.setLocalProperty("spark.scheduler.pool", "job-pool-2") // 执行作业2的action操作 df2.write.parquet("/path/to/job2/output") }).start()这种方式下,两个作业会并行运行各占50核,同时分区数可保持合理数量(大于50),调度池会自动控制任务并发数,既不会让单个作业占用过多资源,也能充分利用空闲资源。
2. 任务CPU占比调整(可选补充)
如果你的任务本身需要占用多个CPU核心,可通过spark.task.cpus参数调整单个任务的CPU数,结合调度池的maxConcurrency控制总核数。比如每个任务占2核,将maxConcurrency设为25,就能保证作业最多占用50核。
总结
优先采用Fair调度器的资源池方案,无需拆分多个Spark应用,也不用强行限制分区数,既能满足每个作业的资源上限,又能保证整体资源利用率。自定义调度器复杂度极高,一般无需考虑。
内容的提问来源于stack exchange,提问作者Thow
相关产品推荐
相关产品推荐

