web-dev-qa-db-ja.com

Apacheの依存関係の問題を解決するSpark

Sparkアプリケーションをビルドおよびデプロイする際の一般的な問題は次のとおりです。

  • Java.lang.ClassNotFoundException
  • object x is not a member of package yコンパイルエラー。
  • Java.lang.NoSuchMethodError

これらをどのように解決できますか?

30
user7337271

Sparkアプリケーションをビルドおよびデプロイする場合、すべての依存関係には互換性のあるバージョンが必要です。

  • Scalaバージョン。すべてのパッケージは同じメジャー(2.10、2.11、2.12)Scalaバージョンを使用する必要があります。

    次の(誤った)build.sbtを検討してください。

    name := "Simple Project"
    
    version := "1.0"
    
    libraryDependencies ++= Seq(
       "org.Apache.spark" % "spark-core_2.11" % "2.0.1",
       "org.Apache.spark" % "spark-streaming_2.10" % "2.0.1",
       "org.Apache.bahir" % "spark-streaming-Twitter_2.11" % "2.0.1"
    )
    

    Scala 2.10にはspark-streamingを使用し、残りのパッケージはScala 2.11に使用します。 有効ファイルは

    name := "Simple Project"
    
    version := "1.0"
    
    libraryDependencies ++= Seq(
       "org.Apache.spark" % "spark-core_2.11" % "2.0.1",
       "org.Apache.spark" % "spark-streaming_2.11" % "2.0.1",
       "org.Apache.bahir" % "spark-streaming-Twitter_2.11" % "2.0.1"
    )
    

    ただし、バージョンをグローバルに指定し、%%を使用することをお勧めします。

    name := "Simple Project"
    
    version := "1.0"
    
    scalaVersion := "2.11.7"
    
    libraryDependencies ++= Seq(
       "org.Apache.spark" %% "spark-core" % "2.0.1",
       "org.Apache.spark" %% "spark-streaming" % "2.0.1",
       "org.Apache.bahir" %% "spark-streaming-Twitter" % "2.0.1"
    )
    

    同様にMavenでも:

    <project>
      <groupId>com.example</groupId>
      <artifactId>simple-project</artifactId>
      <modelVersion>4.0.0</modelVersion>
      <name>Simple Project</name>
      <packaging>jar</packaging>
      <version>1.0</version>
      <properties>
        <spark.version>2.0.1</spark.version>
      </properties> 
      <dependencies>
        <dependency> <!-- Spark dependency -->
          <groupId>org.Apache.spark</groupId>
          <artifactId>spark-core_2.11</artifactId>
          <version>${spark.version}</version>
        </dependency>
        <dependency>
          <groupId>org.Apache.spark</groupId>
          <artifactId>spark-streaming_2.11</artifactId>
          <version>${spark.version}</version>
        </dependency> 
        <dependency>
          <groupId>org.Apache.bahir</groupId>
          <artifactId>spark-streaming-Twitter_2.11</artifactId>
          <version>${spark.version}</version>
        </dependency>
      </dependencies>
    </project>
    
  • Sparkバージョンすべてのパッケージは、同じメジャーSparkバージョン(1.6、2.0、2.1、...)を使用する必要があります。

    次の(誤った)build.sbtを検討してください。

    name := "Simple Project"
    
    version := "1.0"
    
    libraryDependencies ++= Seq(
       "org.Apache.spark" % "spark-core_2.11" % "1.6.1",
       "org.Apache.spark" % "spark-streaming_2.10" % "2.0.1",
       "org.Apache.bahir" % "spark-streaming-Twitter_2.11" % "2.0.1"
    )
    

    spark-core 1.6を使用し、残りのコンポーネントはSpark 2.0にあります。 有効ファイルは

    name := "Simple Project"
    
    version := "1.0"
    
    libraryDependencies ++= Seq(
       "org.Apache.spark" % "spark-core_2.11" % "2.0.1",
       "org.Apache.spark" % "spark-streaming_2.10" % "2.0.1",
       "org.Apache.bahir" % "spark-streaming-Twitter_2.11" % "2.0.1"
    )
    

    しかし、変数を使用することをお勧めします。

    name := "Simple Project"
    
    version := "1.0"
    
    val sparkVersion = "2.0.1"
    
    libraryDependencies ++= Seq(
       "org.Apache.spark" % "spark-core_2.11" % sparkVersion,
       "org.Apache.spark" % "spark-streaming_2.10" % sparkVersion,
       "org.Apache.bahir" % "spark-streaming-Twitter_2.11" % sparkVersion
    )
    

    同様にMavenでも:

    <project>
      <groupId>com.example</groupId>
      <artifactId>simple-project</artifactId>
      <modelVersion>4.0.0</modelVersion>
      <name>Simple Project</name>
      <packaging>jar</packaging>
      <version>1.0</version>
      <properties>
        <spark.version>2.0.1</spark.version>
        <scala.version>2.11</scala.version>
      </properties> 
      <dependencies>
        <dependency> <!-- Spark dependency -->
          <groupId>org.Apache.spark</groupId>
          <artifactId>spark-core_${scala.version}</artifactId>
          <version>${spark.version}</version>
        </dependency>
        <dependency>
          <groupId>org.Apache.spark</groupId>
          <artifactId>spark-streaming_${scala.version}</artifactId>
          <version>${spark.version}</version>
        </dependency> 
        <dependency>
          <groupId>org.Apache.bahir</groupId>
          <artifactId>spark-streaming-Twitter_${scala.version}</artifactId>
          <version>${spark.version}</version>
        </dependency>
      </dependencies>
    </project>
    
  • Spark依存関係で使用されるSparkバージョンは、SparkインストールのSparkバージョンと一致する必要があります。たとえば、クラスターで1.6.1を使用する場合、jarを作成するには1.6.1を使用する必要があります。マイナーバージョンの不一致は常に受け入れられるとは限りません。

  • Jarのビルドに使用されるScalaバージョンは、デプロイされたSparkのビルドに使用されるScalaバージョンと一致する必要があります。デフォルト(ダウンロード可能なバイナリとデフォルトのビルド):

    • Spark 1.x-> Scala 2.10
    • Spark 2.x-> Scala 2.11
  • Fat jarに含まれている場合、ワーカーノードで追加のパッケージにアクセスできる必要があります。以下を含む多くのオプションがあります。

    • --jarsspark-submit引数-ローカルjarファイルを配布します。
    • --packagesspark-submit引数-Mavenリポジトリーから依存関係を取得します。

    クラスターノードで送信する場合、アプリケーションjar--jarsに含める必要があります。

18
user7337271

Apache Sparkのクラスパスは動的に構築され(アプリケーションごとのユーザーコードに対応するため)、このような問題に対して脆弱になります。 @ user7337271 の答えは正しいですが、cluster manager( "master")に応じて、さらに懸念があります。あなたが使用しています。

まず、Sparkアプリケーションはこれらのコンポーネントで構成されます(各コンポーネントは個別のJVMであるため、クラスパスに異なるクラスが含まれる可能性があります):

  1. Driver:それはyourアプリケーションがSparkSession(またはSparkContext)を作成するクラスターマネージャーに接続して実際の作業を実行する
  2. Cluster Manager:クラスターへの「エントリポイント」として機能し、executorの割り当てを担当します各アプリケーション。 Sparkでサポートされているいくつかの異なるタイプがあります:スタンドアロン、YARN、およびMesos。以下で説明します。
  3. Executors:これらはクラスタノード上のプロセスであり、実際の作業を実行しています(Sparkタスク

これらの間の関係は、Apache Sparkの クラスターモードの概要 のこの図で説明されています。

Cluster Mode Overview

今-これらの各コンポーネントにどのクラスが存在する必要がありますか?

これは、次の図で答えることができます。

Class placement overview

それをゆっくりと解析しましょう:

  1. Spark CodeはSparkのライブラリです。それらは[〜#〜] all [〜#〜]3つのコンポーネントに存在する必要があります。これらのコンポーネントには、Sparkところで-Spark作成者は、すべてのコンポーネントのコードをすべてのコンポーネントに含めるように設計を決定しました(たとえば、ドライバーのExecutorでのみ実行するコードを含める)) Sparkの「ファットジャー」(バージョン1.6まで)または「アーカイブ」(2.0、詳細は以下)には、すべてのコンポーネントに必要なコードが含まれており、すべてのコンポーネントで使用できるはずです。

  2. ドライバー専用コードこれは、エグゼキューターで使用する必要のあるものを一切含まないユーザーコードです。つまり、上のトランスフォーメーションで使用されないコードです。 RDD/DataFrame/Dataset。これは、必ずしも分散ユーザーコードから分離する必要はありませんが、分離できます。

  3. Distributed Codeこれはドライバーコードでコンパイルされたユーザーコードですが、Executorで実行する必要があります-実際の変換で使用されるすべてのものを含める必要がありますこのjar。

まっすぐになったので、how各コンポーネントでクラスを正しくロードして、どのルールに従う必要がありますか?

  1. Spark Code:以前の回答の状態として、同じScalaを使用する必要がありますおよびSparkすべてのコンポーネントのバージョン。

    1.1Standaloneモードでは、アプリケーション(ドライバー)が接続できる「既存の」Sparkインストールがあります。つまり、すべてのドライバーは、同じSpark versionをマスターとエグゼキューターで実行する必要があります。

    1.2YARN/Mesosでは、各アプリケーションは異なるSparkバージョンを使用できますが、同じアプリケーションのすべてのコンポーネントはつまり、バージョンXを使用してドライバーアプリケーションをコンパイルおよびパッケージ化する場合、SparkSessionの起動時に同じバージョンを提供する必要があります(たとえば、YARNを使用する場合はspark.yarn.archiveまたはspark.yarn.jarsパラメーターを使用) 。提供するjarファイル/アーカイブには、すべてのSpark依存関係(推移的な依存関係を含む)が含まれている必要があり、出荷されますアプリケーションの起動時にクラスターマネージャーから各エグゼキューターに送信されます。

  2. ドライバーコード:それは完全に-ドライバーコードは、すべてを含む限り、jarファイルの束または「脂肪瓶」として出荷できます。 Spark依存関係+すべてのユーザーコード

  3. 分散コード:このコードは、ドライバー上に存在することに加えて、エグゼキューターに出荷する必要があります(これもすべての推移的な依存関係とともに)。これは、spark.jarsパラメーターを使用して行われます。

要約するために、Spark Application(この場合-YARNを使用))を構築およびデプロイするための推奨アプローチを以下に示します。

  • 分散コードでライブラリを作成し、「通常の」jar(依存関係を記述した.pomファイルを含む)と「脂肪jar」(そのすべての推移的な依存関係を含む)の両方としてパッケージ化します。
  • 分散コードライブラリとApache Spark(特定のバージョンで)にコンパイル依存関係があるドライバーアプリケーションを作成します。
  • ドライバーアプリケーションをファットjarにパッケージ化し、ドライバーに展開します
  • SparkSessionの起動時に、spark.jarsパラメーターの値として適切なバージョンの分散コードを渡します
  • ダウンロードしたSparkバイナリのlib/フォルダーの下のすべてのjarを含むアーカイブファイル(gzipなど)の場所をspark.yarn.archiveの値として渡す]
28
Tzach Zohar

User7337271によって既に与えられた非常に広範な答えに加えて、外部依存関係の欠落が問題の原因である場合、依存関係のあるjarをビルドできます。 maven Assemblyプラグイン

その場合、すべてのコアspark=依存関係をビルドシステムで「提供」としてマークし、既に述べたように、それらがランタイムsparkバージョン。

3
winson

アプリケーションの依存クラスは、起動コマンドのapplication-jarオプションで指定する必要があります。

詳細は Spark documentation で見つけることができます

ドキュメントから取得:

application-jar:アプリケーションとすべての依存関係を含むバンドルされたjarへのパス。 URLは、クラスター内でグローバルに表示される必要があります。たとえば、すべてのノードに存在するhdfs://パスまたはfile://パス

2
user7344209

プロジェクトのspark-2.4.0-bin-hadoop2.7\spark-2.4.0-bin-hadoop2.7\jarsからすべてのjarファイルを追加します。 spark-2.4.0-bin-hadoop2.7は https://spark.Apache.org/downloads.html からダウンロードできます

0

この問題は、アセンブリプラグインを解決する必要があると思います。ファットjarを作成する必要があります。たとえばsbtの場合:

  • コードaddSbtPlugin("com.eed3si9n" % "sbt-Assembly" % "0.14.0")でファイル_$PROJECT_ROOT/project/Assembly.sbt_を追加します
  • build.sbt _added some libraries_ libraryDependencies ++ = Seq( "com.some.company" %% "some-lib"% "1.0.0") `へ
  • sbtコンソールで「Assembly」と入力し、アセンブリjarをデプロイします

さらに情報が必要な場合は、 https://github.com/sbt/sbt-Assembly にアクセスしてください

0
dmitrybugakov