web-dev-qa-db-ja.com

なぜSparkアプリケーションはsbtアセンブリのuber-jarとして「ClassNotFoundException:Failed to find data source:kafka」で失敗しますか?

https://github.com/Apache/spark/blob/master/examples/src/main/scala/org/Apache/spark/examples/sql/streaming/StructuredKafkaWordCountのようなサンプルを実行しようとしています.scalahttp://spark.Apache.org/docs/latest/structured-streaming-programming-guide.html のSpark構造化ストリーミングプログラミングガイドから始めました。

私のコードは

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ファイルを追加しました。

build.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
   }
}

Project/Assembly.sbtも追加しました

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

これにより、provided以外のjarを持つUber jarが作成されます。

次の行で送信します。

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$1(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$5$$anonfun$apply$1.apply(DataSource.scala:132)
        at org.Apache.spark.sql.execution.datasources.DataSource$$anonfun$5$$anonfun$apply$1.apply(DataSource.scala:132)
        at scala.util.Try$.apply(Try.scala:192)
        at org.Apache.spark.sql.execution.datasources.DataSource$$anonfun$5.apply(DataSource.scala:132)
        at org.Apache.spark.sql.execution.datasources.DataSource$$anonfun$5.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ソースコードは https://github.com/Apache/spark/blob/83a6ace0d1be44f70e768348ae6688798c84343e/sql/core/src/main/scala/org/Apache/の543行目にあるようです。 spark/sql/execution/datasources/DataSource.scala しかし、Kafkaデータソースとの直接リンクが見つかりませんでした...

完全なソースコードはこちら: https://github.com/boontadata/boontadata-streams/tree/ad0d0134ddb7664d359c8dca40f1d16ddd94053f

20
benjguin

私はこのようにしてみました、それは私のために働いています。このように送信し、問題が発生したらお知らせください

./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
19

問題は、build.sbtの次のセクションです。

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

データソースエイリアス(例:kafka)を機能させる「コード」を含め、すべてのMETA-INF全体を破棄する必要があると書かれています。

ただし、META-INFファイルは、kafka(およびストリーミングデータソースの他のエイリアス)が機能するために非常に重要です。

kafkaエイリアスが機能する場合Spark SQLは META-INF/services/org.Apache.spark.sql.sources.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 all META-INF/services/org.Apache.spark.sql.sources.DataSourceRegisterkafkaデータソースを含むすべてのデータソースでuber-jarを作成する)です。

case "META-INF/services/org.Apache.spark.sql.sources.DataSourceRegister" => MergeStrategy.concat
18
Jacek Laskowski

私の場合、sbtでコンパイルしているときにこのエラーも発生しました。その原因は、sbt Assemblyspark-sql-kafka-0-10_2.11アーティファクトをファットjarの一部として含んでいなかったことです。

(ここでコメントを歓迎します。依存関係はスコープとして指定されていなかったので、「提供された」と見なされるべきではありません)。

そこで、通常の(スリムな)jarをデプロイし、--jarsパラメーターを持つ依存関係をspark-submitに含めるように変更しました。

すべての依存関係を1か所で収集するには、retrieveManaged := trueをsbtプロジェクト設定に追加するか、sbtコンソールで以下を発行します。

> set retrieveManaged := true
> package

これにより、すべての依存関係がlib_managedフォルダーに移動します。

次に、これらのファイルをすべてコピーできます(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"
3
ssice

これは、Jacek Laskowskiの答えを考慮しています。

Mavenでプロジェクトを構築している人は、これを試すことができます。以下の行をmaven-shade-pluginに追加します。

META-INF/services/org.Apache.spark.sql.sources.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>

書式設定のスキルを許してください。

1
Algomeister

spark 2.1を使用していますが、回避策はまったく同じ問題に直面しています

1)spark-Shell --packages org.Apache.spark:spark-sql-kafka-0-10_2.11:2.1.0

2)cd ~/.ivy2/jarsここにいます。必要なすべてのjarはこのフォルダーにあります

3)このフォルダー内のすべてのjarをすべてのノードにコピーします(それらを保持する特定のフォルダーを作成できます)

4)フォルダー名をspark.driver.extraClassPathおよびspark.driver.extraClassPathに追加します。 spark.driver.extraClassPath=/opt/jars/*:your_other_jars

5 spark-submit --class ClassNm --Other-Options YourJar.jarが正常に動作するようになりました

1
dalin qin

Gradleをビルドツールとして使用し、shadowJarプラグインを使用してuberJarを作成しています。解決策は、単にファイルを追加することでした

src/main/resources/META-INF/services/org.Apache.spark.sql.sources.DataSourceRegister  

プロジェクトに。

このファイルには、使用するデータソースのクラス名を1行ずつ入力する必要があります。この場合はorg.Apache.spark.sql.kafka010.KafkaSourceProvider(たとえば here などのクラス名を見つける)

その理由は、Spark=が内部の依存関係管理メカニズムでJava ServiceLoader を使用するためです。

完全な例 こちら

0
Falco Winkler

Jarファイルをドライバーシステムにダウンロードすることで解決しました。そこから、jarをspark submit with --jarオプションで提供しました。

また、注意する必要があるのは、すべてのパッケージをspark 2.1 uber jarでパッケージ化したことです(クラスターはまだ1.6.1にあるため))瓶。

spark-submit --jar /ur/path/spark-sql-kafka-0-10_2.11:2.1.0 --class ClassNm --Other-Options YourJar.jar

0
Gyan