[英]How to pass configuration from driver to executors in Spark?
例如。
object App {
var confValue: String = ""
def main(args: Array[String]): Unit = {
// set conf by cmd args
confValue = args.head
// do some context init
val dataset: Dataset[Int] = ???
dataset.foreach { row =>
// get conf from executor
println(confValue)
}
}
}
我想在 executors 上获取 conf,但实际上它无法完成,因为confValue
仅在驱动程序上进行了修改
我知道我可以通过像这样的局部变量将confValue
传递给执行程序。
def main(args: Array[String]): Unit = {
// set conf by cmd args
val confValue = args[0]
// do some context init
val dataset: Dataset[Int] = ???
dataset.foreach { row =>
// get conf from executor
println(confValue)
}
}
但我的火花工作是巨大的。 它有这么多的功能。 我不能将 confValue 作为局部变量到处传递。 例如:
def main(args: Array[String]): Unit = {
// set conf by cmd args
val confValue = args[0]
// do some context init
val dataset: Dataset[Int] = ???
dataset.foreach { row =>
doSomeLogic(row)
}
}
private def doSomeLogic(row: Int): Unit = {
// get conf from executor
println(confValue)
}
有很多doSomeLogic
。 所以我不能将confValue
传递给他们所有人。 有没有办法自动将confValue
传递给每个执行者?
更新 1
我的火花代码可能如下所示
object App {
/** env flag, will be inited by cmd args, and be used in executors */
var env: String = ""
val spark: SparkSession = ???
import spark.implicits._
def main(args: Array[String]): Unit = {
// read env from args
env = args.head
var ds: Dataset[Int] = ???
ds = doLogic1(ds)
ds = doLogic2(ds)
doLogic3(ds)
}
private def doLogic1(ds: Dataset[Int]): Dataset[Int] = {
ds.map { row =>
// env will be used here
???
}
}
private def doLogic2(ds: Dataset[Int]): Dataset[Int] = {
ds.map { row =>
// env will be used here
???
}
}
private def doLogic3(ds: Dataset[Int]): Dataset[Int] = {
ds.map { row =>
// env will be used here
???
}
}
}
env
将在main
中初始化,并将在一些doLogicN
函数中使用。 我的 spark 项目是一个有很多doLogicN
函数的大型项目,因此将env
标志传递给每个doLogicN
function 会更改太多代码。
将env
标志传递给所有doLogicN
函数的最简单方法是什么?
最难的一点是env
会在executors中使用。 如果它只用于驱动程序,我可以通过全局env
变量将它传递到任何地方。 但它在执行程序中不能很好地工作,因为尚未初始化全局env
变量。 它只能在驱动程序端启动。
您可以执行以下操作将值广播给所有执行者,然后根据您的要求并可以根据需要使用它。 此外,如果您想并行处理每个分区的数据,您应该为每个分区使用,而不是使用 for each。
下面是如何广播一个值并使用它的示例代码:
//Sample data created
val df = Seq(("a","2020-01-16 08:55:50"),("b","2020-01-16 08:57:37"),("c","2020-01-16 09:00:13"),("d","2020-01-16 09:01:32"),("e","2020-01-16 09:03:32"),("f","2020-01-16 09:06:56")).toDF("ID","timestamp")
//check the partitions that a datframe has
df.rdd.partitions.size
//broadcast the value that you want to broadcast
val confValue = "Test"
val bdct_confvalue = spark.sparkContext.broadcast(confValue);
//using the broadcasted value on each executors nodes as required
df.foreachPartition(partition => {
println("Confvalue partition =" +bdct_confvalue.value)
}
)
此外,要查看日志中打印的值,您必须查看执行程序日志而不是驱动程序日志,因为您无法在驱动程序日志中看到此打印语句。 您也无法在 Jupyter 或 Databricks 笔记本等任何笔记本中看到这一点,因为它们会在 UI 上显示驱动程序日志。
我找到了解决我的问题的方法。
conf 可以在提交 spark 作业时由 Spark Conf 设置,例如spark.my.env=env_1
可以通过SparkEnv.get.conf.get("spark.my.env")
读取,在sparkContext
初始化后,在驱动程序和执行程序之间具有相同的效果。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.