Spark 4.1.2 + Scala 2.13 开发环境:IntelliJ IDEA 2024.3 与 SBT 1.9.9 配置实战
Spark 4.1.2 + Scala 2.13 开发环境:IntelliJ IDEA 2024.3 与 SBT 1.9.9 配置实战
对于希望构建现代化Spark应用的开发者而言,搭建一个高效的本地开发环境至关重要。本文将详细介绍如何在IntelliJ IDEA 2024.3中配置Spark 4.1.2与Scala 2.13的开发环境,使用SBT 1.9.9作为构建工具,并提供完整的项目配置示例。
1. 环境准备与工具安装
在开始Spark项目开发前,需要确保系统中已安装以下基础组件:
- Java Development Kit (JDK) :Spark 4.1.2要求JDK 8或更高版本,推荐使用JDK 11或17以获得最佳兼容性
- Scala 2.13 :与Spark 4.1.2兼容的Scala版本
- IntelliJ IDEA 2024.3 :安装时需包含Scala插件
- SBT 1.9.9 :Scala的构建工具
1.1 JDK安装验证
在终端中运行以下命令检查Java版本:
java -version
预期输出应类似于:
openjdk version "17.0.3" 2022-04-19
OpenJDK Runtime Environment (build 17.0.3+7)
OpenJDK 64-Bit Server VM (build 17.0.3+7, mixed mode)
1.2 Scala环境配置
使用SDKMAN!安装特定版本的Scala:
sdk install scala 2.13.12
安装后验证版本:
scala -version
正确配置应显示:
Scala code runner version 2.13.12 -- Copyright 2002-2023, LAMP/EPFL and Lightbend, Inc.
2. IntelliJ IDEA项目初始化
2.1 创建新SBT项目
- 打开IntelliJ IDEA,选择"New Project"
- 在左侧菜单中选择"Scala",右侧选择"SBT"
- 设置项目名称和位置
- 确保SDK选择正确的JDK版本(如JDK 17)
- SBT版本指定为1.9.9,Scala版本选择2.13.12
- 点击"Create"完成项目创建
2.2 基础项目结构
创建完成后,项目应具有以下目录结构:
my-spark-project/
├── build.sbt
├── project/
│ ├── build.properties
│ └── plugins.sbt
├── src/
│ ├── main/
│ │ ├── resources/
│ │ └── scala/
│ └── test/
│ ├── resources/
│ └── scala/
└── target/
3. 配置build.sbt文件
build.sbt 是SBT项目的核心配置文件。以下是Spark 4.1.2与Scala 2.13的完整配置示例:
ThisBuild / version := "1.0.0"
ThisBuild / scalaVersion := "2.13.12"
ThisBuild / organization := "com.example"
// 解决Java模块系统在Spark中的警告
ThisBuild / run / fork := true
ThisBuild / run / javaOptions += "--add-opens=java.base/sun.nio.ch=ALL-UNNAMED"
lazy val root = (project in file("."))
.settings(
name := "spark-scala-demo",
libraryDependencies ++= Seq(
// Spark核心依赖
"org.apache.spark" %% "spark-core" % "4.1.2",
"org.apache.spark" %% "spark-sql" % "4.1.2",
// 测试依赖
"org.scalatest" %% "scalatest" % "3.2.16" % Test,
// 日志处理
"org.apache.logging.log4j" % "log4j-api" % "2.20.0",
"org.apache.logging.log4j" % "log4j-core" % "2.20.0",
"org.apache.logging.log4j" % "log4j-slf4j-impl" % "2.20.0"
),
// 并行执行设置
parallelExecution in Test := false,
// 编译器选项
scalacOptions ++= Seq(
"-deprecation",
"-feature",
"-unchecked",
"-Xlint",
"-Ywarn-dead-code",
"-Ywarn-numeric-widen",
"-Ywarn-unused",
"-Ywarn-value-discard"
),
// JVM运行参数
javaOptions ++= Seq(
"-Xms512M",
"-Xmx2G",
"-XX:+UseG1GC",
"-Dlog4j.configurationFile=log4j2.properties"
)
)
3.1 关键配置说明
-
Spark依赖管理 :
spark-core和spark-sql是Spark的基础模块- 使用
%%确保获取与Scala 2.13兼容的版本
-
日志配置 :
- 添加Log4j2依赖以避免Spark的日志冲突
- 需要在
src/main/resources下添加log4j2.properties文件
-
JVM参数 :
- 设置合理的堆内存大小(-Xms和-Xmx)
- 使用G1垃圾收集器提高性能
4. 解决常见依赖冲突
Spark项目经常会遇到依赖冲突问题,以下是两个典型场景的解决方案:
4.1 Guava版本冲突
Spark 4.1.2依赖Guava 14.0.1,而许多现代库需要更高版本。解决方案:
dependencyOverrides += "com.google.guava" % "guava" % "32.1.3-jre"
4.2 Jackson版本冲突
Spark自带Jackson模块,可能与用户引入的版本冲突:
dependencyOverrides ++= Seq(
"com.fasterxml.jackson.core" % "jackson-core" % "2.15.3",
"com.fasterxml.jackson.core" % "jackson-databind" % "2.15.3",
"com.fasterxml.jackson.module" %% "jackson-module-scala" % "2.15.3"
)
提示:使用
sbt dependencyTree命令可以查看完整的依赖关系树,帮助识别冲突
5. 编写第一个Spark应用
在 src/main/scala 目录下创建 SimpleApp.scala 文件:
import org.apache.spark.sql.SparkSession
object SimpleApp {
def main(args: Array[String]): Unit = {
// 创建SparkSession
val spark = SparkSession.builder()
.appName("Simple Application")
.master("local[*]") // 使用本地模式,所有可用核心
.config("spark.sql.shuffle.partitions", "4") // 优化小数据集性能
.getOrCreate()
// 减少日志输出
spark.sparkContext.setLogLevel("WARN")
import spark.implicits._
try {
// 创建示例DataFrame
val data = Seq(
("Java", 20000),
("Python", 100000),
("Scala", 3000)
)
val df = data.toDF("language", "users")
// 执行简单转换
val filteredDF = df.filter($"users" > 10000)
// 显示结果
filteredDF.show()
// 执行聚合操作
df.createOrReplaceTempView("languages")
val resultDF = spark.sql(
"""
|SELECT language, users
|FROM languages
|WHERE users > (SELECT AVG(users) FROM languages)
|""".stripMargin)
resultDF.show()
} finally {
// 确保SparkSession被正确关闭
spark.stop()
}
}
}
5.1 运行配置
- 在IntelliJ中右键点击
SimpleApp对象 - 选择"Run 'SimpleApp'"
- 或创建自定义运行配置:
- Main class:
SimpleApp - VM options:
-Xmx2G -Dlog4j.configurationFile=log4j2.properties - Working directory: 项目根目录
- Environment variables: 可添加
SPARK_LOCAL_IP=127.0.0.1
- Main class:
6. 性能优化配置
在 build.sbt 中添加以下配置可显著提升本地开发体验:
// 针对本地开发的优化配置
fork in run := true
outputStrategy := Some(StdoutOutput)
connectInput in run := true
// 内存设置
javaOptions in run ++= Seq(
"-Xms1G",
"-Xmx4G",
"-XX:MaxMetaspaceSize=1G",
"-XX:+UseG1GC",
"-XX:MaxGCPauseMillis=200",
"-Djava.net.preferIPv4Stack=true"
)
// 针对Spark的特定配置
javaOptions in run ++= Seq(
"-Dspark.master=local[*]",
"-Dspark.driver.memory=2G",
"-Dspark.executor.memory=2G",
"-Dspark.ui.enabled=true",
"-Dspark.ui.port=4040"
)
6.1 日志配置示例
在 src/main/resources/log4j2.properties 中添加:
rootLogger.level = WARN
rootLogger.appenderRef.stdout.ref = console
appender.console.type = Console
appender.console.name = console
appender.console.layout.type = PatternLayout
appender.console.layout.pattern = %d{yy/MM/dd HH:mm:ss} %p %c{1}: %m%n
logger.spark.name = org.apache.spark
logger.spark.level = WARN
logger.jetty.name = org.sparkproject.jetty
logger.jetty.level = WARN
7. 高级项目配置
7.1 多模块项目结构
对于复杂项目,可以拆分为多个模块:
lazy val core = (project in file("core"))
.settings(
name := "spark-core",
// 核心配置
)
lazy val utils = (project in file("utils"))
.settings(
name := "spark-utils",
// 工具类配置
)
lazy val app = (project in file("app"))
.dependsOn(core, utils)
.settings(
name := "spark-app",
// 应用配置
)
7.2 打包配置
添加assembly插件用于创建可部署的fat JAR:
- 在
project/plugins.sbt中添加:
addSbtPlugin("com.eed3si9n" % "sbt-assembly" % "2.1.1")
- 在
build.sbt中添加合并策略:
assembly / assemblyMergeStrategy := {
case PathList("META-INF", "services", xs @ _*) => MergeStrategy.filterDistinctLines
case PathList("META-INF", xs @ _*) => MergeStrategy.discard
case "reference.conf" => MergeStrategy.concat
case _ => MergeStrategy.first
}
- 使用命令创建部署包:
sbt assembly
8. 实际开发技巧
8.1 使用Spark Shell进行快速验证
在SBT项目中集成Spark Shell功能:
lazy val sparkShell = taskKey[Unit]("Start Spark shell with project dependencies")
sparkShell := {
val sbtClasspath = (fullClasspath in Runtime).value.files.absString
val cmd = s"""spark-shell --jars "$sbtClasspath""""
println(s"Running: $cmd")
cmd !
}
运行方式:
sbt sparkShell
8.2 性能监控配置
在 spark-defaults.conf 中添加(位于 src/main/resources ):
spark.eventLog.enabled true
spark.eventLog.dir file:///tmp/spark-events
spark.history.fs.logDirectory file:///tmp/spark-events
spark.metrics.conf.*.sink.console.class org.apache.spark.metrics.sink.ConsoleSink
8.3 单元测试示例
在 src/test/scala 中创建测试类:
import org.apache.spark.sql.SparkSession
import org.scalatest.BeforeAndAfterAll
import org.scalatest.funsuite.AnyFunSuite
class SparkTestExample extends AnyFunSuite with BeforeAndAfterAll {
private var spark: SparkSession = _
override def beforeAll(): Unit = {
spark = SparkSession.builder()
.appName("Testing")
.master("local[2]")
.config("spark.ui.enabled", "false")
.getOrCreate()
}
override def afterAll(): Unit = {
if (spark != null) {
spark.stop()
}
}
test("simple dataframe creation") {
import spark.implicits._
val data = Seq(("a", 1), ("b", 2))
val df = data.toDF("letter", "number")
assert(df.count() == 2)
assert(df.columns.length == 2)
}
}
运行测试:
sbt test
更多推荐




所有评论(0)