热释光;医生:这是一份包含问题的回购协议。
cassandra和hdfs都在内部使用Guava,但由于各种原因,它们都没有掩盖这种依赖性。因为Guava的版本不是二进制兼容的,我发现 NoSuchMethodError
在运行时停止。
我试着把Guava藏在我的房间里 build.sbt
:
val HadoopVersion = "2.6.0-cdh5.11.0"
// ...
val hadoopHdfs = "org.apache.hadoop" % "hadoop-hdfs" % HadoopVersion
val hadoopCommon = "org.apache.hadoop" % "hadoop-common" % HadoopVersion
val hadoopHdfsTest = "org.apache.hadoop" % "hadoop-hdfs" % HadoopVersion % "test" classifier "tests"
val hadoopCommonTest = "org.apache.hadoop" % "hadoop-common" % HadoopVersion % "test" classifier "tests"
val hadoopMiniDFSCluster = "org.apache.hadoop" % "hadoop-minicluster" % HadoopVersion % Test
// ...
assemblyShadeRules in assembly := Seq(
ShadeRule.rename("com.google.common.**" -> "shade.com.google.common.@1").inLibrary(hadoopHdfs).inProject,
ShadeRule.rename("com.google.common.**" -> "shade.com.google.common.@1").inLibrary(hadoopCommon).inProject,
ShadeRule.rename("com.google.common.**" -> "shade.com.google.common.@1").inLibrary(hadoopHdfsTest).inProject,
ShadeRule.rename("com.google.common.**" -> "shade.com.google.common.@1").inLibrary(hadoopCommonTest).inProject,
ShadeRule.rename("com.google.common.**" -> "shade.com.google.common.@1").inLibrary(hadoopMiniDFSCluster).inProject
)
assemblyJarName in assembly := s"${name.value}-${version.value}.jar"
assemblyMergeStrategy in assembly := {
case PathList("META-INF", "MANIFEST.MF") => MergeStrategy.discard
case _ => MergeStrategy.first
}
但是运行时异常仍然存在(哈——这是Cassandra的玩笑,各位)。
具体的例外是
[info] HdfsEntitySpec***ABORTED***
[info] java.lang.NoSuchMethodError: com.google.common.base.Objects.toStringHelper(Ljava/lang/Object;)Lcom/google/common/base/Objects$ToStringHelper;
[info] at org.apache.hadoop.metrics2.lib.MetricsRegistry.toString(MetricsRegistry.java:406)
[info] at java.lang.String.valueOf(String.java:2994)
[info] at java.lang.StringBuilder.append(StringBuilder.java:131)
[info] at org.apache.hadoop.ipc.metrics.RetryCacheMetrics.<init>(RetryCacheMetrics.java:46)
[info] at org.apache.hadoop.ipc.metrics.RetryCacheMetrics.create(RetryCacheMetrics.java:53)
[info] at org.apache.hadoop.ipc.RetryCache.<init>(RetryCache.java:202)
[info] at org.apache.hadoop.hdfs.server.namenode.FSNamesystem.initRetryCache(FSNamesystem.java:1038)
[info] at org.apache.hadoop.hdfs.server.namenode.FSNamesystem.<init>(FSNamesystem.java:949)
[info] at org.apache.hadoop.hdfs.server.namenode.FSNamesystem.<init>(FSNamesystem.java:796)
[info] at org.apache.hadoop.hdfs.server.namenode.NameNode.format(NameNode.java:1040)
[info] ...
如何正确着色Guava以停止运行时错误?
1条答案
按热度按时间mqkwyuun1#
着色规则仅在构建胖jar时适用。它不会在其他sbt任务中应用。
如果您想对hadoop依赖项中的某个库进行着色处理,可以创建一个只包含hadoop依赖项的新项目,对库进行着色处理,并发布一个包含所有着色hadoop依赖项的胖jar。
这并不是一个完美的解决方案,因为新hadoopjar中的所有依赖项对于谁使用它们都是“未知”的,您需要手动处理冲突。
这是您在应用程序中需要的代码
build.sbt
要发布一个胖hadoop jar(使用您的代码和sbt程序集文档):我没有测试过,但这就是它的要点。
我想指出我注意到的另一个问题,您的合并策略可能会给您带来问题,因为您希望对某些文件应用不同的策略。请参见此处的默认策略。
我建议使用这样的方法来保留原来的策略
deduplicate
```assemblyMergeStrategy in assembly := {
entry: String => {
val strategy = (assemblyMergeStrategy in assembly).value(entry)
if (strategy == MergeStrategy.deduplicate) MergeStrategy.first
else strategy
}
}