如何在 Apache Spark 中使用 TypeSafe 配置?

How to use TypeSafe config with Apache Spark?

我有一个 Spark 应用程序,我试图将其打包为一个胖 jar 并使用 spark-submit 部署到本地集群。我正在使用 Typesafe 配置为各种部署环境创建配置文件 - local.confstaging.confproduction.conf - 并尝试提交我的 jar。

我运行的命令如下:

/opt/spark-3.0.1-bin-hadoop2.7/bin/spark-submit \
--master spark://127.0.0.1:7077 \
--files ../files/local.conf \
--driver-java-options '-Dconfig.file=local.conf' \
target/scala-2.12/spark-starter-2.jar  

我通过一个接一个地添加选项逐步构建命令。使用 --files,日志显示文件正在上传到 Spark,但是当我添加 --driver-java-options 时,提交失败,找不到文件。

Caused by: java.io.FileNotFoundException: local.conf (No such file or directory)
        at java.base/java.io.FileInputStream.open0(Native Method)
        at java.base/java.io.FileInputStream.open(FileInputStream.java:219)
        at java.base/java.io.FileInputStream.<init>(FileInputStream.java:157)
        at com.typesafe.config.impl.Parseable$ParseableFile.reader(Parseable.java:629)
        at com.typesafe.config.impl.Parseable.reader(Parseable.java:99)
        at com.typesafe.config.impl.Parseable.rawParseValue(Parseable.java:233)
        at com.typesafe.config.impl.Parseable.parseValue(Parseable.java:180)
        ... 35 more

代码:

import com.example.spark.settings.Settings
import com.typesafe.config.ConfigFactory
import org.apache.spark.sql.SparkSession

object App extends App {
  val config = ConfigFactory.load()
  val settings = Settings(config = config)

  val spark = SparkSession
    .builder()
    .getOrCreate()

  spark.stop()
}

我需要更改什么才能单独提供配置文件?

根据Spark Docs--files放在每个executor的工作目录下。当您尝试从驱动程序而不是执行程序访问此文件时。

为了在驱动端加载配置,尝试这样的事情:

/opt/spark-3.0.1-bin-hadoop2.7/bin/spark-submit \
--master spark://127.0.0.1:7077 \
--driver-java-options '-Dconfig.file=../files/local.conf' \
target/scala-2.12/spark-starter-2.jar  

如果你想要在执行端加载配置,你需要使用spark.executor.extraJavaOptions 属性。在这种情况下,您需要在执行程序上运行的 lambda 中加载配置,例如 RDD API:


myRdd.map { row => 
  val config = ConfigFactory.load()
  ...
}

config 的可见性将限制在 lambda 的范围内。这是一个相当复杂的方法,我将在下面描述一个更好的选择。

我关于如何在 Spark 中使用自定义配置的一般建议:

  1. 阅读this chapter of Spark Docs
  2. 在驱动端加载配置
  3. 将您需要的设置映射到不可变大小写 class
  4. 通过闭包将这个案例class传递给执行者
  5. 请记住,带设置的案例 class 应该包含尽可能少的数据,任何字段类型都应该是原始的或实现的 java.io.Serializable

EMR 具体是很难访问驱动程序的文件系统。所以最好将配置存储在外部存储中,通常是 S3。

类型安全配置库无法直接从 S3 加载文件,因此您可以将路径作为应用参数传递给配置,而不是 -D属性,使用 [=16] 从 S3 读取它=] 然后使用 ConfigFactory.parseString() 将其加载为配置。以 this answer 为例。