运行使用maven构建的jar时,FlinkMLTools NoClassDef

时间:2015-07-15 19:27:46

标签: maven jar noclassdeffounderror apache-flink flinkml

我正在使用Apache Flink开发推荐系统。当我在IntelliJ中测试它时,实现正在运行,但我现在想要进入集群。我还构建了一个jar文件并在本地测试它以查看是否一切正常但我遇到了问题。

  

java.lang.NoClassDefFoundError:org / apache / flink / ml / common / FlinkMLTools $

正如我们所看到的,在运行jar时找不到我的代码中使用的类FlinkMLTools。 我使用Maven 3.3.3和mvn clean install构建了这个jar,我使用的是Flink的0.9.0版本。

First Trail

事实是我的全球项目包含其他项目(这个推荐人是子项目之一)。这样,我必须在正确项目的文件夹中启动mvn clean install,否则Maven总是构建一个其他项目的jar(我不明白为什么)。所以我想知道是否有办法明确地说maven来构建一个全球项目的特定项目。实际上,FlinkMLTools的路径可能包含在全球项目的pom.xml文件中的链接中。

还有其他想法吗?

2 个答案:

答案 0 :(得分:5)

问题是Flink的二进制发行版不包含库(flink-ml,gelly等)。这意味着您必须将库jar文件与您的作业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文件夹。这是相当棘手的,因为你必须弄清楚你的算法实际需要哪些传递依赖,因此,你最终会复制所有传递依赖。

如何使用maven构建特定的子模块

要从父项目构建特定的子模块X,您可以使用以下命令:

 mvn clean package -pl X -am

-pl允许您指定要构建的子模块,-am告诉maven还构建其他所需的子模块。它还描述了here

答案 1 :(得分:3)

在群集模式下,Flink不会将所有库JAR文件放入其worker的类路径中。在IntelliJ中本地执行程序时,所有必需的依赖项都在类路径中,但在集群上执行时则不行。

您有两种选择:

  1. 将FlinkML Jar文件复制到所有Flink TaskManager的lib文件夹
  2. 为您的应用程序构建一个胖Jar文件,其中包含FLinkML依赖项。
  3. 有关详细信息,请参阅Cluster Execution Documentation