这个问题旨在通过询问一个";出乎意料的";(对我来说(问题:
我已经将两个独立的scala代码库打包到两个不同的uber jar中。我将它们打包为uber jar,因为它们应该在同一台机器上运行,但它们之间存在冲突的依赖关系。
我期待什么每个uber jar只从自身解决依赖关系,因此没有冲突,没有着色问题等。
发生了什么相互冲突的依赖关系。其中一个uber jar试图指向第二个uber jar中存在的依赖项的另一个版本。
我希望jar总是试图解决对最近类路径的依赖关系(也许我在这里混合了一些术语(;环顾四周";。我有一个天真的期望,并将高度赞赏一个明确的解释(和/或学习资源(。
详细信息:
- uber罐子使用sbt组装进行包装:
addSbtPlugin("com.eed3si9n" % "sbt-assembly" % "1.0.0")
- ,具有以下选项:
assembly / assemblyOption ~= {
_.withIncludeScala(false)
}
assembly / assemblyMergeStrategy := {
case "META-INF/services/org.apache.spark.sql.sources.DataSourceRegister" => MergeStrategy.concat
case "META-INF/services/com.fasterxml.jackson.databind.Module" => MergeStrategy.concat
case "META-INF/services/com.fasterxml.jackson.core.JsonFactory" => MergeStrategy.concat
case "META-INF/services/com.fasterxml.jackson.core.ObjectCodec" => MergeStrategy.concat
case "META-INF/services/org.apache.spark.deploy.history.EventFilterBuilder" => MergeStrategy.concat
case "META-INF/services/org.glassfish.jersey.internal.spi.AutoDiscoverable" => MergeStrategy.concat
case PathList("org", "apache", "spark", "unused", xs@_*) => MergeStrategy.discard
case "UnusedStubClass.class" => MergeStrategy.discard
case "module-info.class" => MergeStrategy.rename
case "META-INF/MANIFEST.MF" => MergeStrategy.discard
case PathList(ps@_*) if ps.last contains "NOTICE" => MergeStrategy.discard
case PathList(ps@_*) if ps.last contains "LICENSE" => MergeStrategy.discard
case PathList(ps@_*) if ps.last contains "pom.properties" => MergeStrategy.discard
case PathList(ps@_*) if ps.last contains "pom.xml" => MergeStrategy.discard
case PathList(ps@_*) if ps.last contains "git.properties" => MergeStrategy.discard
case PathList(ps@_*) if ps.last contains "io.netty.versions.properties" => MergeStrategy.discard
case PathList(ps@_*) if ps.last contains "DUMMY.SF" => MergeStrategy.discard
case PathList(ps@_*) if ps.last contains "DUMMY.DSA" => MergeStrategy.discard
case "META-INF/DEPENDENCIES" => MergeStrategy.discard
case x => MergeStrategy.deduplicate
}
这两个uber jar是在同一集群中相继运行的火花作业。
当我在同一个集群中运行它们时,uber-jar2因冲突而失败。当我在不同的集群中运行时,两者都运行得非常好。
.class
文件和应用程序资源的目录的ZIP。
Uber JAR只是将您的所有依赖项(其他JAR-提取、编译输出(放在一个单独的归档中,这样无论使用它们,都不必获取其他JAR。
如果您构建了两个具有相同依赖关系的不同版本的Uber JAR,那么当您尝试在同一个ClassLoader中同时加载它们时,它将出现问题,因为同一类将有两个.class文件。
因此,如果您总是打算为同一个集群进行部署,只需将它们捆绑在一起即可。如果你想单独部署它们,那么不构建2个uberjar会更容易,因为依赖关系会重叠。例如,您可以构建2个依赖项的unerjar,并使代码依赖于它(然后在类路径上有2个JAR(,或者使用任何其他避免冲突的策略。