【Scala】Spark/Scalaの開発環境構築 ~ Windows編 ~

■ はじめに

https://dk521123.hatenablog.com/entry/2019/09/18/214814

で、Windows で Spark の実行環境を構築した。
で、最近、AWS Glue4.0になり、Sparkのバージョンもv3.3.0になり
かつ、今の仕事で、Scalaを使うことになった。

そこで、今回は、「Windows上でSpark/Scala開発環境構築」を行う。
色々と、ググってサイトを漁って、そのまま実行しても
うまくいかないところもあったので、整理する。
(本当は、Dockerで一発でばーんって作りたい、、、が、とりあえず1歩目として、、、)

Docker compose ~ LocalStack/Glue4.0 ~
https://dk521123.hatenablog.com/entry/2023/03/25/021432

目次

【1】構築環境
【2】前提条件
 注意点:「環境変数:JAVA_HOME」の設定
【3】Sparkの構築手順
 1)Sparkの設定
 2)環境変数の設定
 3)winutils.exeの設定
 4)構築確認
 トラブル:「spark-shell --version」した際に何も反応しない場合
【3】Spark/ScalaでのHello World
 1)フォルダ構成
 2)サンプル
 3)動作確認

【1】構築環境

AWS Glue4.0想定の開発環境
https://dk521123.hatenablog.com/entry/2023/03/15/000000

* OS : Windows 11
* Apache Spark : v3.3.0 (AWS Glue4.0と同じバージョン)
* Java : OpenJDK v11

【2】前提条件

* Scala用に、以下のモジュールを入れておくこと
~~~~~~
[1] JDK (Java Development Kit ) <= Sparkでも必要
[2] sbt
~~~~~~

 => 構築環境方法によっては、以下の関連記事を参照のこと

Scala ~ 環境構築編 ~
https://dk521123.hatenablog.com/entry/2023/03/10/193805

注意点:「環境変数JAVA_HOME」の設定

* 環境変数「JAVA_HOME」も設定しておくこと ★重要★
* 以下の関連記事を参照のこと。
 => JAVA_HOME を「C:\java\jdk-11」のように設定

【2】Sparkの構築手順

* しつこいようだが、やる前に「JDK」は構築しておくこと

1)Sparkの設定

Apache Spark をダウンロードし、任意の場所に解凍する
(tarファイルの解凍は「※補足:Windows での tar の解凍について」を参照)

(今回は「spark-3.3.0-bin-hadoop3.tgz」)

https://spark.apache.org/downloads.html
https://archive.apache.org/dist/spark/

※補足:Windows での tar の解凍について

Windows 10 の場合は、tarコマンドが備わっている。
(Windows 10未満の場合なら7Zipなどで解凍)

# 確認のためにヘルプを表示
tar --help

# 解凍
tar -zxvf spark-3.3.0-bin-hadoop3.tgz

2)環境変数の設定

* しつこいようだが、「JAVA_HOME」をJDKの時に設定していない場合は
 設定しておくこと ★重要★

[1] SPARK_HOME : Sparkインストール先

* C:\work\spark-3.3.0-bin-hadoop3

[2] HADOOP_HOME : Sparkインストール先

★重要★
* C:\work\spark-3.3.0-bin-hadoop3 or %SPARK_HOME%

[3] Path

* C:\java\jdk-11\bin; C:\work\spark-3.3.0-bin-hadoop3\bin

3)winutils.exeの設定

winutils.exe をダウンロードして、%SPARK_HOME%\bin配下に置く

https://github.com/steveloughran/winutils
https://github.com/steveloughran/winutils/blob/master/hadoop-3.0.0/bin/winutils.exe

4)構築確認

# まずは、バージョン確認
spark-shell --version
~~~~~~~~~~~~~~~~~~~
Welcome to
      ____              __
     / __/__  ___ _____/ /__
    _\ \/ _ \/ _ `/ __/  '_/
   /___/ .__/\_,_/_/ /_/\_\   version 【3.3.0】 << ★ここ、メモっとく(「build.sbt」で使う)
      /_/

Using Scala version 【2.12.15】, OpenJDK 64-Bit Server VM, 11 << ★ここも、メモっとく
Branch HEAD
Compiled by user ubuntu on 2022-06-09T19:24:16Z
Revision f74867bddfbcdd4d08076db36851e88b15e66556
Url https://github.com/apache/spark
Type --help for more information.
~~~~~~~~~~~~~~~~~~~

# spark-shell 実行
spark-shell
# => シェルを終了するときは「:q」を入力

scala> sc <<★入力
res0: org.apache.spark.SparkContext = org.apache.spark.SparkContext@7ccf845a

scala> val result=sc.parallelize(List("hello","world","hi","bye")) <<★入力
result: org.apache.spark.rdd.RDD[String] = ParallelCollectionRDD[1] at parallelize at <console>:23

scala> result.take(2).foreach(println) <<★入力
hello
world

https://www.atmarkit.co.jp/ait/articles/1809/10/news022.html

トラブル:「spark-shell --version」した際に何も反応しない場合

JAVA_HOME を以下のように修正したら動いた。

修正前:「C:\java\jdk-11\bin」
修正後:「C:\java\jdk-11」

【3】Spark/ScalaでのHello World

1)フォルダ構成

* フォルダ構成は、以下の通り。
 => 各ファイルの説明は、後述「2)サンプル」を参照
~~~~~~~~
build.sbt
src
└─main
    └─scala
            HelloWorldApp.scala

* 任意の場所にテストデータを置く
C:\temp\hello.txt
~~~~~~~~

2)サンプル

Hello worldとして、テキストファイル(hello.txt)を読み込んで
「a」「b」が含まれている行をカウントし出力する

注意点

[1] 古いドキュメントの以下の「Self-Contained Applications」

https://spark.apache.org/docs/2.0.2/quick-start.html#self-contained-applications

だと、「simple.sbt」になっているが、「build.sbt」にする必要がある。

【後日談】
以下のSpark v3.3.0のドキュメントには、しっかりフォローされていた

https://spark.apache.org/docs/3.3.0/quick-start.html#self-contained-applications

[2] 「build.sbt」のバージョン値は、「spark-shell --version」で調べて設定
 => 今回は、「Spark: v3.3.0」「Scala : 2.12.15」

build.sbt

name := "sample"

version := "1.0"

scalaVersion := "2.12.15"

libraryDependencies ++= Seq(
  "org.apache.spark" %% "spark-core" % "3.3.0",
  "org.apache.spark" %% "spark-mllib" % "3.3.0",
  "org.apache.spark" %% "spark-sql" % "3.3.0"
)

HelloWorldApp.scala

/* HelloWorldApp.scala */
import org.apache.spark.SparkContext
import org.apache.spark.SparkContext._
import org.apache.spark.SparkConf
import org.apache.spark.sql.SparkSession

object HelloWorldApp {
  def main(args: Array[String]) {
    val spark = SparkSession.builder
     .master("local")
     .appName("Hello_World")
     .config("spark.some.config.option", "some-value")
     .getOrCreate()
    val sparkContext = spark.sparkContext
    val logFile = """C:\temp\hello.txt""" // Should be some file on your system
    val logData = sparkContext.textFile(logFile)
    val numAs = logData.filter(line => line.contains("a")).count()
    val numBs = logData.filter(line => line.contains("b")).count()

    println("**[Hello World]**********")
    println(s"Lines with a: $numAs, Lines with b: $numBs")
    println("*************************")

    sparkContext.stop()
  }
}

hello.txt (テストデータ)

aaabbb << 「a」「b」カウント対象
aaabbb << 「a」「b」カウント対象
111111
222222
aaaaaa << 「a」カウント対象
333333
bbbb11 << 「b」カウント対象
aaaaaa << 「a」カウント対象

3)動作確認

* 「build.sbt」があるフォルダ内で以下を実行。

実行例

$ dir << 確認
2023/03/19  02:08               248 build.sbt
2023/03/19  01:37    <DIR>          src

$ sbt run << 実行
[info] welcome to sbt 1.8.2 (Oracle Corporation Java 11)
...
**[Hello World]**********
Lines with a: 4, Lines with b: 3
*************************
...

参考文献

https://qiita.com/tomotagwork/items/1431f692387242f4a636

関連記事

Apache Spark ~ 環境設定 / Windows編 ~
https://dk521123.hatenablog.com/entry/2019/09/18/214814
Apache Spark ~ 入門編 ~
https://dk521123.hatenablog.com/entry/2019/09/14/123206
Apache Spark ~ 環境設定 / Linux編 ~
https://dk521123.hatenablog.com/entry/2019/11/01/000000
Apache Hadoop ~ 環境設定 / Windows編 ~
https://dk521123.hatenablog.com/entry/2019/12/26/223506
Maven ~ 環境設定編 ~
https://dk521123.hatenablog.com/entry/2010/01/13/215415
Scala ~ 環境構築編 ~
https://dk521123.hatenablog.com/entry/2023/03/10/193805
WSL ~ Docker-CE + Genie / 環境構築編 ~
https://dk521123.hatenablog.com/entry/2021/11/03/003836
WSL ~ Windows Terminal ~
https://dk521123.hatenablog.com/entry/2020/12/10/094125
AWS Glue ~ ローカル環境を作成する / Glue v3.0版 ~
https://dk521123.hatenablog.com/entry/2022/01/31/165650
AWS Glue ~ Scalaでの実装 ~
https://dk521123.hatenablog.com/entry/2023/03/17/000000
LocalStack ~ 入門編 ~
https://dk521123.hatenablog.com/entry/2019/12/14/010524
LocalStack ~ 基本編 ~
https://dk521123.hatenablog.com/entry/2019/12/16/231149
LocalStack ~ awscli-local ~
https://dk521123.hatenablog.com/entry/2020/12/16/211127
Docker ~ 基礎知識編 ~
https://dk521123.hatenablog.com/entry/2020/04/24/160044
Docker compose ~ 環境構築編 ~
https://dk521123.hatenablog.com/entry/2022/04/28/000000
Docker compose ~ 入門編 ~
https://dk521123.hatenablog.com/entry/2022/05/21/222910
Docker compose ~ 基本編 ~
https://dk521123.hatenablog.com/entry/2020/04/11/000000
Docker compose ~ docker-compose.yml ~
https://dk521123.hatenablog.com/entry/2020/12/18/152949
Docker compose ~ Version 2 ~
https://dk521123.hatenablog.com/entry/2023/01/02/000000
Spark ~ FutureAction ~
https://dk521123.hatenablog.com/entry/2023/04/18/234214