news 2026/10/2 5:20:32

Spark 3.2.0 预编译版实战:从解压到 YARN 集群提交

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
Spark 3.2.0 预编译版实战:从解压到 YARN 集群提交

简介:spark-3.2.0-bin-hadoop3.2.tgz 是 Apache Spark 3.2.0 面向 Hadoop 3.2 环境编译的官方二进制发行包,适合大数据开发工程师、数据科学家及高校学生快速搭建分布式计算与机器学习实验环境。压缩包共 1476 个文件,约 287.02MB,以 462 个 py、238 个 jar、203 个 scala、135 个 java 等源码与依赖文件为主,并含 91 个 txt 说明、32 个 sh 与 16 个 cmd 启动脚本,以及 parquet、orc、avro 等示例数据文件,覆盖 Spark Core、SQL、Streaming、MLlib、GraphX 全部核心组件。该版本在 DataFrame/Dataset 性能、Catalyst 优化器、PySpark 一致性、Kubernetes 原生支持及内存管理上均有改进,并新增时间旅行查询等能力。解压后可直接在 Hadoop 3.2 集群运行 spark-submit、spark-shell 与 pyspark,便于对照源码与脚本理解任务调度、SQL 执行及流处理机制。目前已有 1123 人学习下载,适合需要完整发行包进行本地调试、集群部署与版本对比的读者。

1. 拿到 spark-3.2.0-bin-hadoop3.2.tgz 之后:它到底是什么,能省掉哪些折腾

如果你在搜索框里敲下spark-3.2.0-bin-hadoop3.2.tgz,大概率不是想听 Spark 的发展史,而是手里已经有一个 tgz 包,或者正准备下载一个,想知道它能不能直接跑、跟 Hadoop 怎么对接、解压完该改哪几个文件。这个包是 Apache Spark 官方发布的预编译二进制发行版,版本号 3.2.0,编译时绑定的 Hadoop 版本是 3.2。名字里的bin说明它已经帮你把 Scala、Java 依赖、启动脚本、示例 jar 全部打好了,hadoop3.2说明它默认按 Hadoop 3.2 的客户端接口来编译,连的是 Hadoop 3.x 的 HDFS 和 YARN。

它解决的核心问题是:你不需要自己装 Maven、不需要从源码编译、不需要折腾 Scala 版本对齐,解压就能用spark-shell、spark-submit、pyspark。适合谁?适合要搭本地开发环境的后端或数据开发、要跑课程设计的学生、要在伪分布式或集群上提交第一个 Spark 作业的人。不适合谁?不适合已经用 Databricks 托管服务、或者需要 Spark 3.5 新特性的人。一句话:这是「从零开始安装 Hadoop」之后,最省事的那块拼图。

2. 解压、环境变量与三种启动模式:把 tgz 变成能跑的命令

2.1 解压位置和目录结构决定了后面所有路径

拿到 tgz 之后第一件事不是急着spark-shell,而是选一个不会带空格、不会带中文的路径。Linux 下我一般放/opt/bigdata/,Windows 下放D:\bigdata\。原因很简单:Spark 的启动脚本里大量拼接路径,空格会让classpath断掉,中文在某些 locale 下会乱码。

# Linux / macOS 下解压,注意 -C 指定目标目录 mkdir -p /opt/bigdata tar -zxvf spark-3.2.0-bin-hadoop3.2.tgz -C /opt/bigdata/ # 进入目录看结构,确认关键子目录都在 cd /opt/bigdata/spark-3.2.0-bin-hadoop3.2 ls -1 # bin/ 启动脚本:spark-shell、spark-submit、pyspark # sbin/ 集群脚本:start-master.sh、start-workers.sh # conf/ 配置文件:spark-env.sh、spark-defaults.conf # jars/ 所有依赖 jar,Spark 本体和 Hadoop 客户端都在这里 # examples/ 示例 jar,用来验证环境 # python/ pyspark 的 Python 包

逻辑说明:bin/是给开发者用的,sbin/是给集群管理员用的。jars/里已经包含了 Hadoop 3.2 的客户端 jar,所以只要你连的 HDFS 是 3.x,理论上不用额外拷 jar。参数说明:-C指定解压目录,-z表示 gzip,-x解压,-v显示过程,-f指定文件。这四个参数顺序可以换,但-f必须紧挨文件名。

2.2 环境变量只配三个,多配反而容易冲突

很多人一上来就抄一堆SPARK_HOME、HADOOP_HOME、JAVA_HOME、SCALA_HOME,结果spark-submit报No such file or directory。血泪经验是:Spark 3.2 自带 Scala,不需要你单独装 Scala;Hadoop 客户端 jar 已经在jars/里,不需要HADOOP_HOME也能跑本地模式。真正必须配的只有JAVA_HOME和SPARK_HOME,PATH里加上$SPARK_HOME/bin。

# 编辑 ~/.bashrc 或 /etc/profile export JAVA_HOME=/usr/lib/jvm/java-8-openjdk-amd64 export SPARK_HOME=/opt/bigdata/spark-3.2.0-bin-hadoop3.2 export PATH=$PATH:$SPARK_HOME/bin:$SPARK_HOME/sbin # 让配置生效 source ~/.bashrc # 验证:能打印版本就说明环境变量对了 spark-submit --version

逻辑说明:spark-submit --version会输出 Spark 版本、Scala 版本、Java 版本。如果这里报JAVA_HOME is not set,说明 Java 路径写错了。参数说明:Java 8 是 Spark 3.2 的推荐版本,Java 11 也能跑但部分 API 有警告,Java 17 不建议。SPARK_HOME不要带结尾斜杠,脚本里会自己加。

2.3 三种启动模式:local、standalone、on YARN 怎么选

Spark 3.2 的spark-submit支持多种 master URL,新手最容易懵的是local[*]、spark://host:7077、yarn到底什么时候用哪个。

master URL适用场景是否需要 Hadoop进程数
local[2]本地开发、单元测试否单 JVM 内 2 线程
local[*]本地跑小数据集否用满所有核
spark://host:7077独立集群,不依赖 YARN否Master + Worker
yarn已有 Hadoop 集群,资源统一调度是YARN 分配

常见做法是:开发阶段用local[*],验证逻辑;要连 HDFS 读数据时,把fs.defaultFS指向你的 NameNode;要提交到集群时,再换成yarn。注意local[*]下sc.textFile("hdfs://...")也能跑,因为 Spark 会直接用jars/里的 Hadoop 客户端去连,不需要你启动 YARN。

# 本地模式启动 spark-shell,验证安装 spark-shell --master local[2] # 在 shell 里跑一行 WordCount,确认能出结果 val rdd = sc.parallelize(List("spark", "hadoop", "spark")) rdd.map((_, 1)).reduceByKey(_ + _).collect() # 预期输出:Array((spark,2), (hadoop,1))

逻辑说明:sc是 SparkContext,spark-shell启动时自动创建。parallelize把本地集合转成 RDD,reduceByKey做聚合。参数说明:local[2]表示用 2 个线程,写local[*]会用满 CPU 核数。这一步能跑通,说明 tgz 包本身没问题,后面连不上 HDFS 就是 Hadoop 侧的事。

3. 连 HDFS 与提交 YARN:配置文件改哪几行,参数怎么对齐

3.1 让 Spark 找到 HDFS:core-site.xml 的两种放法

Spark 读 HDFS 靠的是 Hadoop 客户端配置。spark-3.2.0-bin-hadoop3.2.tgz的jars/里已经有hadoop-client相关 jar,但默认不知道你的 NameNode 地址。两种做法:一是把 Hadoop 的core-site.xml和hdfs-site.xml拷到$SPARK_HOME/conf/,二是直接在spark-defaults.conf里写spark.hadoop.fs.defaultFS。我一般用第一种,因为跟 Hadoop 命令行行为一致,排查时少一个变量。

# 假设 Hadoop 装在 /opt/bigdata/hadoop-3.2.1 cp /opt/bigdata/hadoop-3.2.1/etc/hadoop/core-site.xml $SPARK_HOME/conf/ cp /opt/bigdata/hadoop-3.2.1/etc/hadoop/hdfs-site.xml $SPARK_HOME/conf/ # 确认 core-site.xml 里的 fs.defaultFS 指向你的 NameNode grep -A1 "fs.defaultFS" $SPARK_HOME/conf/core-site.xml # 常见值:hdfs://localhost:9000 或 hdfs://namenode-host:8020

逻辑说明:Spark 启动时会自动加载conf/下的core-site.xml,所以拷过来就能生效。参数说明:fs.defaultFS的端口取决于 Hadoop 配置,伪分布式常见 9000 或 8020,集群模式看core-site.xml实际值。如果这里写错,spark-shell里执行sc.textFile("hdfs:///tmp/test.txt")会报Connection refused。

# 验证:在 spark-shell 里读 HDFS 文件 spark-shell --master local[2] val data = sc.textFile("hdfs://localhost:9000/tmp/wordcount.txt") data.count() # 能返回行数说明 HDFS 连通

逻辑说明:textFile返回 RDD[String],count()触发实际读取。如果报FileNotFoundException,说明路径不对;报Connection refused,说明 NameNode 地址或端口不对。注意 HDFS 上文件路径要写全,/tmp/wordcount.txt前面要加hdfs://localhost:9000。

3.2 提交到 YARN:spark-submit 的五个关键参数

当你要把作业扔到已有 Hadoop 集群上跑,--master yarn是入口,但真正决定成败的是--deploy-mode、--executor-memory、--executor-cores、--num-executors、--queue这几个。Hadoop 作业提交到 YARN 的流程里,Spark 会先申请一个 ApplicationMaster 容器,再由 AM 去申请 Executor 容器。

# 提交一个 Spark 作业到 YARN,client 模式便于看日志 spark-submit \ --master yarn \ --deploy-mode client \ --executor-memory 2g \ --executor-cores 2 \ --num-executors 4 \ --queue default \ --class org.apache.spark.examples.SparkPi \ $SPARK_HOME/examples/jars/spark-examples_2.12-3.2.0.jar \ 100

逻辑说明:--class指定主类,最后两个参数是 jar 路径和传给 main 的参数。--deploy-mode client下 Driver 跑在你提交命令的机器上,日志直接打印在终端,适合调试;cluster模式下 Driver 跑在 YARN 容器里,终端看不到日志,要用yarn logs -applicationId查。参数说明:--executor-memory 2g是每个 Executor 的内存,--executor-cores 2是每个 Executor 的核数,--num-executors 4是 Executor 总数。总资源 = 4 * 2g 内存 + 4 * 2 核,要小于队列可用资源,否则会卡在ACCEPTED状态。

注意:--num-executors在--deploy-mode client下由spark-submit直接传给 YARN,但在某些 Hadoop 版本里会被spark.dynamicAllocation覆盖。如果发现 Executor 数量不对,先检查spark-defaults.conf里有没有开启动态分配。

3.3 读 JSON 和写 Parquet:Spark 3.2 里最常用的两个数据入口

Spark 数据分析案例里,读 JSON 和写 Parquet 几乎是标配。Spark 3.2 的spark.read.json支持多行 JSON,但默认只认单行一条记录。如果你的 JSON 文件是格式化过的多行结构,要加multiLine=true。

# pyspark 读 JSON,注意 multiLine 参数 from pyspark.sql import SparkSession spark = SparkSession.builder \ .appName("json-demo") \ .master("local[2]") \ .getOrCreate() # 单行 JSON,直接读 df = spark.read.json("hdfs://localhost:9000/tmp/users.json") df.printSchema() df.show(5) # 多行 JSON,必须加 option df_multi = spark.read.option("multiLine", "true").json("hdfs://localhost:9000/tmp/nested.json") # 写成 Parquet,压缩用 snappy df.write.mode("overwrite").parquet("hdfs://localhost:9000/tmp/users_parquet")

逻辑说明:printSchema()打印推断出的 schema,show(5)显示前 5 行。multiLine=true会让 Spark 先读整个文件再解析,大文件慎用,容易 OOM。参数说明:mode("overwrite")覆盖已有目录,mode("append")追加。Parquet 默认压缩是 snappy,如果集群没装 snappy 本地库,会报native snappy library not available,这时可以换gzip或none。

# 如果 snappy 报错,改用 gzip df.write.mode("overwrite").option("compression", "gzip").parquet("hdfs://localhost:9000/tmp/users_parquet_gz")

逻辑说明:option("compression", "gzip")在写 Parquet 时生效。参数说明:gzip 压缩率高但读写慢,snappy 平衡最好,lz4 更快但压缩率低。生产环境一般用 snappy,本地测试没装 native 库时用 gzip 绕过。

4. 避坑与排查:tgz 包跑不起来时先看这五条

4.1 现象:spark-shell启动报JAVA_HOME is not set

原因:spark-env.sh或系统环境变量里JAVA_HOME没配,或者配了但路径指向 JRE 而不是 JDK。Spark 需要 JDK 里的tools.jar(Java 8)或jdk.compiler模块(Java 11+)。

解决:确认echo $JAVA_HOME输出的是 JDK 根目录,且$JAVA_HOME/bin/javac存在。如果用的是 Java 11,Spark 3.2 能跑但会有Illegal reflective access警告,不影响功能。Java 17 需要加--add-opens参数,不建议新手折腾。

4.2 现象:连 HDFS 报Connection refused或UnknownHostException

原因:core-site.xml里的fs.defaultFS写的是主机名,但本机/etc/hosts没解析;或者 NameNode 根本没启动。

解决:先用hdfs dfs -ls /确认 Hadoop 自己能连上。如果 Hadoop 命令能连、Spark 连不上,检查$SPARK_HOME/conf/下有没有core-site.xml。如果报UnknownHostException,在/etc/hosts里加一行127.0.0.1 namenode-host。

4.3 现象:提交 YARN 后一直卡在ACCEPTED,不变成RUNNING

原因:YARN 队列资源不足,或者--executor-memory加--executor-cores算出来的总资源超过了队列上限。常见于--num-executors设太大。

解决:用yarn application -list看应用状态,用yarn queue -status default看队列资源。先把--num-executors降到 1、--executor-memory降到 1g 试跑,能跑通再往上加。注意spark.yarn.am.memory默认 1g,如果 AM 都申请不到,会直接失败。

4.4 现象:读 JSON 报Failed to read data或 schema 全变成 string

原因:JSON 文件里有格式不一致的行,或者multiLine没开。Spark 的 schema 推断会扫描一部分数据,如果样本里某字段全是 null,推断出来就是 string。

解决:先df.printSchema()看推断结果,如果不对,手动指定 schema。用spark.read.schema(customSchema).json(...)跳过推断。对于多行 JSON,加option("multiLine", "true"),但注意大文件会内存溢出。

4.5 现象:写 Parquet 报native snappy library not available

原因:spark-3.2.0-bin-hadoop3.2.tgz自带的 snappy 是 Java 实现,但某些操作会尝试加载 native 库。在 Windows 或精简版 Linux 上容易触发。

解决:写的时候显式指定option("compression", "gzip")或option("compression", "none")。如果一定要 snappy,在spark-defaults.conf里加spark.sql.parquet.compression.codec=gzip全局改掉。这个坑在课程设计里很常见,因为学生机往往没装libsnappy。

5. 进阶技巧:用 spark-submit 的 --files 和 --jars 把依赖带进集群

5.1 为什么需要 --files 和 --jars

本地跑得好好的作业,一提交到 YARN 就报ClassNotFoundException或FileNotFoundException,八成是依赖没带上去。spark-submit的--jars把额外 jar 分发到每个 Executor 的 classpath,--files把配置文件、字典文件分发到每个 Executor 的工作目录。这两个参数是 Spark 作业从「本地能跑」到「集群能跑」的关键一步。

# 提交时带上自定义 jar 和配置文件 spark-submit \ --master yarn \ --deploy-mode cluster \ --jars /opt/libs/mysql-connector-java-8.0.28.jar,/opt/libs/fastjson-1.2.79.jar \ --files /opt/conf/app.properties,/opt/data/dict.txt \ --executor-memory 4g \ --executor-cores 2 \ --num-executors 8 \ --class com.example.MainJob \ /opt/jobs/my-spark-job.jar \ --input hdfs://localhost:9000/tmp/input \ --output hdfs://localhost:9000/tmp/output

逻辑说明:--jars里的 jar 会被复制到每个 Executor 的$PWD下并加入 classpath。--files里的文件会被复制到每个 Executor 的工作目录,代码里用new File("app.properties")就能读到,不需要写绝对路径。参数说明:多个 jar 用逗号分隔,不要有空格。--files同理。注意--jars里的 jar 如果跟 Spark 自带 jar 冲突,会优先用--jars里的,这可能导致版本问题。

5.2 在代码里读取 --files 分发的文件

# pyspark 里读取 --files 分发的配置文件 from pyspark import SparkFiles # 方式一:通过 SparkFiles.get 拿绝对路径 config_path = SparkFiles.get("app.properties") with open(config_path) as f: content = f.read() # 方式二:直接在当前工作目录找(Executor 的 CWD 就是分发目录) import os if os.path.exists("dict.txt"): with open("dict.txt") as f: dict_data = f.read().splitlines()

逻辑说明:SparkFiles.get("app.properties")返回该文件在 Executor 上的绝对路径,Driver 和 Executor 都能用。方式二依赖 Executor 的 CWD,在cluster模式下更可靠。参数说明:--files分发的文件默认不覆盖同名文件,如果 Executor 上已有同名文件,行为取决于 Spark 版本,3.2 里会覆盖。

5.3 验证依赖是否真的分发成功

提交之后不要只看ApplicationMaster状态,要进 Executor 日志确认。用yarn logs -applicationId application_xxx拉日志,搜app.properties或mysql-connector。如果日志里报FileNotFoundException: app.properties,说明--files没生效,检查路径是不是绝对路径、文件是不是存在。

# 拉取 YARN 应用日志,过滤关键信息 yarn logs -applicationId application_1680000000000_0001 | grep -E "app.properties|mysql-connector|ClassNotFoundException"

逻辑说明:yarn logs会把 AM 和所有 Executor 的日志合并输出,grep过滤出跟依赖相关的行。参数说明:applicationId从yarn application -list里拿。如果日志太大,可以加-log_files指定只拉某个容器的日志。

从那以后我每次提交集群作业前,都强制走一遍「本地local[2]跑通 → 带--jars和--files提交yarn client→ 确认日志无ClassNotFoundException→ 再换cluster模式」这个流程。多花五分钟,省掉半夜被电话叫醒查 YARN 日志的麻烦。希望帮到你。

本文还有配套的精品资源,点击获取

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/10/2 5:19:26

img2threejs实战:用AI将图片生成Three.js 3D代码

1. 一张图变3D模型,这个项目到底在解决什么问题第一次看到 img2threejs 这个项目的时候,我正被一个需求折磨得够呛——客户丢过来十几张产品白底图,要求一周内出一套可以在网页里旋转、缩放、拆解的 3D 展示方案。传统路子无非两条&#xff1…

作者头像 李华
网站建设 2026/10/2 5:19:22

随机森林工程落地:从可复现训练到SHAP可解释性

简介:本资源是一套面向机器学习初学者与数据科学实践者的随机森林模型全栈学习包,聚焦分类与回归任务建模,助力掌握集成学习核心算法原理与工程实现。压缩包共66个文件,涵盖14个C源码(含RF核心算法实现)、1…

作者头像 李华
网站建设 2026/10/2 5:19:22

Nacos服务注册失败排查:客户端、网络、服务端全链路指南

1. 从一次真实的服务注册失败说起凌晨一点半,本地起了一个新的微服务,控制台日志刷过去几屏,服务列表里就是看不到它的身影。日志末尾只留下一句轻飘飘的nacos registry, DEFAULT_GROUP xxx register failed,没有堆栈,…

作者头像 李华
网站建设 2026/10/2 5:18:57

探地雷达图像数据处理实战:从A-scan到B-scan的全流程

简介:一份探地雷达图像数据处理领域的学术研究文献,面向地质探测、考古、土木工程检测等方向的技术人员与研究者,聚焦解决雷达图像信噪比低、目标识别受噪声干扰的问题。内容系统梳理了探地雷达单道数据构成模型,针对直达波、地表…

作者头像 李华
网站建设 2026/10/2 5:18:48

区域电网规划设计全流程拆解:从负荷校验到调压计算

简介:区域电网规划设计参考.pdf是一份完整的电气工程综合课程设计报告,面向电力系统专业学生、电网规划初学者及需要完成课程设计或毕业设计的人员。资源围绕区域电网规划核心流程展开,包括负荷合理性校验、功率平衡计算、110kV网络电压等级确…

作者头像 李华