4

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

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

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

第一条线索

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

还有其他想法吗?

4

2 回答 2

5

问题是 Flink 的二进制发行版不包含库(flink-ml、gelly 等)。这意味着您要么必须将库 jar 文件与作业 jar 一起发送,要么必须手动将它们复制到集群中。我强烈推荐第一个选项。

构建一个包含库 jar 的 fat-jar

构建一个不包含不必要 jar 的胖 jar 的最简单方法是使用 Flink 的快速入门原型来设置项目的 pom.jar。

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>

当您知道使用 构建作业 jar 时mvn package,生成的 jar 应包含该flink-mljar 及其所有传递依赖项。

手动将库 jar 复制到集群

Flink 包含所有位于<FLINK_ROOT_DIR>/lib已执行作业的类路径中的文件夹中的 jar。因此,为了使用 Flink 的机器学习库,您必须将flink-mljar 和所有需要的传递依赖项放入/lib文件夹中。这相当棘手,因为您必须弄清楚您的算法实际需要哪些传递依赖,因此,您通常最终会复制所有传递依赖。

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

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

 mvn clean package -pl X -am

-pl允许您指定要构建的子模块,并-am告诉 maven 还构建其他必需的子模块。这里也有描述。

于 2015-07-16T13:06:41.783 回答
3

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

你有两个选择:

  1. 将 FlinkML Jar 文件复制到lib所有 Flink TaskManager 的文件夹中
  2. 为您的应用程序构建一个包含 FLinkML 依赖项的胖 Jar 文件。

有关详细信息,请参阅集群执行文档

于 2015-07-15T20:14:29.617 回答