首页 > 解决方案 > spark提交应用程序中的Scala ScriptEngine问题

问题描述

我正在开发一个让用户编写 DSLS 并在运行时将其作为我的 Type 实例加载的系统,这些可以应用于 RDD 之上。整个应用程序作为 spark-submit 应用程序运行,我使用 ScriptEngine 引擎编译用 Scala 本身编写的 DSL。每个测试在 SBT 和 IntelliJ 中都能正常工作。但是,在进行 spark-submit 时,我的 fat-jar 中可用的我自己的类型无法在 Script 中导入。我如下初始化脚本引擎。

val engine: ScriptEngine = new ScriptEngineManager().getEngineByName("scala")
private val settings: Settings = engine.asInstanceOf[scala.tools.nsc.interpreter.IMain].settings
settings.usejavacp.value = true

settings.embeddedDefaults[DummyClass]
private val loader: ClassLoader = Thread.currentThread().getContextClassLoader
settings.embeddedDefaults(loader)

这似乎是火花提交期间类加载器的问题。但是我无法弄清楚为什么我自己的 jar 中的类型也有 spark-submit 的主程序在我的脚本中不可用的原因,该脚本是在同一个 JVM 中创建的。scala scala-compiler、scala-reflect 和 scala-library 版本是 2.11.8。一些帮助将不胜感激。

标签: apache-sparkclassloaderspark-submitscriptenginescala-script

解决方案


我找到了一个可行的解决方案。通过代码和大量调试,我终于发现 ScriptEngine 通过使用用于创建它的 Classloader 的 Classpath 字符串为自己创建了一个 Classloader。在 spark-submit 的情况下,spark 创建一个特殊的类加载器,它可以从本地文件和 hdfs 文件中读取。但是从这个类加载器获得的类路径字符串不会包含我们在 HDFS 中存在的应用程序 jar。

通过在初始化之前手动将我的应用程序 jar 附加到 ScriptEngine 类路径,它解决了我的问题。为此,我必须先将 HDFS 中的应用程序 jar 本地下载到本地,然后再添加它。


推荐阅读