覆盖Databricks依赖性

时间:2019-12-19 14:10:04

标签: maven databricks azure-databricks

在我们的项目中,我们使用版本1.3.4中的com.typesafe:config。根据最新的release notes,该依赖性已经由Databricks在群集上提供,但是在非常旧的版本(1.2.1)中。 如何用我们自己的版本覆盖提供的依赖项?

我们使用maven,因为我有依赖关系

<dependency>
    <groupId>com.typesafe</groupId>
    <artifactId>config</artifactId>
    <version>1.3.4</version>
</dependency>

因此,我们创建的jar文件应包含较新的版本。

我通过上传jar文件创建了一个Job。作业失败,因为它找不到在1.2.1版之后添加的方法,因此看来我们提供的库被群集上的较早版本覆盖了。

3 个答案:

答案 0 :(得分:3)

最后,我们通过对相关类进行着色来解决此问题,方法是在build.sbt中添加以下内容

assemblyShadeRules in assembly := Seq(
  ShadeRule.rename("com.typesafe.config.**" -> "shadedSparkConfigForSpark.@1").inAll
)

答案 1 :(得分:3)

我们最终通过使用Sparks ChildFirstURLClassLoader解决了该问题。该项目是开源的,因此您可以自己here和方法here进行检查。

但是作为参考,这里是完整的方法。您需要提供一个Seq的jar,要用自己的jar覆盖,在我们的情况下,这是类型安全配置。

def getChildFirstClassLoader(jars: Seq[String]): ChildFirstURLClassLoader = {
  val initialLoader = getClass.getClassLoader.asInstanceOf[URLClassLoader]

  @tailrec
  def collectUrls(clazz: ClassLoader, acc: Map[String, URL]): Map[String, URL] = {

    val urlsAcc: Map[String, URL] = acc++
      // add urls on this level to accumulator
      clazz.asInstanceOf[URLClassLoader].getURLs
      .map( url => (url.getFile.split(Environment.defaultPathSeparator).last, url))
      .filter{ case (name, url) => jars.contains(name)}
      .toMap

    // check if any jars without URL are left
    val jarMissing = jars.exists(jar => urlsAcc.get(jar).isEmpty)
    // return accumulated if there is no parent left or no jars are missing anymore
    if (clazz.getParent == null || !jarMissing) urlsAcc else collectUrls(clazz.getParent, urlsAcc)
  }

  // search classpath hierarchy until all jars are found or we have reached the top
  val urlsMap = collectUrls(initialLoader, Map())

  // check if everything found
  val jarsNotFound = jars.filter( jar => urlsMap.get(jar).isEmpty)
  if (jarsNotFound.nonEmpty) {
    logger.info(s"""available jars are ${initialLoader.getURLs.mkString(", ")} (not including parent classpaths)""")
    throw ConfigurationException(s"""jars ${jarsNotFound.mkString(", ")} not found in parent class loaders classpath. Cannot initialize ChildFirstURLClassLoader.""")
  }
  // create child-first classloader
  new ChildFirstURLClassLoader(urlsMap.values.toArray, initialLoader)
}

如您所见,如果您指定的jar文件在类路径中不存在,它也有一些中止逻辑。

答案 2 :(得分:0)

Databricks支持初始化脚本(集群作用域或全局作用域),以便您可以安装/删除任何依赖项。详细信息在https://docs.databricks.com/clusters/init-scripts.html

在初始化脚本中,您可以删除位于databricks驱动程序/执行程序类路径/databricks/jars/上的默认jar文件,并在其中添加预期的jar文件。

相关问题