运行使用 maven 构建的 jar 时的 FlinkMLTools NoClassDef
Posted
技术标签:
【中文标题】运行使用 maven 构建的 jar 时的 FlinkMLTools NoClassDef【英文标题】:FlinkMLTools NoClassDef when running jar built with maven 【发布时间】:2015-10-05 00:32:29 【问题描述】:我正在使用 Apache Flink 开发推荐系统。当我在 IntelliJ 中测试它时,该实现正在运行,但我现在想在集群上运行。我还构建了一个 jar 文件并在本地对其进行了测试,以查看是否一切正常,但我遇到了问题。
java.lang.NoClassDefFoundError: org/apache/flink/ml/common/FlinkMLTools$
正如我们所见,我的代码中使用的 FlinkMLTools
类在 jar 运行期间找不到。
我用 Maven 3.3.3 和 mvn clean install
构建了这个 jar,我使用的是 Flink 0.9.0 版本。
第一道
事实是我的全局项目包含其他项目(并且这个推荐器是子项目之一)。这样,我必须在正确项目的文件夹中启动mvn clean install
,否则Maven总是会构建另一个项目的jar(我不明白为什么)。所以我想知道是否有一种方法可以明确地告诉 maven 来构建全球项目的一个特定项目。实际上,FlinkMLTools
的路径可能包含在全局项目的 pom.xml
文件中的链接中。
还有其他想法吗?
【问题讨论】:
【参考方案1】:问题在于 Flink 的二进制发行版不包含库(flink-ml、gelly 等)。这意味着您要么必须将库 jar 文件与作业 jar 一起发送,要么必须手动将它们复制到集群中。我强烈推荐第一个选项。
构建一个 fat-jar 来包含库 jars
构建不包含不必要 jar 的 fat jar 的最简单方法是使用 Flink 的快速入门原型来设置项目的 pom。
mvn archetype:generate -DarchetypeGroupId=org.apache.flink \
-DarchetypeArtifactId=flink-quickstart-scala -DarchetypeVersion=0.9.0
将使用 Scala API 为 Flink 项目创建结构。生成的pom文件会有以下依赖。
<dependencies>
<dependency>
<groupId>org.apache.flink</groupId>
<artifactId>flink-scala</artifactId>
<version>0.9.0</version>
</dependency>
<dependency>
<groupId>org.apache.flink</groupId>
<artifactId>flink-streaming-scala</artifactId>
<version>0.9.0</version>
</dependency>
<dependency>
<groupId>org.apache.flink</groupId>
<artifactId>flink-clients</artifactId>
<version>0.9.0</version>
</dependency>
</dependencies>
您可以删除 flink-streaming-scala
并插入以下依赖标签以包含 Flink 的机器学习库。
<dependency>
<groupId>org.apache.flink</groupId>
<artifactId>flink-ml</artifactId>
<version>0.9.0</version>
</dependency>
当您知道使用 mvn package
构建作业 jar 时,生成的 jar 应该包含 flink-ml
jar 及其所有传递依赖项。
手动复制库jar到集群
Flink 包含所有位于已执行作业的类路径中的 <FLINK_ROOT_DIR>/lib
文件夹中的 jar。因此,为了使用 Flink 的机器学习库,您必须将 flink-ml
jar 和 所有需要的传递依赖项 放入 /lib
文件夹中。这相当棘手,因为您必须弄清楚您的算法实际上需要哪些传递依赖,因此,您通常最终会复制 all 传递依赖。
如何用maven构建特定的子模块
为了从您的父项目构建特定的子模块 X,您可以使用以下命令:
mvn clean package -pl X -am
-pl
允许您指定要构建的子模块,-am
告诉 maven 也构建其他必需的子模块。它也被描述为here。
【讨论】:
【参考方案2】:在集群模式下,Flink 不会将所有库 JAR 文件放入其工作线程的类路径中。在 IntelliJ 中本地执行程序时,所有必需的依赖项都在类路径中,但在集群上执行时则不然。
你有两个选择:
-
将FlinkML Jar文件复制到所有Flink TaskManager的
lib
文件夹中
为您的应用程序构建一个包含 FLinkML 依赖项的胖 Jar 文件。
详情请参阅Cluster Execution Documentation。
【讨论】:
对于网站上给出的不同方法,我仍然有同样的问题。我会直接在我使用的集群上尝试,希望他们有这个库! :) 你是如何在你的集群上运行 Flink 的?你是在使用 YARN 还是在所有节点上都安装了 Flink? 我在所有节点上都使用 Flink。我有一个新事实。我设法在 jar 文件中有FlinkMLTools
(我可以看到它在那里),用这个 jar 运行但有一个NoClassDefFound: breeze/storage/Zero
,但根据我在 Internet 上找到的内容,它似乎是 Flink 的原生(微风库)...以上是关于运行使用 maven 构建的 jar 时的 FlinkMLTools NoClassDef的主要内容,如果未能解决你的问题,请参考以下文章