简介这份实验报告围绕华为云大数据平台完整收录四个实验使用弹性云服务器ECS与对象存储OBS搭建Hadoop集群配置访问密钥、完成OpenJDK安装、防火墙关闭与节点SSH互信通过华为云托管服务实现数据收集与分析基于BigData Pro一站式方案购买ECS、创建OBS并搭建Hadoop与Spark协同集群最后借助Spark SQL/Flink SQL完成大数据交互式查询涵盖创建数据表、编写SQL和实时查看结果。内容覆盖从云环境准备、集群部署到SQL分析的完整链路适合正在学习云计算与大数据、需要按步骤完成课程实验或平台实训的读者。压缩包为单一docx文档大小约4.36MB按实验目录分章节组织每个实验均配有详细命令、配置与验证说明可作为实操指南和排错手册。目前已有2197人浏览学习对入门华为云大数据平台及掌握集群搭建流程具有实用价值。1. 华为云大数据实验在做什么:从一台按需计费的MRS集群说起很多高校的大数据课程会布置一类代号类似 hhu 的华为云大数据实验:任务书很简单,给你一份网约车订单或电商日志,要求你完成环境部署、数据导入、清洗分析、最后交一份实验报告。但真正动手才发现,这背后是一条完整的大数据流水线:对象存储OBS负责放数据,MapReduce服务MRS负责跑Hadoop/Hive/Spark,最后还要把结果做成可视化页面。这篇文章不聊概念,只讲我带着学生从零跑通这套实验的完整路径:怎么创建集群、怎么写Hive和Spark作业、哪些环节最容易翻车,以及报告里放什么样的证据才算真的做完。2. 实验环境准备:创建MRS集群、配置安全组、把数据集送进OBS2.1 先搞懂OBS、MRS、DLI在实验里各干什么华为云上的大数据组件并不是一个大一统的软件,而是按存储、计算、分析拆成三个服务,实验报告里出现频率最高的就是OBS、MRS和DLI。OBS是对象存储服务,相当于一个海量文件柜,原始数据(比如CSV格式的订单表、日志文件)进来后先放在这里。MRS是MapReduce服务,它按需拉几台ECS拼成一个真正的Hadoop集群,Hive、Spark、HDFS都在里面跑。DLI则是数据湖探索,一种不用管集群的Serverless SQL服务,直接写SQL就能查OBS里的数据。选型上,如果实验任务书明确写着「部署集群」「提交MapReduce作业」,那么MRS是唯一合理的答案,因为DLI不需要你管理集群,也就谈不上集群部署策略。但如果任务只要求「做数据分析」,DLI会更快,省去集群维护成本。我的建议是以MRS为主体来完成实验,同时用DLI跑一遍同样的SQL作结果对照,最后写进实验报告的对比分析环节,这样既满足任务书要求,又显得你考虑了不同方案的取舍,是报告里很实用的加分写法。2.2 MRS集群创建:版本、规格、计费三个必调参数登录华为云控制台,搜索「MapReduce服务」,进入购买页面。创建集群时有三个参数直接决定后续所有流程顺不顺,值得在动手前想清楚。第一个是集群版本。选MRS 3.x的公共版本就够了,不要追最新大版本。实验作业只用到Hive、Spark这些基础组件,公共版本经过了更多生产验证,踩到未知Bug的概率小很多。第二个是计费模式,这里是一个很典型的坑:实验课的MRS集群应该选「按需计费」,用几个小时就释放,虽然单价看着比包年高,但总量很小;选包年包月的话,实验做完忘了退订,账单金额会非常难看。第三个是节点规格,Master节点4核8G足够承担调度,Core节点至少2个,每个也按4核8G起步。实验数据通常只有几百MB,堆高配只会让账单变大,不会让报告得分变高。额外要注意的是登录方式和安全组。创建集群时选择密码登录,用户名一般默认root,密码自己设,后面SSH登录Master节点要用。安全组在创建时可以顺带确认22端口放通,MRS默认的安全组不一定放开这个端口,没放通的话后面SSH会直接超时,这一步把配置截图留好,实验报告里能用上。集群创建需要等待10到20分钟,状态变成「运行中」才说明Master节点可以连了,等待期间不要反复去SSH,那是徒劳。2.3 数据上传:用obsutil命令行把本地文件放进OBS桶集群创建的同时,先把实验数据准备好。在OBS控制台新建一个桶,桶名有硬性约束:全小写、不能有下划线,比如hhu-bigdata-2024这种格式。需要注意Region一定要和MRS集群在同一个区域,否则跨区读写会慢得让人失去耐心。上传数据最常见的方式是使用华为云官方命令行工具obsutil。下载解压后先配置AK/SK和endpoint,然后执行上传命令:# 配置obsutil,填入AK/SK和endpoint,AK/SK在控制台我的凭证里创建 obsutil config -i你的AK -k你的SK -ehttps://obs.cn-north-4.myhuaweicloud.com # 把本地的网约车订单CSV上传到桶的input目录 obsutil cp ./order_data.csv obs://hhu-bigdata-2024/input/order_data.csv # 查看桶内文件,确认上传成功 obsutil ls obs://hhu-bigdata-2024/input/这段命令里,-i和-k是访问密钥对的Access Key Id和Secret Access Key,实验场景不要用主账号的AK,建议创建一个子用户只授权OBS权限,避免密钥泄露影响整个账户。-e参数是endpoint,必须与MRS集群所在Region一致,华北北京四是cn-north-4,华东上海一是cn-east-3,具体以控制台右上角区域为准。上传完成后用ls命令检查对象大小,和本地文件对比,大小对不上多半是网络中断,重新传一次即可。到这里,集群和数据集都已经就位,下一个核心动作是把数据从OBS拉进HDFS,再交给Hive建表。3. 第一个Hive作业:建表、数据清洗、提交MapReduce的完整命令3.1 Hive建表:外部表还是内部表,决定你的数据去哪MRS集群运行后,用SSH登录Master节点,Hive已经内置好了。实验里操作Hive有两种姿势,一种是直接敲hive -e SQL,适合一次性查询;另一种是进入beeline命令行交互模式,适合反复调试。为了让报告里能截到完整的执行过程,我一般让学生先用beeline。数据在OBS上,Hive要读它需要先映射到HDFS。最直接的办法是把OBS里的CSV下载到本地再传上HDFS,也可以用hadoop distcp做云上拷贝:# 在HDFS上创建实验目录 hdfs dfs -mkdir -p /user/hhu/input # 把OBS数据拷贝到HDFS,跳过CRC校验以加快拷贝 hadoop distcp -skipcrccheck obs://hhu-bigdata-2024/input/order_data.csv /user/hhu/input/第一行命令在HDFS根目录下创建了/user/hhu/input,存放原始数据。第二行hadoop distcp是Hadoop自带的数据拷贝工具,-skipcrccheck跳过一致性校验,在实验环境下能省不少时间。拷贝完成后用hdfs dfs -ls /user/hhu/input确认文件存在,然后就可以建表了。建表时面临的第一个选择是外部表还是内部表。外部表用EXTERNAL关键字创建,删除表时只删元数据,HDFS上的原始文件还在;内部表删表时底层数据会被一起删除。实验场景里强烈建议用外部表,因为数据是从OBS拷贝进来的,删错了还能重新拷贝,后悔药是有的。CREATE EXTERNAL TABLE IF NOT EXISTS hhu_orders( order_id STRING, city STRING, car_type STRING, start_time STRING, end_time STRING, distance DOUBLE, amount DOUBLE, status STRING ) ROW FORMAT DELIMITED FIELDS TERMINATED BY , STORED AS TEXTFILE LOCATION /user/hhu/input;这段SQL里,字段类型按实验数据的实际内容去定义,时间字段先全部用STRING,后边清洗时再交给Hive内置函数处理。ROW FORMAT指定CSV的逗号分隔符,STORED AS TEXTFILE表示纯文本存储,LOCATION指向HDFS目录。有一个细节经常让同学们卡住:如果CSV第一行是表头,建表后会发现数据里混进来一行字段名,解决方式是在建表语句尾部追加TBLPROPERTIES(skip.header.line.count1)。这个参数很隐蔽,但实验报告里专门写一句「通过skip.header.line.count过滤表头」,会让批改老师觉得你处理数据是认真的。3.2 数据清洗:Hive SQL处理空值和脏数据实验报告的「数据预处理」章节,Hive SQL足够应付大部分场景。常见的清洗动作包括过滤空订单号、排除金额为负的异常记录、统一时间格式。下面这段SQL是实验里的常用模板:-- 清洗:过滤订单号为空、金额为负、时间格式异常的记录 CREATE TABLE hhu_orders_clean AS SELECT order_id, city, car_type, from_unixtime(unix_timestamp(start_time,yyyy-MM-dd HH:mm:ss)) AS start_time, from_unixtime(unix_timestamp(end_time,yyyy-MM-dd HH:mm:ss)) AS end_time, round(distance,2) AS distance, round(amount,2) AS amount, status FROM hhu_orders WHERE order_id IS NOT NULL AND amount 0 AND distance 0 AND start_time LIKE %:%:%;清洗逻辑分三层:WHERE里的IS NOT NULL剔除空订单号,amount 0排除负金额的测试数据,distance 0排除异常里程。时间字段用unix_timestamp配合from_unixtime做格式统一,LIKE %:%:%粗筛掉不含冒号的脏时间串。清洗后的结果写入hhu_orders_clean新表,这张表是内部表,方便后续反复查询使用。跑完先用SELECT COUNT() FROM hhu_orders和SELECT COUNT() FROM hhu_orders_clean对比行数变化,这两个数字写进报告就是非常好的数据质量说明,比任何文字描述都有说服力。3.3 提交MapReduce作业:hadoop jar的参数与输出路径如果实验任务书明确写了「MapReduce」,只跑Hive是不够的,因为Hive底层把SQL翻译成MapReduce作业,但这是框架自动完成的,报告里最好体现你自己写过或提交过原生的MR作业。最快的方案是直接使用MRS自带的示例jar包。# 查找集群里自带的hadoop-mapreduce-examples jar包 find / -name hadoop-mapreduce-examples*.jar 2/dev/null # 提交WordCount作业:jar包路径 程序名 输入目录 输出目录 hadoop jar /opt/hadoop/share/hadoop/mapreduce/hadoop-mapreduce-examples.jar wordcount /user/hhu/input /user/hhu/output/wc第一次跑MR作业,建议先跑WordCount这种自带示例,它不需要你写任何代码,就能演示完整的Map与Reduce过程。命令中第一个参数是jar包绝对路径,第二个参数wordcount是示例程序的主类名,第三个是输入目录,第四个是输出目录。有一个硬性约束:输出目录必须事先不存在,否则Hadoop会直接报错退出,这是分布式文件系统防止覆盖安全机制。提交后作业进入Yarn队列,可以用yarn application -list查看状态,跑完执行下面命令查看结果:# 合并输出文件并查看前20行 hdfs dfs -cat /user/hhu/output/wc/part-r-00000 | head -20如果跑完发现输出目录里全是part-r-000xx这样的文件,这是正常的,MapReduce的每个Reducer都会写一个分片文件。实验报告里务必截图展示这个输出目录结构,它直观证明了Map和Reduce阶段真的执行了,比贴一堆日志强得多。4. 切到Spark做分析:executor参数调优与FlaskECharts可视化4.1 为什么大数据实验要切到SparkHive跑作业稳定,但代价是慢。每一个SQL都编译成MapReduce,中间结果要落盘,数据量一旦超过百万行,一个简单的group by聚合可能要等上两三分钟。Spark把中间结果放在内存里,同样的聚合操作能快一个量级。如果实验任务书里有「Spark」这个关键词,这一步绕不开;就算任务书没写,主动用Spark重跑一遍分析,再和Hive做耗时对比,也是报告里很有价值的实验结论。MRS集群默认集成Spark,不需要额外安装。提交Spark作业和MapReduce长得像,但参数细节更多,稍有不慎就会把作业卡死在资源调度上。4.2 spark-submit提交作业:executor内存与并行度怎么定先用PySpark写一个简单的城市维度订单分析脚本:from pyspark.sql import SparkSession spark SparkSession.builder \ .appName(hhu_order_analysis) \ .getOrCreate() # 读取HDFS上的清洗后数据,自动推断字段类型 df spark.read.csv(hdfs:///user/hhu/input/, headerTrue, inferSchemaTrue) # 按城市统计订单量、平均金额 result df.groupBy(city) \ .agg({order_id: count, amount: avg}) \ .withColumnRenamed(count(order_id), order_cnt) \ .withColumnRenamed(avg(amount), avg_amount) result.show(10) # 结果写回HDFS,覆盖模式方便重复运行 result.write.mode(overwrite).csv(hdfs:///user/hhu/output/spark_city_result) spark.stop()脚本逻辑很直接:SparkSession.builder初始化应用,appName是作业在Yarn界面上的显示名;read.csv读取HDFS数据,headerTrue声明首行为表头,inferSchema让Spark自动识别字段类型;groupBy(city)做分组聚合;最后write.mode(overwrite)把结果写成CSV,覆盖模式允许脚本重复执行而不报错。提交命令同样关键:spark-submit \ --master yarn \ --deploy-mode cluster \ --executor-memory 4g \ --num-executors 3 \ --executor-cores 2 \ /home/admin/hhu_city_analysis.py参数含义分别是:--master yarn让作业统一交给Yarn调度;--deploy-mode cluster让Driver进程也跑在集群内,本地终端断开连接也不影响作业运行;--executor-memory 4g分配给每个执行器的内存堆,建议不超过节点物理内存的一半;--num-executors 3应该与Core节点数对齐;--executor-cores 2则控制每个执行器占用的CPU核数。这里的经验是:宁可参数配保守,也不要贪大。executor内存过大或核数超过集群总资源,Yarn分配不出容器,作业会一直卡在ACCEPTED状态,看起来像是死锁,实际是资源不够。正确的调参顺序是先用小数据量跑通默认参数,再逐步加大executor数量跑全量数据,把两次耗时都记录下来,写进报告就是一组完整的对比实验。4.3 用FlaskECharts把结果变成可视化页面Spark跑出来的CSV只是文本,实验报告里最直观的结果呈现方式是图表。国内高校大数据项目里,FlaskECharts几乎是标配方案,原因有两个:Flask起一个本地Web服务只需要几行Python,ECharts画图不需要写复杂的Canvas代码,一个柱状图十几行配置就能完成。from flask import Flask, jsonify, render_template import csv app Flask(__name__) app.route(/api/city_stats) def city_stats(): data [] # Spark输出的CSV是part-*分片文件,读取第一个分片即可 with open(/home/admin/spark_city_result/part-00000-*.csv) as f: reader csv.reader(f) for row in reader: data.append({city: row[0], cnt: int(row[1]), avg: round(float(row[2]), 2)}) return jsonify(data) app.route(/) def index(): return render_template(index.html) if __name__ __main__: app.run(host0.0.0.0, port5000)代码里通过/api/city_stats接口返回JSON数据,前端页面再通过fetch请求这个接口并交给ECharts渲染。注意到读取文件时用了part-00000-*.csv的通配写法,这是因为Spark写出的CSV文件会自动命名成part-00000-xxxxx,直接写死完整文件名在第二次跑作业后就会失效,用通配符能避免这个坑。前端页面index.html中,ECharts的核心配置长这样:script src/static/echarts.min.js/script script fetch(/api/city_stats).then(res res.json()).then(data { const chart echarts.init(document.getElementById(chart)); chart.setOption({ title: {text: 各城市订单量分布}, xAxis: {type: category, data: data.map(d d.city)}, yAxis: {type: value}, series: [{type: bar, data: data.map(d d.cnt)}] }); }); /scriptFlask服务启动后,浏览器访问Master节点的公网IP加端口5000就能看到图表。这一步有两个直接影响成败的配置:一是安全组必须额外放通5000端口的入方向访问,默认安全组不会开这个端口;二是如果实验要求最后做数据大屏,可以把图表改成多面板布局,用ECharts的grid组件把城市订单量、平均金额、车型分布放在同一个页面里,这样呈现出来的效果远好于一张孤零零的柱状图。5. 华为云大数据实验避坑指南:五个最容易翻车的环境与作业问题5.1 集群创建成功但SSH连不上现象:MRS集群状态已经变成「运行中」,但用终端SSH到Master节点的公网IP,提示Connection refused或直接超时。原因:九成情况是安全组没有放通22端口,MRS创建时默认安全组只开放了集群内部通信端口,并不包含SSH;剩下的一成是Master节点没有绑定弹性公网IP,你拿到的地址其实是内网地址。解决:在ECS控制台找到MRS集群对应的Master节点,进入安全组规则,添加入方向放通22端口,来源写0.0.0.0/0(实验环境可以,生产环境別这么干)。再确认节点已经有弹性公网IP,没有就先绑定一个。SSH登录使用的用户名取决于创建集群时的设置,并不是固定root;如果用密码登录,注意密码中类似#、!的字符不要被Shell转义,否则密码对也会认证失败。5.2 Spark作业一直停留在ACCEPTED状态现象:用spark-submit提交作业之后,Yarn界面上Application一直显示ACCEPTED,十几分钟没有任何变化,日志里只有等待资源的提示。原因:资源调度不出容器。集群Core节点总数太少,或者executor请求的核数、内存超过了集群剩余可分配资源,Yarn队列里所有作业排成一串,谁也不让谁。解决:先把--num-executors降到2、--executor-memory降到2g再试一次。如果仍然排队,登录Yarn的ResourceManager界面,查看队列里是不是有之前跑挂的作业还占着资源,有就手动Kill。我自己的习惯是实验场景把executor参数按集群总资源的70%去配,留出30%给Yarn的ApplicationMaster和系统进程,这个比例能让作业稳定跑完。5.3 Hive查出的中文全是乱码现象:CSV文件里的城市名、车型名在Hive查询结果里显示成????或一串不可读字符。原因:字符集不一致。CSV文件本身是UTF-8编码,但Hive表的字段或客户端的连接字符集不是UTF-8,导致中文被按错误编码解析;还有一个高频场景是CSV在Windows下编辑后带上了BOM头,导致第一个字段名前缀出现乱码。解决:建表时在TBLPROPERTIES加(charsetUTF-8),这是最省事的做法。同时检查CSV是否带BOM,用命令去掉:# 去掉CSV文件开头的BOM标记 sed -i s/^\xEF\xBB\xBF// order_data.csv修改后重新上传OBS并覆盖原文件,再查询一次。乱码问题在实验报告里很值得写一小节,因为几乎每个班都有同学中招,你把它写明白,反而成了报告里的亮点。5.4 实验做完发现账户欠费了现象:报告提交几天后,收到短信提醒账户欠费,登录控制台一看,MRS集群的计费还在持续运行。原因:MRS控制台释放集群后,关联的ECS节点和云盘不一定被自动清理,尤其是按需购买的节点,只要没删除就继续计费。另一个容易被忽略的计费点是OBS桶里的数据还在按存储量收钱。解决:实验结束后,先到MRS控制台「释放集群」,再去ECS控制台把挂着的节点和云盘一并退订,最后清空并删除OBS桶。操作顺序很重要:先下载作业结果到本地,再释放集群,最后删桶。释放之后过半小时在费用中心确认没有新的计费明细产生。这是我踩过一次的坑,那次的账单够买好几杯咖啡,从那以后每次实验收尾都把釋放集群当作最后一个必须执行的步骤。5.5 本地能跑的代码提交到集群就报ClassNotFound现象:同样的Spark脚本、同样的数据,在本地PySpark环境跑得好好的,提交到MRS集群就报java.lang.ClassNotFoundException,而且堆栈信息指向的类看起来和业务逻辑毫无关系。原因:本地环境和集群环境版本不一致,最常见的是Python版本和Java依赖差异。集群预装的Python可能是3.7,本地用的是3.10,脚本里用到的某些语法或第三方库在集群上不存在。解决:先看堆栈里Caused by的第一行,确认缺的是什么类或模块。如果是第三方库,用--jars参数把对应jar包带进提交命令;如果是Python语法问题,把脚本改写成低版本兼容的写法。实验场景下不要去尝试升级集群组件,那样可能会破坏集群的既有环境,最快、最稳的做法是让代码去适配集群。6. 报告收尾前必做的一件事:用Yarn日志和指标表验证实验结论6.1 用Yarn日志确认作业真的跑过很多同学写实验报告,结论部分全靠一句「程序运行成功」,但老师提问时大概率会追问:作业跑了多久?输入了多少条数据?输出结果在哪里?这些信息靠截图和日志才能支撑起来。完成每个作业后,我都会要求学生把Yarn的Application ID、运行耗时、输入输出行数记录到一个单独的文件里。查这些信息的命令非常直接:# 查看作业的详细状态和耗时 yarn application -status application_171000000000_0042 | grep -E State|Final-State|Total-Time|Total-MB # 查看HDFS输出目录的实际大小 hdfs dfs -du -h /user/hhu/output/第一条命令返回的信息里,State字段显示作业是FINISHED还是FAILED,Total-Time是毫秒级的实际耗时,Total-MB记录了作业占用的资源量。第二条命令查看输出目录的体积,配合Hive的COUNT(*)查询,就能算出「输入多少行、输出多少行、消耗多少资源」这三个关键数字。把这些数字整理成表格放进报告,结论才站得住脚。6.2 给报告加一张运行指标对比表实验报告里表格是最省字、最出效果的形式。跑完同一份数据,把MapReduce、Hive、Spark的各项指标放在同一张表里,报告的说服力立刻上一个台阶:| 作业方式 | 输入数据量 | 运行耗时 | 输出记录数 | | MapReduce WordCount | 约120MB | 4分12秒 | 8,421 | | Hive聚合查询 | 约120MB | 2分08秒 | 327 | | Spark聚合查询 | 约120MB | 41秒 | 327 |这张表本身就是实验结论。我带的实验里,很多同学跑完会惊讶地发现,Spark并不是在所有数据量下都吊打Hive:数据量在50MB以内时,Spark的调度开销反而让耗时变长;数据量超过200MB后,Spark的内存计算优势才真正拉开差距。把这个观察写进报告,你的实验报告就不再是「照做步骤」,而是「验证了一个观点」。最后说一个我自己的习惯,整个实验从创建集群到最后一次提交作业,每跑通一步就截一张图,存进一个叫screenshots的目录。写报告时截图永远不嫌多,但回头补截图是最痛苦的事。有一次我嫌麻烦没有及时截图,最后整理报告时不得不把整个流程重新跑了一遍,白白浪费了两个多小时。现在哪怕只是一条SELECT COUNT(*)的成功返回,我也会顺手存档。这个习惯,希望帮到你。本文还有配套的精品资源点击获取