我有一个在Mesos集群中运行的Spark 2.1.1作业。 Spark UI显示32个活动执行程序,RDD.getNumPartitions显示28个分区。 但只有一个(随机)执行者正在做任何工作,其他所有执行者都被标记为已完成。 我将调试语句添加到执行程序代码(stdout),只有一个执行程序显示这些。整个管道的结构如下: 获取ids列表 - >下载每个id的JSON数据 - >解析JSON数据 - >保存到S3。
stage 1: val ids=session.sparkContext.textFile(path).repartition(28) -> RDD[String]
//ids.getNumPartitions shows 28
stage 2: val json=ids.mapPartitions { keys =>
val urlBuilder ...
val buffer ....
keys map { key =>
val url=urlBuilder.createUrl(id) //java.net.URL
val json=url.openStream() ... //download text to buffer, close stream
(id,json.toString)
}
} -> RDD[Tuple2[String,String]]
stage 3: val output = json flatMap { t =>
val values = ... //parse JSON, get values from JSON or empty sequence if not found
values map { value => (t._1, value) }
} -> RDD[Tuple2[String,String]]
stage 4: output.saveAsTextFile("s3://...")
这些是Spark二进制文件的配置设置: --driver-memory 32g --conf spark.driver.cores = 4 --executor-memory 4g --conf spark.cores.max = 128 --conf spark.executor.cores = 4
仅在一个执行程序上运行的阶段是第二个。 我在第一步中明确指定了分区数(repartition(28))。 有没有人见过这样的行为? 谢谢,
中号
解
我走了另一条路(看Travis的建议)并将分区数量(在步骤1之后)增加到100.这样就可以了,工作在几分钟内完成。但是有副作用 - 现在我在S3中有100个部分文件。
答案 0 :(得分:0)
确保在“获取ID列表”后发生.repartition()
阶段。
听起来你首先生成一个包含28个分区的空集,然后将id列表放到一个分区中。
提供示例代码后编辑:
每项任务是否可能快速完成(即在几秒钟内)?我已经看到,当任务在短时间内完成时,即使有数千个未完成的任务,也不会将任务计划到空闲执行程序。如果是这种情况,您可能需要更少的分区来使每个任务花费更长的时间。有时,这足以触发任务调度程序将更多任务安排到空闲执行程序。