3

Чтобы подать заявку Спарк в кластер, их документация Примечания:Apache Spark - с помощью искрового представить бросает NoSuchMethodError

Чтобы сделать это, создайте сборочный банку (или «убер» сосуд), содержащий ваши кода и его зависимостей. Оба sbt и Maven имеют сборные плагины. При создании сборочных банок укажите Spark и Hadoop в качестве предоставленных зависимостей; их не нужно связывать, поскольку они предоставляются менеджером кластера во время выполнения. - http://spark.apache.org/docs/latest/submitting-applications.html

Итак, я добавил тени плагин Apache Maven для моей pom.xml файла. (версия 3.0.0)
И я превратил сферу своей Spark в provided. (Версия 2.1.0)

(Я также добавил Apache Maven Assembly плагин, чтобы гарантировать, что я обмотать все мои зависимостями в банке, когда я бегу mvn clean package. Я уверен, если это действительно необходимо.)


Таким образом, как spark-submit не удается. Он выбрасывает NoSuchMethodError для зависимости, которую я имею (обратите внимание, что код работает из локального экземпляра при компиляции внутри IntelliJ, предполагая, что provided удален).

Exception in thread "main" java.lang.NoSuchMethodError: com.google.common.base.Stopwatch.createStarted()Lcom/google/common/base/Stopwatch; 

Строка кода, который бросает ошибку не имеет значения - это просто первая линия в моей основной метод, который создает Stopwatch, часть утилит Google гуавы. (версия 21.0)

Другие решения в Интернете предполагают, что это связано с конфликтами версий Guava, но мне еще не удалась с этими предложениями. Любая помощь будет оценена, спасибо.

ответ

2

Если вы посмотрите на подкаталогустановки Spark 2.1.0, вы, скорее всего, увидите guava-14.0.1.jar. За API for the Guava Stopwatch#createStarted method вы используете, createStarted не существовало до Guava 15.0. Наиболее вероятно, что процесс Spark Classloader находит библиотеку Guava 14.0.1, предоставленную Spark, прежде чем он найдет библиотеку Guava 21.0, упакованную в ваш uberjar.

Одним из возможных решений является использование class-relocation feature provided by the Maven Shade plugin (которое вы уже используете для создания вашего uberjar). Через «перемещение класса» Maven-Shade перемещает классы Guava 21.0 (необходимые вашему коду) во время упаковки uberjar из местоположения pattern, отражающего их существующее имя пакета (например, com.google.common.base) произвольному адресу shadedPattern, которое вы указываете в Конфигурация оттенков (например,myguava123.com.google.common.base).

В результате старшие и новые библиотеки Guava больше не имеют имени пакета, избегая конфликтов во время выполнения.

+0

Спасибо, добавив раздел 'relocation' в плагин для тени, исправил ошибку. Кроме того, я смог удалить плагин сборки, и он все еще работал нормально. –

2

Скорее всего, у вас конфликт зависимости, да.

Прежде всего вы можете посмотреть, есть ли у вас конфликт зависимости, когда вы строите свою банку. Быстрый способ - посмотреть в свою банку напрямую, чтобы увидеть, есть ли файл Stopwatch.class, и если, посмотрев на байт-код, кажется, что существует метод createStarted. В противном случае вы можете также указать дерево зависимостей и работать оттуда: https://maven.apache.org/plugins/maven-dependency-plugin/examples/resolving-conflicts-using-the-dependency-tree.html

Если это не проблема с банкой, вы можете иметь проблемы зависимостей из-за конфликт между вашей установкой свечи и вашей баночкой. Посмотрите в папку lib и jars вашей искровой установки. Там вы можете увидеть, есть ли у вас баночки, содержащие альтернативную версию guava, которые не поддерживали бы метод createStarted() из секундомера

+0

Параметр 'Stopwatch.createStarted()' метод существует в банке, я теперь проверить, чтобы увидеть, если искра есть какие-либо противоречивую версию гуавы уже. –

+0

Похоже, что Spark 2.1.0 имеет 'guava-14.0.1.jar' в каталоге jars. –

0

Применить выше ответы, чтобы решить проблему с помощью следующей конфигурации:

<plugin> 
    <groupId>org.apache.maven.plugins</groupId> 
    <artifactId>maven-shade-plugin</artifactId> 
    <version>3.1.0</version> 
    <executions> 
     <execution> 
     <phase>package</phase> 
     <goals> 
      <goal>shade</goal> 
     </goals> 
     <configuration> 
      <relocations> 
       <relocation> 
        <pattern>com.google.common</pattern> 
        <shadedPattern>shade.com.google.common</shadedPattern> 
       </relocation> 
       <relocation> 
        <pattern>com.google.thirdparty.publicsuffix</pattern> 
        <shadedPattern>shade.com.google.thirdparty.publicsuffix</shadedPattern> 
       </relocation> 
      </relocations> 
     </configuration> 
     </execution> 
    </executions> 
    </plugin>