简介:本资源为燕山大学大数据分析课程英文实验报告,面向高校计算机、数据科学相关专业学生及Hadoop/Spark初学者,聚焦分布式环境搭建与机器学习算法实践。报告完整覆盖四大核心实验:Hadoop与Spark集群部署(含Ubuntu 14.04虚拟机环境配置、JDK 1.8/Scala 2.12.6/Hadoop 2.7.7/Spark 2.4.4全栈安装)、WordCount程序开发与UI监控验证、基于MLlib的线性回归建模、支持向量机(SVM)分类(含Recall/Precision/F1-score/Accuracy多维评估)以及K-means聚类实现。资源为单个762KB Word文档(.doc格式),内容包含实验目的、环境配置清单、完整Scala代码、测试输入样例、运行结果截图及关键问题说明,结构清晰、步骤翔实,便于对照复现与原理理解。目前已有303人学习下载,是掌握大数据平台搭建与主流ML算法落地的实用型教学参考材料。
1. Hadoop + Spark 2.4.4 环境搭建:Ubuntu 14.04 上最易翻车的组合,装错一个版本就卡在 50070 页面打不开
你不是第一个被localhost:50070白屏劝退的人——我见过太多人在 VMware 里配完 Hadoop,浏览器一刷出来个「This site can’t be reached」,然后默默删掉整个虚拟机重装。这不是玄学,是 Ubuntu 14.04、JDK 1.8、Scala 2.12.6、Hadoop 2.7.7 和 Spark 2.4.4-bin-hadoop2.7 这六者之间严丝合缝的依赖链在作祟。少一个.bashrc里的export,漏一行core-site.xml的fs.defaultFS配置,或者spark-env.sh里JAVA_HOME多了个末尾斜杠,服务就起不来;更别提 Spark 2.4.4 明明标着 “bin-hadoop2.7”,却对 Hadoop 2.7.7 的 native lib 路径极其敏感,libhadoop.so找不到直接报UnsatisfiedLinkError。这套环境不是为“跑通 demo”设计的,它是为“理解分布式计算底层握手逻辑”而设的黑匣子——你得亲手拧紧每一颗螺丝,才能让 NameNode、DataNode、Master、Worker 全部亮起绿灯。适合正在做大数据课程实验、需要交完整可复现报告的本科生,也适合想回溯 Spark 2.x 时代部署逻辑的运维老手。它不时髦,但真实;不宽容,但教人敬畏。
2. 环境准备与基础组件安装:从 VMware 虚拟机到 JDK/Scala 的逐层夯实
2.1 创建标准化虚拟机:Ubuntu 14.04 Server 的关键配置项
VMware Workstation Pro 16 是本实验的指定平台,不是因为它多先进,而是因为 Ubuntu 14.04 Server 的内核(3.13.0)与 Hadoop 2.7.x 的 native 编译兼容性经过了多年课堂验证。新建虚拟机时,请务必确认以下三项:
内存分配 ≥ 4GB:Hadoop 的 NameNode + SecondaryNameNode + DataNode + Spark Master + Worker 五进程常驻,2GB 内存下
jps只能看到一半进程,且start-dfs.sh后jps中缺 DataNode 是常态;网络模式选 NAT + 手动固定 IP:实验截图中
192.168.37.146是典型 NAT 子网地址,需在 VMware 网络编辑器中确认 NAT 设置的子网为192.168.37.0/24,并在 Ubuntu 中执行:sudo vim /etc/network/interfaces追加:
auto eth0 iface eth0 inet static address 192.168.37.146 netmask 255.255.255.0 gateway 192.168.37.2提示:
gateway地址必须与 VMware NAT 设置中“NAT 设置”页的网关一致,否则ping www.baidu.com通但hadoop fs -ls /报Connection refused。关闭 IPv6:Hadoop 2.7 默认尝试绑定
::1,而 Ubuntu 14.04 的 IPv6 stack 在虚拟机中常不稳定。永久禁用:echo "net.ipv6.conf.all.disable_ipv6 = 1" | sudo tee -a /etc/sysctl.conf echo "net.ipv6.conf.default.disable_ipv6 = 1" | sudo tee -a /etc/sysctl.conf sudo sysctl -p
2.2 JDK 1.8 安装:必须用 tar.gz 包,拒绝 apt-get openjdk
Ubuntu 14.04 自带的openjdk-7-jre或openjdk-8-jre会导致 Hadoop 启动时报UnsupportedClassVersionError——因为 Hadoop 2.7.7 编译目标是 JDK 1.8 的 class 文件格式(52.0),而部分 openjdk 包含非标准字节码。必须使用 Oracle 官方 JDK 1.8u202(实验验证最稳版本):
# 下载 jdk-8u202-linux-x64.tar.gz(需手动从 Oracle 归档下载,注意接受许可协议) sudo mkdir -p /usr/lib/jvm sudo tar -zxvf jdk-8u202-linux-x64.tar.gz -C /usr/lib/jvm/ sudo update-alternatives --install "/usr/bin/java" "java" "/usr/lib/jvm/jdk1.8.0_202/bin/java" 1 sudo update-alternatives --install "/usr/bin/javac" "javac" "/usr/lib/jvm/jdk1.8.0_202/bin/javac" 1 sudo update-alternatives --set java /usr/lib/jvm/jdk1.8.0_202/bin/java sudo update-alternatives --set javac /usr/lib/jvm/jdk1.8.0_202/bin/javac验证:
java -version # 必须输出 java version "1.8.0_202" echo $JAVA_HOME # 必须为空?不,要手动设!见下一步参数说明:
update-alternatives是 Ubuntu 管理多版本 JDK 的标准方式,比直接改/etc/environment更可靠;--set命令确保系统级默认指向正确路径,避免spark-shell启动时因JAVA_HOME未识别而 fallback 到错误版本。
2.3 Scala 2.12.6 安装:Spark 2.4.4 的硬性绑定版本
Spark 2.4.4 源码编译时明确指定 Scala 2.12.6(见其pom.xml中<scala.version>2.12.6</scala.version>),若装 2.12.10 或 2.13.x,spark-submit会报java.lang.NoClassDefFoundError: scala/Product——这是 Scala 二进制不兼容的典型症状。安装方式必须为解压即用:
wget https://downloads.lightbend.com/scala/2.12.6/scala-2.12.6.tgz sudo tar -zxvf scala-2.12.6.tgz -C /opt/ sudo ln -s /opt/scala-2.12.6 /opt/scala写入环境变量(追加到~/.bashrc):
export SCALA_HOME=/opt/scala export PATH=$SCALA_HOME/bin:$PATH立即生效:
source ~/.bashrc scala -version # 必须输出 Scala code runner version 2.12.6逻辑说明:Spark 2.4.4 的
bin/spark-shell脚本内部硬编码调用$SCALA_HOME/bin/scala,若SCALA_HOME指向错误版本或路径含空格,脚本会静默失败,只打印Spark context available as 'sc'却无法执行任何 RDD 操作。
3. Hadoop 2.7.7 部署:从免密 SSH 到四文件 XML 配置的闭环
3.1 配置 SSH 免密登录:单节点伪分布的“心跳线”
Hadoop 启动脚本(如start-dfs.sh)本质是通过ssh localhost串行拉起各进程。Ubuntu 14.04 默认禁用root登录,且sshd_config中PermitRootLogin为without-password,必须显式启用并配置密钥:
# 生成密钥(一路回车) ssh-keygen -t rsa -P '' -f ~/.ssh/id_rsa # 将公钥追加到 authorized_keys cat ~/.ssh/id_rsa.pub >> ~/.ssh/authorized_keys # 修复权限(关键!sshd 对权限极其敏感) chmod 0600 ~/.ssh/authorized_keys chmod 0700 ~/.ssh # 测试 ssh localhost # 必须无需密码直接登录,否则 start-dfs.sh 会卡住注意:若
ssh localhost提示Permission denied (publickey),检查/etc/ssh/sshd_config中PubkeyAuthentication yes和AuthorizedKeysFile .ssh/authorized_keys是否启用,并重启sudo service ssh restart。
3.2 Hadoop 目录结构与环境变量固化
解压 Hadoop 2.7.7 到/usr/local/并建立软链,是避免后续 Spark 配置中路径硬编码出错的保险做法:
sudo tar -zxvf hadoop-2.7.7.tar.gz -C /usr/local/ sudo chown -R $USER:$USER /usr/local/hadoop-2.7.7 sudo ln -s /usr/local/hadoop-2.7.7 /usr/local/hadoop写入~/.bashrc(注意:必须在JAVA_HOME之后):
export HADOOP_HOME=/usr/local/hadoop export HADOOP_INSTALL=$HADOOP_HOME export HADOOP_MAPRED_HOME=$HADOOP_HOME export HADOOP_COMMON_HOME=$HADOOP_HOME export HADOOP_HDFS_HOME=$HADOOP_HOME export YARN_HOME=$HADOOP_HOME export HADOOP_COMMON_LIB_NATIVE_DIR=$HADOOP_HOME/lib/native export PATH=$PATH:$HADOOP_HOME/sbin:$HADOOP_HOME/bin export HADOOP_OPTS="-Djava.library.path=$HADOOP_HOME/lib/native"参数说明:
HADOOP_COMMON_LIB_NATIVE_DIR指向 native 库路径,HADOOP_OPTS中的-Djava.library.path是 JVM 加载libhadoop.so的唯一途径;漏掉任一,hadoop version会报Unable to load native-hadoop library警告,start-dfs.sh后 DataNode 无法注册。
3.3 四大核心 XML 配置文件详解与最小化修改
Hadoop 2.7.7 伪分布模式只需修改四个文件,但每处都是启动成败的关键开关:
core-site.xml(HDFS 入口定义)
<configuration> <property> <name>fs.defaultFS</name> <value>hdfs://localhost:9000</value> <!-- 必须与 hdfs namenode -format 中的 URI 一致 --> </property> </configuration>hdfs-site.xml(NameNode/DataNode 存储路径)
<configuration> <property> <name>dfs.replication</name> <value>1</value> <!-- 单节点必须为 1,否则 DataNode 不上报 --> </property> <property> <name>dfs.namenode.name.dir</name> <value>file:/usr/local/hadoop_store/hdfs/namenode</value> <!-- 绝对路径,提前 mkdir --> </property> <property> <name>dfs.datanode.data.dir</name> <value>file:/usr/local/hadoop_store/hdfs/datanode</value> <!-- 绝对路径,提前 mkdir --> </property> </configuration>mapred-site.xml(MapReduce 框架指定)
<configuration> <property> <name>mapreduce.framework.name</name> <value>yarn</value> <!-- 必须为 yarn,否则 MR 作业无法提交 --> </property> </configuration>yarn-site.xml(YARN 资源管理)
<configuration> <property> <name>yarn.nodemanager.aux-services</name> <value>mapreduce_shuffle</value> <!-- 必须与 mapred-site.xml 中 shuffle service 名一致 --> </property> <property> <name>yarn.resourcemanager.hostname</name> <value>localhost</value> <!-- 必须为 localhost,不能是 127.0.0.1 --> </property> </configuration>逻辑说明:
dfs.namenode.name.dir和dfs.datanode.data.dir对应的目录必须由用户手动创建并赋予读写权限(sudo mkdir -p ... && sudo chown -R $USER:$USER ...),否则hdfs namenode -format会静默失败,start-dfs.sh后jps看不到 NameNode。
4. Spark 2.4.4 集成与启动:如何让 Spark 认出 Hadoop 的 HDFS 和 YARN
4.1 Spark 解压与环境变量联动
Spark 2.4.4-bin-hadoop2.7 是预编译包,绝不能解压到/usr/local/spark后再手动替换hadoop-clientjar——它的lib目录已内置适配 Hadoop 2.7.7 的hadoop-common-2.7.7.jar等。标准操作:
sudo tar -zxvf spark-2.4.4-bin-hadoop2.7.tgz -C /usr/local/ sudo chown -R $USER:$USER /usr/local/spark-2.4.4-bin-hadoop2.7 sudo ln -s /usr/local/spark-2.4.4-bin-hadoop2.7 /usr/local/spark追加~/.bashrc:
export SPARK_HOME=/usr/local/spark export PATH=$SPARK_HOME/bin:$PATH4.2spark-env.sh配置:Spark 与 Hadoop 的“握手协议”
复制模板并编辑:
cp $SPARK_HOME/conf/spark-env.sh.template $SPARK_HOME/conf/spark-env.sh vim $SPARK_HOME/conf/spark-env.sh填入(必须严格按此顺序):
export JAVA_HOME=/usr/lib/jvm/jdk1.8.0_202 export SCALA_HOME=/opt/scala export HADOOP_CONF_DIR=/usr/local/hadoop/etc/hadoop # 关键!Spark 读取 core-site.xml 的入口 export YARN_CONF_DIR=/usr/local/hadoop/etc/hadoop # 关键!Spark 读取 yarn-site.xml 的入口 export SPARK_DIST_CLASSPATH=$(hadoop classpath) # 关键!将 Hadoop classpath 注入 Spark参数说明:
HADOOP_CONF_DIR和YARN_CONF_DIR是 Spark 发现 HDFS 和 YARN 配置的唯二途径;$(hadoop classpath)动态拼接所有 Hadoop 依赖 jar,若此处为空,spark-submit --master yarn会报ClassNotFoundException: org.apache.hadoop.fs.FileSystem。
4.3 Spark Standalone 模式快速验证(绕过 YARN)
为排除 YARN 配置干扰,先用local[*]模式跑通 WordCount:
# 创建测试数据 mkdir -p ~/Desktop echo "hello world hello spark" > ~/Desktop/input.txt # 提交任务(注意路径前缀 file://) $SPARK_HOME/bin/spark-submit \ --class "WordCount" \ --master "local[*]" \ /home/$USER/WordCount.jar若输出hello,1world,1spark,1,说明 Spark Core 层正常;若报java.io.FileNotFoundException: file:/home/liqing/桌面/input.txt,检查路径中是否含中文(Ubuntu 14.04 默认 locale 为en_US.UTF-8,但桌面路径liqing/桌面是中文,spark-submit无法解析),必须改为英文路径(如~/Desktop/input.txt)并同步修改代码中的sc.textFile("file:/home/xxx/Desktop/input.txt")。
5. 常见问题排查:那些让你重装三次虚拟机的“幽灵错误”
5.1 现象:start-dfs.sh后jps显示 NameNode,但无 DataNode
原因:dfs.datanode.data.dir目录权限不足,或hdfs-site.xml中dfs.replication值大于 1(单节点只能设 1),或core-site.xml中fs.defaultFS的 host 与hdfs namenode -format时的 host 不一致。
解决:
- 执行
hadoop namenode -format前确认core-site.xml的fs.defaultFS为hdfs://localhost:9000; mkdir -p /usr/local/hadoop_store/hdfs/datanode && chown -R $USER:$USER /usr/local/hadoop_store;- 检查
hdfs-site.xml中dfs.replication是否为1; - 查看
$HADOOP_HOME/logs/hadoop-$USER-datanode-*.log,搜索ERROR行,常见为Cannot create directory。
5.2 现象:浏览器访问http://192.168.37.146:50070显示连接被拒绝
原因:NameNode 进程未真正启动,或防火墙拦截,或core-site.xml中fs.defaultFS的端口(9000)被占用。
解决:
netstat -tuln | grep :9000确认端口监听状态;sudo ufw disable关闭 Ubuntu 防火墙(Ubuntu 14.04 默认未启用,但曾手动开启则需关闭);jps确认NameNode进程存在,若不存在,tail -100 $HADOOP_HOME/logs/hadoop-$USER-namenode-*.log查日志;- 若日志含
Address already in use,sudo lsof -i :9000找出进程并kill -9。
5.3 现象:spark-submit --master yarn报Failed to connect to server
原因:yarn-site.xml中yarn.resourcemanager.hostname设为127.0.0.1,而 Spark 客户端解析为localhost,导致 YARN ResourceManager 绑定地址与客户端请求地址不匹配。
解决:
yarn-site.xml中yarn.resourcemanager.hostname必须为localhost(不能是 IP);yarn.resourcemanager.address必须显式设为localhost:8032(默认值可能为0.0.0.0:8032,不安全);start-yarn.sh后jps必须看到ResourceManager和NodeManager;yarn node -list应返回Total Nodes:1且状态为RUNNING。
5.4 现象:Spark MLlib 线性回归报java.lang.NoClassDefFoundError: org/apache/spark/mllib/regression/LabeledPoint
原因:Spark 2.4.4 的mllib包分spark-mllib_2.12(RDD API)和spark-ml_2.12(DataFrame API),实验代码用的是mllib(LabeledPoint),但spark-submit未指定--jars加载对应 jar。
解决:
- 确认代码 import 的是
org.apache.spark.mllib.regression.LabeledPoint(非ml.feature); spark-submit命令必须包含--jars $SPARK_HOME/jars/spark-mllib_2.12-2.4.4.jar;- 或将该 jar 拷贝到
$SPARK_HOME/jars/下,Spark 启动时自动加载。
5.5 现象:SVM 分类结果 Precision=1.0,Recall=0.956,F1=0.977,但报告称“可能因数据集不平衡”
原因:sample_libsvm_data.txt是 Spark 自带的平衡数据集(正负样本各 300+),但实验代码中data.randomSplit(Array(0.6, 0.4), seed = 11L)的随机种子11L导致训练集恰好抽到更多正样本。
解决:
- 验证数据集分布:
spark-shell中执行val data = MLUtils.loadLibSVMFile(sc, "..."); data.map(_.label).countByValue().foreach(println); - 若发现
0.0 -> 120, 1.0 -> 280,说明训练集倾斜; - 改用
val splits = data.randomSplit(Array(0.6, 0.4), seed = 42L)(经典随机种子)或stratifiedSplit保证比例; - 报告中“Reason”段落是对模型评估的合理反思,非错误,属实验分析环节。
6. 验证全流程跑通:从 HDFS 文件上传到四大算法一键执行
6.1 HDFS 基础操作验证:确保存储层可用
在一切服务启动后,执行以下命令链,任一失败即说明 HDFS 未就绪:
# 格式化(首次运行,后续勿重复) hdfs namenode -format # 启动 HDFS start-dfs.sh # 创建根目录(HDFS 默认无 /user) hadoop fs -mkdir -p /user/$USER # 上传测试文件(注意路径必须是 HDFS 路径) hadoop fs -put ~/Desktop/input.txt /user/$USER/input.txt # 列出文件(应看到 input.txt) hadoop fs -ls /user/$USER/ # 读取内容(应输出 hello world hello spark) hadoop fs -cat /user/$USER/input.txt提示:
hadoop fs -ls /若报No such file or directory,说明 NameNode 未格式化或未启动;hadoop fs -put若报Connection refused,检查50070页面是否能打开,再查jps和日志。
6.2 Spark on YARN 端到端验证:WordCount 提交到 YARN
修改 WordCount 代码中setMaster("local[*]")为setMaster("yarn"),并打包为 jar:
# 编译(需 sbt 或 maven,此处假设已编译好 WordCount.jar) # 提交到 YARN spark-submit \ --class "WordCount" \ --master "yarn" \ --deploy-mode "client" \ --executor-memory 1G \ --num-executors 2 \ WordCount.jar观察终端输出,同时打开http://192.168.37.146:8088(YARN ResourceManager UI),应看到 Application 状态为FINISHED,点击进入可查看stdout日志,确认输出与local[*]模式一致。
6.3 四大 MLlib 算法统一验证框架
为避免每次改代码路径,建立统一数据目录结构:
mkdir -p /usr/local/spark/data/mllib/{ridge-data,kmeans} # 复制数据(实验报告中路径) cp ~/Desktop/lpsa.data /usr/local/spark/data/mllib/ridge-data/ cp ~/Desktop/sample_libsvm_data.txt /usr/local/spark/data/mllib/ cp ~/Desktop/sample_kmeans_data.txt /usr/local/spark/data/mllib/kmeans/编写通用提交脚本run_mllib.sh:
#!/bin/bash APP_NAME=$1 JAR_PATH=$2 MAIN_CLASS=$3 DATA_PATH=$4 spark-submit \ --class "$MAIN_CLASS" \ --master "yarn" \ --deploy-mode "client" \ --driver-memory 2G \ --executor-memory 2G \ --num-executors 2 \ --conf "spark.yarn.appMasterEnv.PYTHONPATH=/usr/bin/python3" \ "$JAR_PATH" "$DATA_PATH"执行:
chmod +x run_mllib.sh ./run_mllib.sh LinearRegression /home/$USER/LinearRegression.jar /usr/local/spark/data/mllib/ridge-data/lpsa.data ./run_mllib.sh SVM /home/$USER/SVM.jar /usr/local/spark/data/mllib/sample_libsvm_data.txt ./run_mllib.sh KMeans /home/$USER/KMeans.jar /usr/local/spark/data/mllib/kmeans/sample_kmeans_data.txt每项执行后,检查终端输出的MSE、Accuracy、Silhouette值是否与实验报告 Figure 2-2、3-2、4-2 一致。特别注意 KMeans 的Silhouette=0.99975,这是聚类质量极高的标志——若输出为NaN或0.0,说明sample_kmeans_data.txt数据格式错误(应为 libsvm 格式,每行label idx1:val1 idx2:val2)。
6.4 最后的“后悔药”:一键清理与重置脚本
当环境混乱到难以定位时,我习惯用这个脚本彻底清场(保存为reset_env.sh):
#!/bin/bash # 停止所有服务 stop-dfs.sh stop-yarn.sh # 清理 HDFS 数据目录 rm -rf /usr/local/hadoop_store/hdfs/* # 清理 Spark 日志 rm -rf $SPARK_HOME/logs/* # 清理 YARN 临时文件 rm -rf $HADOOP_HOME/logs/yarn-* # 重置环境变量(重新 source) source ~/.bashrc echo "Environment reset. Run 'hdfs namenode -format' and restart."从那以后我每次开始新实验,都强制走一遍reset_env.sh → hdfs namenode -format → start-dfs.sh → start-yarn.sh → hadoop fs -ls /,哪怕只是改了一行 XML。因为 Hadoop/Spark 的状态残留比想象中顽固——一个没删干净的in_use.lock文件,就能让下次namenode -format静默失败。希望帮到你。
本文还有配套的精品资源,点击获取