我想构建一个我的代码的“胖” jar 。我主要了解如何执行此操作,但我使用的所有示例都使用 jar 不是本地的想法,并且我不确定如何将我构建的 scala 代码使用的另一个 JAR 包含到我的组装 jar 中。就像我必须包含的这个 JAR 位于哪个文件夹中?
通常,当我使用 Spark-shell 运行当前代码作为测试时,它看起来像这样:
spark-shell --jars magellan_2.11-1.0.6-SNAPSHOT.jar -i st_magellan_abby2.scala
(jar 文件与 .scala 文件位于同一路径中)
现在我想构建一个具有相同功能并包含 SNAPSHOT.jar 文件的 build.sbt 文件?
name := "PSGApp"
version := "1.0"
scalaVersion := "2.11.8"
resolvers += "Spark Packages Repo" at "http://dl.bintray.com/spark-packages/maven"
//provided means don't included it is there. already on cluster?
libraryDependencies ++= Seq(
"org.apache.spark" %% "spark-core" % "2.2.0" % "provided",
"org.apache.spark" %% "spark-sql" % "2.2.0" % "provided",
"org.apache.spark" %% "spark-streaming" % "2.2.0" % "provided",
//add magellan here somehow?
)
那么我应该将 jar 放在 SBT 项目文件夹结构中的哪里,以便在运行 sbt assembly 时将其拾取?它在 main/resources 文件夹中吗?引用手册说的是“要包含在主 jar 中的文件”去哪里?
我应该在库依赖项中放入什么,以便它知道添加特定的 jar 而不是到互联网上获取它?
最后一件事,我还在测试代码中进行了一些导入,但现在我将此代码放入一个附加有 def main
的对象中,这些导入似乎不起作用。
我有这样的事情:
导入 sqlContext.implicits._ 就在上面的代码中,它将像这样使用:
val sqlContext = new org.apache.spark.sql.SQLContext(sc)
import sqlContext.implicits._
import org.apache.spark.sql.functions.udf
val distance =udf {(a: Point, b: Point) =>
a.withinCircle(b, .001f); //current radius set to .0001
}
我不确定是否可以将这些导入保留在 def main 中?或者我必须以某种方式将它们移到其他地方? (我猜仍在学习 scala 并争论范围界定)。
最佳答案
一种方法是在本地使用程序集插件 ( https://github.com/sbt/sbt-assembly ) 和 publishLocal
来构建 fat jar。将生成的 jar 存储到本地 ivy2 缓存中
这将使它可以根据该项目中的 build.sbt 设置包含在您的其他项目中,例如:
name := "My Project"
organization := "org.me"
version := "0.1-SNAPSHOT"
将在本地以 "org.me" %% "my-project" % "0.1-SNAPSHOT"
的形式提供
SBT 将在尝试从外部存储库下载之前搜索本地缓存。
但是,这被认为是不好的做法,因为只有最终项目才应该是一个 fat-jar。你永远不应该将其中之一作为依赖项(很多令人头痛的事情)。
如果 PGapp 中包含库,则没有理由将 magellan 项目制作为 fat-jar。只需publishLocal,无需汇编
另一种方法是使项目作为代码而不是库相互依赖。
lazy val projMagellan = RootProject("../magellan")
lazy val projPSGApp = project.in(file(".")).dependsOn(projMagellan)
这使得 projPSGApp 中的编译成为 projMagellan 中的 tigger 编译。
但这取决于您的用例。
只是不要陷入必须手动管理 .jar 的情况
另一个问题:
import sqlContext.implicits._
应始终包含在需要数据帧操作的范围内,因此您不应将该导入放在标题中的其他导入附近
更新
根据评论中的讨论,我的建议是:
- 获取麦哲伦存储库
git clone <a href="https://stackoverflow.com/cdn-cgi/l/email-protection" class="__cf_email__" data-cfemail="7a1d130e3a1d130e120f1854191517" rel="noreferrer noopener nofollow">[email protected]</a>:harsha2010/magellan.git
- 创建一个要处理的分支,例如。
git checkout -b new-stuff
- 更改您想要的代码
- 然后更新版本号,例如。
version := "1.0.7-SNAPSHOT"
- 本地发布
sbt publishLocal
您会看到类似的内容(一段时间后):
[info] published ivy to /Users/tomlous/.ivy2/local/harsha2010/magellan_2.11/1.0.7-SNAPSHOT/ivys/ivy.xml
- 转到您的其他项目
- 更改
build.sbt
包括
"harsha2010" %% "magellan" % "1.0.7-SNAPSHOT"
在你的libraryDependencies
现在您对您的库有了一个很好的(临时)引用。
您的 PSGApp 应构建为 fat jar 程序集以传递给 Spark
sbt clean assembly
这将拉入自定义构建 jar
如果 magellan 项目中的更改对世界其他地方有用,您应该推送更改并创建拉取请求,以便将来您可以只包含此库的最新版本
关于scala - sbt 组件,包括我的 jar,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/49825081/