sbt依赖冲突查看及解决

安装依赖关系解析插件

graph_importer项目中使用依赖

项目scala版本:scalaVersion := "2.11.11"

libraryDependencies ++= Seq(
  "org.apache.spark" %% "spark-core" % "1.6.2",
  "org.apache.spark" %% "spark-sql" % "1.6.2",
  "com.databricks" %% "spark-csv" % "1.5.0",
  "commons-cli" % "commons-cli" % "1.4",
  "org.janusgraph" % "janusgraph-all" % "0.2.0" exclude("org.apache.hadoop","hadoop-common") exclude("com.sleepycat","je"),
  "org.apache.hadoop" % "hadoop-common" % "2.7.2" exclude("javax.servlet", "servlet-api"),
  "org.apache.hbase" % "hbase-shaded-client" % "1.2.6",
  "com.alibaba" % "fastjson" % "1.2.39"
)

问题

  • 在项目下执行sbt update,出现如下问题:依赖版本冲突,spark-core出现了使用scala 2.11 ,2.10编译的两个版本(其它冲突依赖都是这2个依赖的间接依赖,把这个依赖冲突解决了,其他都就解决了)。
[error] Modules were resolved with conflicting cross-version suffixes in {file:/Users/xiangzuqi/dev/idea_workspace/graph/}graph_importer:
[error]    org.apache.spark:spark-launcher _2.11, _2.10
[error]    org.json4s:json4s-ast _2.11, _2.10
[error]    org.apache.spark:spark-network-shuffle _2.11, _2.10
[error]    com.typesafe.akka:akka-actor _2.11, _2.10
[error]    com.twitter:chill _2.11, _2.10
[error]    org.json4s:json4s-jackson _2.11, _2.10
[error]    com.fasterxml.jackson.module:jackson-module-scala _2.11, _2.10
[error]    org.json4s:json4s-core _2.11, _2.10
[error]    org.apache.spark:spark-unsafe _2.11, _2.10
[error]    com.typesafe.akka:akka-remote _2.11, _2.10
[error]    com.typesafe.akka:akka-slf4j _2.11, _2.10
[error]    org.apache.spark:spark-core _2.11, _2.10
[error]    org.apache.spark:spark-network-common _2.11, _2.10
[trace] Stack trace suppressed: run last graph_importer/*:update for the full output.
  • 因为我们在.sbt中对spark-core的依赖是spark-core_2.11 1.6.2,所以我们知道使用scala 2.10版本编译的spark-core,不是我们想要的。

查找冲突依赖

  • 执行 sbt dependencyList :查询compile范围的依赖
    • 注:sbt test:dependencyList 查询 test范围的依赖,test和compile的依赖一般不一样
  • 查看spark-core 的不同版本。
    • spark-core_2.11 1.6.1和spark-core_2.11 1.6.2两个版本
image.png

确定冲突依赖在哪里引进来的

  • 查询以下冲突依赖分别来自哪里
[info] org.apache.spark:spark-core_2.10:1.6.1
[info] org.apache.spark:spark-core_2.11:1.6.2

查询org.apache.spark:spark-core_2.10:1.6.1依赖图

 sbt whatDependsOn org.apache.spark spark-core_2.10 1.6.1
  • 得到倒叙依赖关系,如下:
    • 即graph_importer依赖janusgraph-all—》janusgraph-hadoop-》spark-gremlin-》spark-core_2.10:1.6.1
    • 可以看到spark-core_2.10 1.6.1通过janusgraph-all的间接依赖传进来的。graph_importer下载janusgraph-all,janusgraph-all下载janusgraph-hadoop,janusgraph-hadoop下载spark-gremlin,spark-gremlin下载spark-core_2.10:1.6.1。
[info] org.apache.spark:spark-core_2.10:1.6.1
[info]   +-org.apache.tinkerpop:spark-gremlin:3.2.6 [S]
[info]     +-org.janusgraph:janusgraph-hadoop:0.2.0
[info]       +-org.janusgraph:janusgraph-all:0.2.0
[info]         +-com.jd.jr:graph_importer_2.11:1.0-fc49bb9d409f43dcd03e317471..
[info]

查询org.apache.spark:spark-core_2.11:1.6.2依赖图

  • 下图可见此org.apache.spark:spark-core_2.11:1.6.2最终通过gaph_importer中的直接依赖spark-sql_2.11:1.6.2引进来的,是我希望的依赖。
image.png

冲突结论

  • 从上一个步骤我们可以看出,org.apache.spark:spark-core_2.10:1.6.1是我们不希望的依赖,根据上面依赖关系可知,其是+-org.apache.tinkerpop:spark-gremlin:3.2.6 [S]的直接依赖。

  • 解决思路:如果spark-gremlin3.2.6中对spark-core的依赖是spark-core_2.11:1.6.2的话,那么就不会出现冲突了。要想在保持spark-gremiln的3.2.6版本不变的情况下,让其依赖spark-core_2.11:1.6.2的话,就需要对其进行定制化编译:从github上下载spark-gremlin3.2.6源码,修改pom中spark-core的依赖版本,再重新编译打包,并将打包好的spark-gremlin3.2.6安装到本地仓库,然后当graph_importer下载spark-gremlin:3.2.6时,我们让其从本地仓库中下载我们改造过的依赖,而不是从中央仓库下载。(因为中央仓库中的spark-gremlin:3.2.6依然是依赖spark-core_2.10:1.6.1)

重新编译打包spark-gremlin

  • 因为spark-gremlin是tinkerpop项目中的一个模块,所以需要下载tinkerpop,但是只需要修改sprk-gremlin模块就行,因为其他模块我们不需要。tinkerpop是maven项目。

  • git clone tinkerpop

git clone https://github.com/apache/tinkerpop.git
  • 切换到3.2.6版本,并在此基础上新建分支tinkerpop3.2.6
git checkout 3.2.6
git checkout -b tinkerpop3.2.6
tinkerpop
  • 修改spark-gremlin模块pom.xml文件,将其中依赖spark-core版本改为正确信息,还需要修改scala-library版本为2.11.8,其原来值是2.10


    image.png

    image.png
  • 编译spark-gremlin模块,并install到maven本地仓库


    编译安装spark-gremlin模块到本地仓库
  • 到此为止,本地maven仓库中的存在了我们定制过的spark-gremlin:3.2.6,其依赖的是spark-core_2.11:1.6.2。

让graph_importer下载本地maven仓库中定制的spark-gremlin

  • graph_importer是sbt项目,其下载依赖默认从本地sbt仓库中下载,如果没有会从其默认的网上仓库下载。
  • 如果让其能下载到本地maven中定制的spark-gremlin而且又不影响其它依赖的下载。那么根据sbt的下载逻辑来看,我们需要配置其寻找依赖的仓库和先后顺序。具体如下:首先修改sbt的默认下载仓库,让其包含本地maven仓库,其次让本地maven仓库的位置在中央仓库之前,这样其就会先从本地maven仓库中找,找不到才会到中央仓库中找,而spark-gremlin定制版本再本地maven仓库中包含了,就不会从网络上下载了。

repositories文件

  • 在repositories中配置其默认的下载仓库和顺序
  • 其位置在 ~/用户/.sbt 下,如果没有则创建,内容如下:
[repositories]
  maven-local
  local
  //typesafe-releases: http://repo.typesafe.com/typesafe/releases
  typesafe-ivy-releasez: http://repo.typesafe.com/typesafe/ivy-releases, [organization]/[module]/(scala_[scalaVersion]/)(sbt_[sbtVersion]/)[revision]/[type]s/[artifact](-[classifier]).[ext]

先删掉sbt本地仓库中的sprk-gremlin:3.2.6

  • 因为其是之前下载的

查看sbt仓库解析器

  • 查看当前项目下依赖解析器,可以看到本地maven仓库排在第一位,sbt解析依赖会按照顺序使用解析器解析,如果第前个解析不到就使用下一个解析器解析,都解析不到就报错。
> show fullResolvers
[info] * Raw(ProjectResolver(inter-project, mapped: ))
[info] * FileRepository(local,FileConfiguration(true,None),Patterns(ivyPatterns=List(${ivy.home}/local/[organisation]/[module]/(scala_[scalaVersion]/)(sbt_[sbtVersion]/)[revision]/[type]s/[artifact](-[classifier]).[ext]), artifactPatterns=List(${ivy.home}/local/[organisation]/[module]/(scala_[scalaVersion]/)(sbt_[sbtVersion]/)[revision]/[type]s/[artifact](-[classifier]).[ext]), isMavenCompatible=false, descriptorOptional=false, skipConsistencyCheck=false))
[info] * cache:Maven2 Local: C:\Users\zhouliang6\.m2\repository
[info] * my-maven-proxy-releases: http://10.13.96.74:8081/artifactory/libs-release
[info] * URLRepository(my-ivy-proxy-releases,Patterns(ivyPatterns=List(http://10.13.96.74:8081/artifactory/sbt-release/[organization]/[module]/(scala_[scalaVersion]/)(sbt_[sbtVersion]/)[revision]/[type]s/[artifact](-[classifier]).[ext]), artifactPatterns=List(http://10.13.96.74:8081/artifactory/sbt-release/[organization]/[module]/(scala_[scalaVersion]/)(sbt_[sbtVersion]/)[revision]/[type]s/[artifact](-[classifier]).[ext]), isMavenCompatible=false, descriptorOptional=false, skipConsistencyCheck=false))

执行sbt update

  • 执行sbt update后,让其更新依赖,如果存在就不会在下载,否则使用本地。

推荐阅读更多精彩内容