2017-10-19 35 views
1

Toute tentative de créer un pot de graisse avec SBT donne une erreur comme ceci:Les classes recompilées depuis la source dans les fichiers Spark rompent la fusion de sbt?

java.lang.RuntimeException: deduplicate: different file contents found in the following: 
C:\Users\db\.ivy2\cache\org.apache.spark\spark-network-common_2.10\jars\spark-network-common_2.10-1.6.3.jar:com/google/common/base/Function.class 
C:\Users\db\.ivy2\cache\com.google.guava\guava\bundles\guava-14.0.1.jar:com/google/common/base/Function.class 

Il existe de nombreuses classes, c'est juste un pour le titre d'exemple. Goyave 14.0.1 est la version en jeu pour Function.class dans les deux pots:

[info] +-com.google.guava:guava:14.0.1 
... 
[info] | | +-com.google.guava:guava:14.0.1 

Cela signifie que SBT/lierre ne détectera pas un comme la nouvelle version, mais les tailles et les dates sont différentes dans les pots, ce qui conduit sans doute à l'erreur ci-dessus:

$ jar tvf /c/Users/db/.ivy2/cache/org.apache.spark/spark-network-common_2.10/jars/spark-network-common_2.10-1.6.3.jar | grep "com/google/common/base/Function.class" 
    549 Wed Nov 02 16:03:20 CDT 2016 com/google/common/base/Function.class 

$ jar tvf /c/Users/db/.ivy2/cache/com.google.guava/guava/bundles/guava-14.0.1.jar | grep "com/google/common/base/Function.class" 
    543 Thu Mar 14 19:56:52 CDT 2013 com/google/common/base/Function.class 

Il semble que Apache est recompiler Function.class de la source plutôt que d'inclure la classe comme initialement compilé. Est-ce que c'est une bonne compréhension de ce qui se passe ici? Maintenant, il est possible d'exclure les classes re-compilées en utilisant sbt, mais y a-t-il un moyen de construire le fichier jar sans exclure explicitement chaque fichier contenant une source recompilée par son nom? En excluant les pots conduit explicitement à quelque chose le long des lignes de l'extrait ci-dessous, ce qui fait croire que je vais descendre un mauvais chemin ici:

libraryDependencies += "org.apache.spark" %% "spark-core" % "1.6.3" 
    excludeAll(
    ExclusionRule(organization = "com.twitter"), 
    ExclusionRule(organization = "org.apache.spark", name = "spark-network-common_2.10"), 
    ExclusionRule(organization = "org.apache.hadoop", name = "hadoop-client"), 
    ExclusionRule(organization = "org.apache.hadoop", name = "hadoop-hdfs"), 
    ExclusionRule(organization = "org.tachyonproject", name = "tachyon-client"), 
    ExclusionRule(organization = "commons-beanutils", name = "commons-beanutils"), 
    ExclusionRule(organization = "commons-collections", name = "commons-collections"), 
    ExclusionRule(organization = "org.apache.hadoop", name = "hadoop-yarn-api"), 
    ExclusionRule(organization = "org.apache.hadoop", name = "hadoop-yarn-common"), 
    ExclusionRule(organization = "org.apache.curator", name = "curator-recipes") 
) 
, 
libraryDependencies += "org.apache.spark" %% "spark-network-common" % "1.6.3" exclude("com.google.guava", "guava"), 
libraryDependencies += "org.apache.spark" %% "spark-graphx" % "1.6.3", 
libraryDependencies += "com.typesafe.scala-logging" %% "scala-logging-slf4j" % "2.1.2", 
libraryDependencies += "org.apache.hadoop" % "hadoop-client" % "2.2.0" exclude("com.google.guava", "guava"), 
libraryDependencies += "com.google.guava" % "guava" % "14.0.1", 
libraryDependencies += "org.json4s" %% "json4s-native" % "3.2.11", 
libraryDependencies += "org.json4s" %% "json4s-ext" % "3.2.11", 
libraryDependencies += "com.rabbitmq" % "amqp-client" % "4.1.1", 
libraryDependencies += "commons-codec" % "commons-codec" % "1.10", 

Si c'est le mauvais chemin, ce qui est une façon plus propre?

Répondre

1

Si c'est le mauvais chemin, quoi de plus propre?

Le propre façon est de ne pas conditionner spark-core du tout, il vous est disponible lorsque vous installez Spark sur vos machines cibles et seront disponibles à vos applications à l'exécution (vous pouvez habituellement les trouver sous le /usr/lib/spark/jars).

Vous devez marquer ces dépendances d'étincelles comme % provided. Cela devrait vous aider à éviter de nombreux conflits causés par l'emballage de ces pots.

+0

C'est ce que je fais pour l'application qui fonctionne sous Spark dans le nuage. Une partie de ce même code est utilisée dans le cadre d'une interface graphique. Il n'y a rien fourni par un conteneur. Peut-être que cela pointe vers une meilleure façon de construire le pot pour l'interface graphique? –

+0

@DonBranson je vois. Je ne recommanderais certainement pas d'emballer Spark dans le cadre d'un pot uber, cela vous mènera à l'enfer de la dépendance, car Spark est assez massive. Au lieu de cela, je m'assurerais que le conteneur a ces dépendances fournies par une gestion de configuration qui est chargée de décompresser les jarres Spark. –

+0

C'est un gâchis de dépendance à chaud, c'est sûr. Il n'y a pas de conteneur pour l'interface graphique. J'ai besoin de construire un standalone que je peux partager avec des non-développeurs. Y-a-t-il un moyen de faire ça? Peut-être que je dois faire un zip avec tous les pots, et un script pour les ajouter tous à un classpath. –