FlinkMLTools NoClassDef при запуске jar, созданной с помощью Maven
Я работаю над системой рекомендаций, используя Apache Flink. Реализация работает, когда я тестирую ее в IntelliJ, но я бы хотел сейчас перейти на кластер. Я также собрал jar-файл и протестировал его локально, чтобы увидеть, все ли работает, но я столкнулся с проблемой.
java.lang.NoClassDefFoundError: org / apache / flink / ml / common / FlinkMLTools $
Как мы видим, класс FlinkMLTools
используемый в моем коде не найден во время работы банки. Я построил эту банку с Maven 3.3.3 с mvn clean install
и я использую версию 0.9.0 Flink.
Первый Тропа
Дело в том, что мой глобальный проект содержит другие проекты (и этот рекомендатель является одним из подпроектов). Таким образом, я должен запустить mvn clean install
в папке нужного проекта, в противном случае Maven всегда создает банку другого проекта (и я не понимаю, почему). Поэтому мне интересно, может ли быть способ явно сказать maven для создания одного конкретного проекта глобального проекта. Действительно, возможно, путь к FlinkMLTools
содержится в ссылке, представленной в pom.xml
файл глобального проекта.
Есть другие идеи?
2 ответа
Проблема в том, что бинарный дистрибутив Flink не содержит библиотек (flink-ml, gelly и т. Д.). Это означает, что вам необходимо либо отправить файлы библиотеки JAR вместе с файлом JAR, либо скопировать их вручную в кластер. Я настоятельно рекомендую первый вариант.
Создание фляги, чтобы включить фляги библиотеки
Самый простой способ создать толстый флягу, которая не содержит ненужных фляг, состоит в том, чтобы использовать архетип быстрого запуска Флинка, чтобы настроить pom проекта.
mvn archetype:generate -DarchetypeGroupId=org.apache.flink \
-DarchetypeArtifactId=flink-quickstart-scala -DarchetypeVersion=0.9.0
создаст структуру для проекта Flink, используя Scala API. Сгенерированный файл 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
и вместо этого вы вставляете следующий тег зависимости, чтобы включить библиотеку машинного обучения Флинка.
<dependency>
<groupId>org.apache.flink</groupId>
<artifactId>flink-ml</artifactId>
<version>0.9.0</version>
</dependency>
Когда вы знаете, построить банку с mvn package
сгенерированная банка должна содержать flink-ml
кувшин и все его переходные зависимости.
Копирование библиотечных банок вручную в кластер
Flink включает в себя все банки, которые расположены в <FLINK_ROOT_DIR>/lib
папка в classpath выполненных заданий. Таким образом, чтобы использовать библиотеку машинного обучения Флинка, вы должны поставить flink-ml
банку и все необходимые переходные зависимости в /lib
папка. Это довольно сложно, поскольку вы должны выяснить, какие транзитивные зависимости на самом деле нужны вашему алгоритму, и, следовательно, вам часто придется копировать все транзитивные зависимости.
Как построить конкретный субмодуль с Maven
Чтобы построить конкретный подмодуль X из вашего родительского проекта, вы можете использовать следующую команду:
mvn clean package -pl X -am
-pl
позволяет указать, какие подмодули вы хотите построить и -am
говорит maven также собирать другие необходимые подмодули. Это также описано здесь.
В кластерном режиме Flink не помещает все JAR-файлы библиотеки в путь классов своих рабочих. При локальном выполнении программы в IntelliJ все необходимые зависимости находятся в пути к классам, но не при выполнении в кластере.
У вас есть два варианта:
- скопируйте файл FlinkML Jar в
lib
папка всех Flink TaskManager - Создайте толстый файл Jar для своего приложения, который включает в себя зависимости FLinkML.
Подробности смотрите в документации по выполнению кластера.