FlinkMLTools NoClassDef when 运行 jar built with maven
FlinkMLTools NoClassDef when running jar built with maven
我正在使用 Apache Flink 开发推荐系统。当我在 IntelliJ 中测试它时,实现是 运行,但我现在想继续集群。我还构建了一个 jar 文件并在本地测试它以查看是否一切正常但我遇到了问题。
java.lang.NoClassDefFoundError: org/apache/flink/ml/common/FlinkMLTools$
正如我们所见,我的代码中使用的 class FlinkMLTools
在 jar 的 运行 期间找不到。
我用 mvn clean install
使用 Maven 3.3.3 构建了这个 jar,我使用的是 Flink.
的 0.9.0 版本
第一条路
事实是我的全局项目包含其他项目(并且这个推荐人是子项目之一)。这样,我必须在正确项目的文件夹中启动 mvn clean install
,否则 Maven 总是构建其他项目的 jar(我不明白为什么)。所以我想知道是否有一种方法可以明确地告诉 maven 来构建全局项目的一个特定项目。实际上,FlinkMLTools
的路径可能包含在全局项目的 pom.xml
文件中的 link 中。
还有其他想法吗?
在集群模式下,Flink 不会将所有库 JAR 文件放入其 workers 的类路径中。在 IntelliJ 中本地执行程序时,所有必需的依赖项都在类路径中,但在集群上执行时则不然。
您有两个选择:
- 将FlinkML Jar文件复制到所有Flink TaskManager的
lib
文件夹中
- 为您的应用程序构建一个包含 FLinkML 依赖项的 fat Jar 文件。
问题是 Flink 的二进制发行版不包含库(flink-ml、gelly 等)。这意味着您要么必须将库 jar 文件与您的作业 jar 一起发送,要么必须手动将它们复制到您的集群。我强烈推荐第一个选项。
构建一个包含库 jar 的 fat-jar
构建不包含不必要 jar 的 fat jar 的最简单方法是使用 Flink 的 quickstart archetype 来设置项目的 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.
我正在使用 Apache Flink 开发推荐系统。当我在 IntelliJ 中测试它时,实现是 运行,但我现在想继续集群。我还构建了一个 jar 文件并在本地测试它以查看是否一切正常但我遇到了问题。
java.lang.NoClassDefFoundError: org/apache/flink/ml/common/FlinkMLTools$
正如我们所见,我的代码中使用的 class FlinkMLTools
在 jar 的 运行 期间找不到。
我用 mvn clean install
使用 Maven 3.3.3 构建了这个 jar,我使用的是 Flink.
第一条路
事实是我的全局项目包含其他项目(并且这个推荐人是子项目之一)。这样,我必须在正确项目的文件夹中启动 mvn clean install
,否则 Maven 总是构建其他项目的 jar(我不明白为什么)。所以我想知道是否有一种方法可以明确地告诉 maven 来构建全局项目的一个特定项目。实际上,FlinkMLTools
的路径可能包含在全局项目的 pom.xml
文件中的 link 中。
还有其他想法吗?
在集群模式下,Flink 不会将所有库 JAR 文件放入其 workers 的类路径中。在 IntelliJ 中本地执行程序时,所有必需的依赖项都在类路径中,但在集群上执行时则不然。
您有两个选择:
- 将FlinkML Jar文件复制到所有Flink TaskManager的
lib
文件夹中 - 为您的应用程序构建一个包含 FLinkML 依赖项的 fat Jar 文件。
问题是 Flink 的二进制发行版不包含库(flink-ml、gelly 等)。这意味着您要么必须将库 jar 文件与您的作业 jar 一起发送,要么必须手动将它们复制到您的集群。我强烈推荐第一个选项。
构建一个包含库 jar 的 fat-jar
构建不包含不必要 jar 的 fat jar 的最简单方法是使用 Flink 的 quickstart archetype 来设置项目的 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.