Почему приложение Spark терпит неудачу с "ClassNotFoundException: не удалось найти источник данных: kafka" как uber-jar с сборкой sbt?

Я пытаюсь запустить образец, как https://github.com/apache/spark/blob/master/examples/src/main/scala/org/apache/spark/examples/sql/streaming/StructuredKafkaWordCount.scala - ... Я начал с Spark Structured Streaming Programming guide в http://spark.apache.org/docs/latest/structured-streaming-programming-guide.html.

мой код

package io.boontadata.spark.job1

import org.apache.spark.sql.SparkSession

object DirectKafkaAggregateEvents {
  val FIELD_MESSAGE_ID = 0
  val FIELD_DEVICE_ID = 1
  val FIELD_TIMESTAMP = 2
  val FIELD_CATEGORY = 3
  val FIELD_MEASURE1 = 4
  val FIELD_MEASURE2 = 5

  def main(args: Array[String]) {
    if (args.length < 3) {
      System.err.println(s"""
        |Usage: DirectKafkaAggregateEvents <brokers> <subscribeType> <topics>
        |  <brokers> is a list of one or more Kafka brokers
        |  <subscribeType> sample value: subscribe
        |  <topics> is a list of one or more kafka topics to consume from
        |
        """.stripMargin)
      System.exit(1)
    }

    val Array(bootstrapServers, subscribeType, topics) = args

    val spark = SparkSession
      .builder
      .appName("boontadata-spark-job1")
      .getOrCreate()

    import spark.implicits._

    // Create DataSet representing the stream of input lines from kafka
    val lines = spark
      .readStream
      .format("kafka")
      .option("kafka.bootstrap.servers", bootstrapServers)
      .option(subscribeType, topics)
      .load()
      .selectExpr("CAST(value AS STRING)")
      .as[String]

    // Generate running word count
    val wordCounts = lines.flatMap(_.split(" ")).groupBy("value").count()

    // Start running the query that prints the running counts to the console
    val query = wordCounts.writeStream
      .outputMode("complete")
      .format("console")
      .start()

    query.awaitTermination()
  }

}

я добавил следующие файлы sbt:

построить.sbt:

name := "boontadata-spark-job1"
version := "0.1"
scalaVersion := "2.11.7"

libraryDependencies += "org.apache.spark" % "spark-core_2.11" % "2.0.2" % "provided"
libraryDependencies += "org.apache.spark" % "spark-streaming_2.11" % "2.0.2" % "provided"
libraryDependencies += "org.apache.spark" % "spark-sql_2.11" % "2.0.2" % "provided"
libraryDependencies += "org.apache.spark" % "spark-sql-kafka-0-10_2.11" % "2.0.2"
libraryDependencies += "org.apache.spark" % "spark-streaming-kafka-0-10_2.11" % "2.0.2"
libraryDependencies += "org.apache.kafka" % "kafka-clients" % "0.10.1.1"
libraryDependencies += "org.apache.kafka" % "kafka_2.11" % "0.10.1.1"

// META-INF discarding
assemblyMergeStrategy in assembly := { 
   {
    case PathList("META-INF", xs @ _*) => MergeStrategy.discard
    case x => MergeStrategy.first
   }
}

Я также добавил проект/сборка.sbt

addSbtPlugin("com.eed3si9n" % "sbt-assembly" % "0.14.3")

это создает банку Uber с non provided банок.

Я представляю со следующей строкой:

spark-submit boontadata-spark-job1-assembly-0.1.jar ks1:9092,ks2:9092,ks3:9092 subscribe sampletopic

но я получаю эту ошибку во время выполнения:

Exception in thread "main" java.lang.ClassNotFoundException: Failed to find data source: kafka. Please find packages at https://cwiki.apache.org/confluence/display/SPARK/Third+Party+Projects
        at org.apache.spark.sql.execution.datasources.DataSource.lookupDataSource(DataSource.scala:148)
        at org.apache.spark.sql.execution.datasources.DataSource.providingClass$lzycompute(DataSource.scala:79)
        at org.apache.spark.sql.execution.datasources.DataSource.providingClass(DataSource.scala:79)
        at org.apache.spark.sql.execution.datasources.DataSource.sourceSchema(DataSource.scala:218)
        at org.apache.spark.sql.execution.datasources.DataSource.sourceInfo$lzycompute(DataSource.scala:80)
        at org.apache.spark.sql.execution.datasources.DataSource.sourceInfo(DataSource.scala:80)
        at org.apache.spark.sql.execution.streaming.StreamingRelation$.apply(StreamingRelation.scala:30)
        at org.apache.spark.sql.streaming.DataStreamReader.load(DataStreamReader.scala:124)
        at io.boontadata.spark.job1.DirectKafkaAggregateEvents$.main(StreamingJob.scala:41)
        at io.boontadata.spark.job1.DirectKafkaAggregateEvents.main(StreamingJob.scala)
        at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
        at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
        at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
        at java.lang.reflect.Method.invoke(Method.java:498)
        at org.apache.spark.deploy.SparkSubmit$.org$apache$spark$deploy$SparkSubmit$$runMain(SparkSubmit.scala:736)
        at org.apache.spark.deploy.SparkSubmit$.doRunMain(SparkSubmit.scala:185)
        at org.apache.spark.deploy.SparkSubmit$.submit(SparkSubmit.scala:210)
        at org.apache.spark.deploy.SparkSubmit$.main(SparkSubmit.scala:124)
        at org.apache.spark.deploy.SparkSubmit.main(SparkSubmit.scala)
Caused by: java.lang.ClassNotFoundException: kafka.DefaultSource
        at java.net.URLClassLoader.findClass(URLClassLoader.java:381)
        at java.lang.ClassLoader.loadClass(ClassLoader.java:424)
        at java.lang.ClassLoader.loadClass(ClassLoader.java:357)
        at org.apache.spark.sql.execution.datasources.DataSource$$anonfun$$anonfun$apply.apply(DataSource.scala:132)
        at org.apache.spark.sql.execution.datasources.DataSource$$anonfun$$anonfun$apply.apply(DataSource.scala:132)
        at scala.util.Try$.apply(Try.scala:192)
        at org.apache.spark.sql.execution.datasources.DataSource$$anonfun.apply(DataSource.scala:132)
        at org.apache.spark.sql.execution.datasources.DataSource$$anonfun.apply(DataSource.scala:132)
        at scala.util.Try.orElse(Try.scala:84)
        at org.apache.spark.sql.execution.datasources.DataSource.lookupDataSource(DataSource.scala:132)
        ... 18 more
16/12/23 13:32:48 INFO spark.SparkContext: Invoking stop() from shutdown hook

есть ли способ узнать, какой класс не найден, чтобы я мог искать maven.org РЕПО для этого класса.

на lookupDataSource исходный код, похоже, на линии 543 на https://github.com/apache/spark/blob/83a6ace0d1be44f70e768348ae6688798c84343e/sql/core/src/main/scala/org/apache/spark/sql/execution/datasources/DataSource.scala но я не смог найти прямую связь с источником данных Кафки...

полный исходный код здесь: https://github.com/boontadata/boontadata-streams/tree/ad0d0134ddb7664d359c8dca40f1d16ddd94053f

6 ответов


я попробовал, как это работает для меня. Отправить, как это и дайте мне знать, как только у вас есть какие-либо вопросы

./spark-submit --packages org.apache.spark:spark-sql-kafka-0-10_2.11:2.1.0 --class com.inndata.StructuredStreaming.Kafka --master local[*] /Users/apple/.m2/repository/com/inndata/StructuredStreaming/0.0.1SNAPSHOT/StructuredStreaming-0.0.1-SNAPSHOT.jar

проблема заключается в следующем разделе в build.sbt:

// META-INF discarding
assemblyMergeStrategy in assembly := { 
   {
    case PathList("META-INF", xs @ _*) => MergeStrategy.discard
    case x => MergeStrategy.first
   }
}

там написано, что все META-INF entires следует отбросить, включая "код", который делает псевдонимы источников данных (например,kafka) работы.

но META-INF файлы очень важны для kafka (и другие псевдонимы источников потоковых данных) для работы.

на kafka псевдоним для работы Spark SQL использует META-INF / services / org.апаш.искра.язык SQL.источники.DataSourceRegister С следующая запись:

org.apache.spark.sql.kafka010.KafkaSourceProvider

KafkaSourceProvider отвечает за регистрацию kafka псевдоним с соответствующим источником потоковых данных, т. е. KafkaSource.

просто чтобы проверить, что реальный код действительно доступен, но "код", который делает зарегистрированный псевдоним, нет, вы можете использовать kafka источник данных по полному имени (не псевдоним) следующим образом:

spark.readStream.
  format("org.apache.spark.sql.kafka010.KafkaSourceProvider").
  load

вы увидите другие проблемы, из-за отсутствия вариантов как kafka.bootstrap.servers, но...мы отвлеклись.

раствор для MergeStrategy.concat все META-INF/services/org.apache.spark.sql.sources.DataSourceRegister (это создаст uber-jar со всеми источниками данных, включая. the kafka источник данных).

case "META-INF/services/org.apache.spark.sql.sources.DataSourceRegister" => MergeStrategy.concat

в моем случае я также получил эту ошибку при компиляции с sbt, и причиной было то, что sbt assembly не включал spark-sql-kafka-0-10_2.11 артефакт, как часть сала банке.

(Я был бы очень рад комментариям здесь. В зависимости не была указана область, поэтому ее не следует считать "предоставленной").

поэтому я перешел к развертыванию нормальной (тонкой) банки и включению зависимостей с --jars параметры для spark-submit.

для того, чтобы собрать все зависимости в одном месте, вы можете добавить retrieveManaged := true к настройкам проекта sbt, или вы можете, в консоли sbt, выдать:

> set retrieveManaged := true
> package

это должно привести все зависимости к .

затем вы можете скопировать все эти файлы (с помощью команды bash, вы можете например использовать что-то вроде этого

cd /path/to/your/project

JARLIST=$(find lib_managed -name '*.jar'| paste -sd , -)

spark-submit [other-args] target/your-app-1.0-SNAPSHOT.jar --jars "$JARLIST"

Я решил это, загрузив файл jar в систему драйверов. Оттуда я поставил банку для spark submit с опцией --jar.

также следует отметить, что я упаковывал всю среду spark 2.1 в свою банку uber (так как мой кластер все еще находится на 1.6.1) по какой-то причине, его не подобрали при включении в банку uber.

spark-submit --jar / ur / path / spark-sql-kafka-0-10_2.11: 2.1.0 --class ClassNm --Другие-Варианты YourJar.Джар


Я использую spark 2.1 и сталкиваюсь с той же проблемой мой обходной путь

1) spark-shell --packages org.apache.spark:spark-sql-kafka-0-10_2.11:2.1.0

2) cd ~/.ivy2/jars вот вы, все необходимые банки находятся в этой папке сейчас

3) скопируйте все банки в этой папке на все узлы (можно создать определенную папку, содержащую их)

4) Добавьте имя папки в spark.driver.extraClassPath и spark.driver.extraClassPath ,например,spark.driver.extraClassPath=/opt/jars/*:your_other_jars

5 spark-submit --class ClassNm --Other-Options YourJar.jar отлично работает сейчас


это ввиду ответа Яцека Ласковского.

те из вас, кто строит свой проект на maven, могут попробовать это. Добавьте строку, указанную ниже, в свой Maven-shade-plugin.

META-INF / services / org.апаш.искра.язык SQL.источники.DataSourceRegister

Я положил код плагина для файла pom в качестве примера, чтобы показать, где добавить строку.


<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>
                <transformers>
                    <transformer implementation="org.apache.maven.plugins.shade.resource.AppendingTransformer">
                        <resource>
                            META-INF/services/org.apache.spark.sql.sources.DataSourceRegister
                        </resource>
                    </transformer>
                </transformers>
                <finalName>${project.artifactId}-${project.version}-uber</finalName>
            </configuration>
        </execution>
    </executions>
</plugin>

пожалуйста, извините мои навыки форматирования.