Sparkアプリケーションをビルドおよびデプロイする際の一般的な問題は次のとおりです。
Java.lang.ClassNotFoundException
。object x is not a member of package y
コンパイルエラー。Java.lang.NoSuchMethodError
これらをどのように解決できますか?
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バージョンと一致する必要があります。デフォルト(ダウンロード可能なバイナリとデフォルトのビルド):
Fat jarに含まれている場合、ワーカーノードで追加のパッケージにアクセスできる必要があります。以下を含む多くのオプションがあります。
--jars
のspark-submit
引数-ローカルjar
ファイルを配布します。--packages
のspark-submit
引数-Mavenリポジトリーから依存関係を取得します。クラスターノードで送信する場合、アプリケーションjar
を--jars
に含める必要があります。
Apache Sparkのクラスパスは動的に構築され(アプリケーションごとのユーザーコードに対応するため)、このような問題に対して脆弱になります。 @ user7337271 の答えは正しいですが、cluster manager( "master")に応じて、さらに懸念があります。あなたが使用しています。
まず、Sparkアプリケーションはこれらのコンポーネントで構成されます(各コンポーネントは個別のJVMであるため、クラスパスに異なるクラスが含まれる可能性があります):
SparkSession
(またはSparkContext
)を作成するクラスターマネージャーに接続して実際の作業を実行するこれらの間の関係は、Apache Sparkの クラスターモードの概要 のこの図で説明されています。
今-これらの各コンポーネントにどのクラスが存在する必要がありますか?
これは、次の図で答えることができます。
それをゆっくりと解析しましょう:
Spark CodeはSparkのライブラリです。それらは[〜#〜] all [〜#〜]3つのコンポーネントに存在する必要があります。これらのコンポーネントには、Sparkところで-Spark作成者は、すべてのコンポーネントのコードをすべてのコンポーネントに含めるように設計を決定しました(たとえば、ドライバーのExecutorでのみ実行するコードを含める)) Sparkの「ファットジャー」(バージョン1.6まで)または「アーカイブ」(2.0、詳細は以下)には、すべてのコンポーネントに必要なコードが含まれており、すべてのコンポーネントで使用できるはずです。
ドライバー専用コードこれは、エグゼキューターで使用する必要のあるものを一切含まないユーザーコードです。つまり、上のトランスフォーメーションで使用されないコードです。 RDD/DataFrame/Dataset。これは、必ずしも分散ユーザーコードから分離する必要はありませんが、分離できます。
Distributed Codeこれはドライバーコードでコンパイルされたユーザーコードですが、Executorで実行する必要があります-実際の変換で使用されるすべてのものを含める必要がありますこのjar。
まっすぐになったので、how各コンポーネントでクラスを正しくロードして、どのルールに従う必要がありますか?
Spark Code:以前の回答の状態として、同じScalaを使用する必要がありますおよびSparkすべてのコンポーネントのバージョン。
1.1Standaloneモードでは、アプリケーション(ドライバー)が接続できる「既存の」Sparkインストールがあります。つまり、すべてのドライバーは、同じSpark versionをマスターとエグゼキューターで実行する必要があります。
1.2YARN/Mesosでは、各アプリケーションは異なるSparkバージョンを使用できますが、同じアプリケーションのすべてのコンポーネントはつまり、バージョンXを使用してドライバーアプリケーションをコンパイルおよびパッケージ化する場合、SparkSessionの起動時に同じバージョンを提供する必要があります(たとえば、YARNを使用する場合はspark.yarn.archive
またはspark.yarn.jars
パラメーターを使用) 。提供するjarファイル/アーカイブには、すべてのSpark依存関係(推移的な依存関係を含む)が含まれている必要があり、出荷されますアプリケーションの起動時にクラスターマネージャーから各エグゼキューターに送信されます。
ドライバーコード:それは完全に-ドライバーコードは、すべてを含む限り、jarファイルの束または「脂肪瓶」として出荷できます。 Spark依存関係+すべてのユーザーコード
分散コード:このコードは、ドライバー上に存在することに加えて、エグゼキューターに出荷する必要があります(これもすべての推移的な依存関係とともに)。これは、spark.jars
パラメーターを使用して行われます。
要約するために、Spark Application(この場合-YARNを使用))を構築およびデプロイするための推奨アプローチを以下に示します。
SparkSession
の起動時に、spark.jars
パラメーターの値として適切なバージョンの分散コードを渡しますlib/
フォルダーの下のすべてのjarを含むアーカイブファイル(gzipなど)の場所をspark.yarn.archive
の値として渡す]User7337271によって既に与えられた非常に広範な答えに加えて、外部依存関係の欠落が問題の原因である場合、依存関係のあるjarをビルドできます。 maven Assemblyプラグイン
その場合、すべてのコアspark=依存関係をビルドシステムで「提供」としてマークし、既に述べたように、それらがランタイムsparkバージョン。
アプリケーションの依存クラスは、起動コマンドのapplication-jarオプションで指定する必要があります。
詳細は Spark documentation で見つけることができます
ドキュメントから取得:
application-jar:アプリケーションとすべての依存関係を含むバンドルされたjarへのパス。 URLは、クラスター内でグローバルに表示される必要があります。たとえば、すべてのノードに存在するhdfs://パスまたはfile://パス
プロジェクトの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 からダウンロードできます
この問題は、アセンブリプラグインを解決する必要があると思います。ファットjarを作成する必要があります。たとえばsbtの場合:
addSbtPlugin("com.eed3si9n" % "sbt-Assembly" % "0.14.0")
でファイル_$PROJECT_ROOT/project/Assembly.sbt
_を追加しますadded some libraries
_ libraryDependencies ++ = Seq( "com.some.company" %% "some-lib"% "1.0.0") `へさらに情報が必要な場合は、 https://github.com/sbt/sbt-Assembly にアクセスしてください