Spark学习笔记1
一、什么是spark?
1.简介
(1)Spark是加州大学伯克利分校AMP实验室开发通用内存并行计算框架。
(2)Spark是基于内存计算的大数据分布式计算框架(Hadoop基于磁盘)。
(3)Spark基于内存计算,提供可交互查询的方式,提供近实时的处理方式,允许用户将Spark部署在大量廉价硬件之上,形成集群(可以部署到本机,也可以运行到yarn集群上,K8S集群,MESOS集群等),提高了处理速度,同时也保证了集群的高容错性和高可伸缩性。
2.spark起源与发展
(1)2009年伯克利分校实验室开始使用Scala语言编写Spark源码,2010年开放源代码,2013年6月进入Apache孵化项目,2014年2月成为Apache顶级项目,2014年5月底发布Spark1.0.0,到目前为止版本更新到了Spark3.X。
(2)演进时间表:
➢2009年由 Berkeley’s AMPLab 开始编写最初的源代码
➢2010年开放源代码
➢2013年6月进入Apache孵化器项目
➢2014年2月成为Apache的顶级项目(8 个月时间)
➢2014年5月底Spark1.0.0发布
➢2014年9月Spark1.1.0发布
… …
➢2016年3月Spark1.6.1发布
➢2016年7月Spark2.0发布
➢2016年10月Spark2.0.1发布
➢2016年11月Spark1.6.3发布
➢2016年11月Spark2.0.2发布
… …
➢2017年10月Spark2.1.2发布
➢2017年12月Spark2.2.1发布
➢2018年2月Spark2.3.0
(3)spark的四个特点:在Spark官网上介绍,它具有运行速度快、易用性好、通用性强和随处运行等特点。
①运行速度快
Spark拥有DAG执行引擎,支持在内存中对数据进行迭代计算。官方提供的数据表明,如果数据由磁盘读取,速度是Hadoop MapReduce的10倍以上,如果数据从内存中读取,速度可以高达100多倍。
纵坐标是时间,横坐标是速度
②易用性好
支持4种语言的API:scala、java、python、R。特别是Scala是一种高效、可拓展的语言,能够用简洁的代码处理较为复杂的处理工作。
下面是一个简单的词频统计的代码:
val text_file=sc.textFile(“hdfs://…”)
➢获取文件数据,括号里是文件的路径。
text_file.flatMap(.split(" ")).map(x=>(x,1)).reduceByKey(+_).foreach(println)
➢flatMap是扁平化操作,将一行一行的数据用空格分开,变成一个一个的单词,然后用map方法统计这些单词(单词,次数),每个单词的次数赋值为1,再用reduceByKey方法统计相同单词的次数有多少个并进行相加,最后遍历输出即可。
text_file.flatMap(_.split(" ")).countByValue();
Spark2.2.0之后变成下面的形式,本质是没什么不同的:
scala> val textFile = spark.read.textFile(“ README.md")
val wordCounts = textFile.flatMap(line => line.split(" ")).groupByKey(identity).count()
③通用性强
Spark生态圈即BDAS(伯克利数据分析栈)包含了Spark Core、Spark SQL、Spark Streaming、MLLib和GraphX等组件,这些组件分别处理不同的内容:Spark Core提供内存计算框架、Spark Streaming处理实时数据、Spark SQL的即席查询,处理结构化数据、MLlib或MLbase的机器学习和GraphX的图计算,它们都是由AMP实验室提供,能够无缝的集成并提供一站式解决平台。
④随处运行
➢ Spark具有很强的适应性,能够读取Hadoop(将最终数据存储到HDFS集群上)、HBase、Cassandra S3和Techyon为持久层读写原生数据,能够以Mesos、YARN和自身携带的Standalone作为资源管理器调度job,来完成Spark应用程序的计算。
(4)spark生态圈/生态系统
Spark生态圈也称为BDAS(伯克利数据分析栈),是伯克利APMLab实验室打造的,力图在算法(Algorithms)、机器(Machines)、人(People)之间通过大规模集成来展现大数据应用的一个平台。伯克利AMPLab运用大数据、云计算、通信等各种资源以及各种灵活的技术方案,对海量不透明的数据进行甄别并转化为有用的信息,以供人们更好的理解世界。该生态圈已经涉及到机器学习、数据挖掘、数据库、信息检索、自然语言处理和语音识别等多个领域。
Spark生态圈以Spark Core为核心,从HDFS、HBase和Amazon S3等持久层读取数据,以MESOS、YARN和自身携带的Standalone为资源管理器调度Job
完成Spark应用程序的计算。这些应用程序可以来自于不同的组件,如Spark Shell/Spark Submit的批处理、Spark Streaming的实时处理应用、Spark SQL的即席查询、BlinkDB的权衡查询、MLlib/MLbase的机器学习、GraphX的图处理和SparkR的数学计算等等。
Spark既可以像Hadoop一样处理离线数据,也可以处理实时数据。
首先在集群上从HDFS,Hbase等地方读取数据,然后通过Spark包含的组件处理这些数据。
二、为什么要学习spark?
1.Spark与MapReduce的差异:
Spark是在借鉴了MapReduce之上发展而来的,继承了其分布式并行计算的优点并改进了MapReduce明显的缺陷,具体如下:
➢基于内存计算
➢容错性高
➢通用性好
首先,Spark把中间数据放到内存中,迭代运算效率高。MapReduce中计算结果需要落地,保存到磁盘上,这样势必会影响整体速度,而Spark支持DAG图的分布式并行计算的编程框架,减少了迭代过程中数据的落地,提高了处理效率。
其次,Spark容错性高。Spark引进了弹性分布式数据集RDD (Resilient Distributed Dataset) 的抽象,它是分布在一组节点中的只读对象集合,这些集合是弹性的,如果数据集一部分丢失,则可以根据“血统”(即充许基于数据衍生过程)对它们进行重建。另外在RDD计算时可以通过CheckPoint(校验)来实现容错,而CheckPoint有两种方式:CheckPoint Data和Logging The Updates,用户可以控制采用哪种方式来实现容错。
最后,Spark更加通用。不像Hadoop只提供了Map和Reduce两种操作,Spark提供的数据集操作类型有很多种,大致分为:Transformations和Actions两大类。Tr ansformations包括map、filter、flatMap、sample、groupByKey、reduceByKey、union、join、cogroup、mapvalues、sort和partionBy等多种操作类型,同时还提供count, Actions包括collect、reduce、lookup和save等操作。另外各个处理节点之间的通信模型不再像Hadoop只有Shuffle一种模式,用户可以命名、物化,控制中间结果的存储、分区等。DAG有向无环图触发一个行动操作,就会产生一个job,一个job产生一个DAG有向无环图。
注意:怎么区分Transformations转化操作和Actions行动操作呢?当调用某一个方法时,如果该方法返回的是RDD对象,则这个操作属于转化操作,其他的操作为行动操作。
2.大数据处理场景
目前大数据处理场景有以下几个类型:
➢复杂的批量处理(Batch Data Processing),偏重点在于处理海量数据的能力,至于处理速度可忍受,通常的时间可能是在数十分钟到数小时;
➢基于历史数据的交互式查询(Interactive Query),通常的时间在数十秒到数十分钟之间;
➢基于实时数据流的数据处理(Streaming Data Processing),通常在数百毫秒到数秒之间。
目前对以上三种场景需求都有比较成熟的处理框架,第一种情况可以用Hadoop的MapReduce来进行批量海量数据处理,第二种情况可以Impala进行交互式查询,对于第三种情况可以用Storm分布式处理框架处理实时流式数据。以上三者都比较独立,各自一套维护成本比较高,而Spark的出现能够一站式平台满意以上需求。
3.spark的适用场景
Spark是基于内存的迭代计算框架,适用于需要多次操作特定数据集的应用场合。需要反复操作的次数越多,所需读取的数据量越大,受益越大,数据量小但是计算密集度较大的场合,受益就相对较小。
由于RDD的特性,Spark不适用那种异步细粒度更新状态的应用,例如web服务的存储或者是增量的web爬虫和索引。就是对于那种增量修改的应用模型不适合。
数据量不是特别大,但是要求实时统计分析需求。
4.spark成功案例
Yahoo将Spark用在Audience Expansion中的应用。Audience Expansion是广告中寻找目标用户的一种方法:首先广告者提供一些观看了广告并且购买产品的样本客户,据此进行学习,寻找更多可能转化的用户,对他们定向广告。Yahoo采用的算法是logistic regression。同时由于有些SQL负载需要更高的服务质量,又加入了专门跑Spark的大内存集群,用于取代商业BI/OLAP工具,承担报表/图表和交互式/即席查询,同时与桌面BI工具对接。目前在Yahoo部署的Spark集群有112台节点,9.2TB内存。
阿里搜索和广告业务,最初使用Mahout或者自己写的MR来解决复杂的机器学习,导致效率低而且代码不易维护。淘宝技术团队使用了Spark来解决多次迭代的机器学习算法、高计算复杂度的算法等。将Spark运用于淘宝的推荐相关算法上,同时还利用Graphx解决了许多生产问题,包括以下计算场景:基于度分布的中枢节点发现、基于最大连通图的社区发现、基于三角形计数的关系衡量、基于随机游走的用户属性传播等。
三、如何学习spark之Spark开发环境搭建
大纲:
◆ Spark运行模式
➢ Local本地模式(多用于测试)
➢ Standalone模式
➢ Yarn集群模式
➢ Mesos集群模式
➢ Kubernetes集群模式
◆ Spark环境搭建
◆ Spark常用命令
➢ spark-shell:spark终端
➢ spark-submit:写完代码打成jar包扔到spark集群时利用这个命令
➢ spark-sql:处理结构化数据写SQL语句的地方
◆ Spark基础案例
1.安装并配置spark
◆◆◆◆◆构建Spark单机模式:
(1)解压缩spark压缩包
sudo tar -xvf spark-2.4.2-bin-hadoop2.7.tar -C /opt/software/
(2)创建软连接:
sudo ln -sf /opt/software/spark-2.4.2-bin-hadoop2.7/ /opt/software/spark
(3)修改环境变量:vi ~/.bashrc
export SPARK_HOME=/opt/software/spark
export PATH=$PATH:$SPARK_HOME/bin:$SPARK_HOME/sbin
使环境变量生效:source ~/.bashrc
(4)测试spark是否安装成功:spark-shell
报错,信息如下:
ERROR SparkContext: Error initializing SparkContext.
java.net.BindException:无法指定被请求的地址: Service ‘sparkDriver’ failed after 16 retries (on a random free port)! Consider explicitly setting the appropriate binding address for the service ‘sparkDriver’ (for example spark.driver.bindAddress for SparkDriver) to the correct binding address.
解决办法:在输入spark-shell命令运行前,先将hadoop集群的节点打开,然后就运行成功了。之后打开spark命令行时不需要开启节点也能成功运行了。
hadoop-daemon.sh start namenode
hadoop-daemon.sh start datanode
参考网址:
https://blog.csdn.net/weixin_44080445/article/details/110137476
其中,Spark图标的右边是安装的spark版本号,Spark图标下面一行的scala版本号是spark内置的scala,与之前自己在虚拟机中安装的scala没有关系,如果将虚拟机中自己安装的scala卸载掉,这里也是可以正常使用的。
访问浏览器:Spark context Web UI available at http://hadoopPD:4040
这个端口是默认将来提交了job任务之后,查看任务的界面。
(5)测试spark-submit环境是否完好:
★★★第一种方式:
在根目录下输入:spark-submit run-example SparkPi 2
如果数据太多,为了更好的查看环境是否完好,先修改一下日志级别,然后再重新运行:
①进入spark安装目录:cd /opt/software/spark/conf;ls
②复制此文件并重命名:sudo cp log4j.properties.template log4j.properties
③修改该文件:sudo vi log4j.properties
修改内容:在第19行的位置,将log4j.rootCategory=INFO,console中的INFO修改为WARN,保存并退出
④重新在根目录下运行该spark-submit命令
最后一行出现:Pi is roughly 3.1413357066785332表示环境是完好的
★★★第二种方式:在集群中利用自带的程序测试
spark-submit 指定主节点 --class 相对路径 绝对路径
spark-submit --master spark://主节点所在机器名:7077 --class org.apache.spark.examples.SparkPi /opt/software/spark/examples/jars/spark-examples_2.11-2.2.1.jar 2
①进入目录并查看:cd /opt/software/spark/examples/jars,发现有一个文件叫做spark-examples_2.12-2.4.2.jar,进入上一级目录:cd …
②进入目录:cd src/main/scala/org/apache/spark/examples/
注意:org后面的都可以直接按Tab键补充写出
◆◆◆◆◆构建Spark集群模式:
注意:spark有3个端口号,分别是4040,、8080和7077,其中4040是默认将来提交了job任务之后,查看任务界面的,spark-shell应用的端口,8080是spark集群的端口,7077是主节点和从节点进行数据交互的端口。
(1)修改Spark配置文件 (路径为$SPARK_HOME/conf/下)
①进入spark安装目录下:cd /opt/software/spark/conf,然后ls查看,发现不存在spark-env.sh配置文件,所以需要复制spark-env.sh.template并重命名作为配置文件(复制slaves.template和 spark-env.sh.template各一份)
sudo cp spark-env.sh.template spark-env.sh
sudo cp slaves.template slaves
(2)修改文件slaves和spark-env.sh,此文件用于指定从节点的主机名,直接添加从节点主机名即可(前提是在/etc/hosts里面配置了)。例如:
mm1
mm2
①修改文件:sudo vi slaves
②使用大写G定位到最后一行,在前面输入“#”将“localhost”注释掉
③然后在下一行输入从节点的主机名:(前提是做过映射)
worker1
worker2
保存并退出
④修改文件:sudo vi spark-env.sh
⑤在最后一行输入:
export SPARK_MASTER_HOST=hadoopPD
保存并退出
(3)进入另外两个从节点虚拟机worker1和worker2,进行同样的操作:复制slaves.template和 spark-env.sh.template→修改文件slaves和spark-env.sh
(4)在hadoopPD虚拟机上启动spark主节点(根目录下):start-master.sh
然后jps查看,发现出现了一个“Master”进程
在worker1虚拟机上启动从节点(根目录下):
start-slave.sh spark://主节点主机名:7077
即输入:start-slave.sh spark://hadoopPD:7077
然后jps查看,发现出现了一个“Worker”进程
(5)在浏览器访问8080端口:192.168.255.136:8080/,可以查看主节点和从节点
(6)关闭从节点的spark集群:stop-slave.sh
◆◆◆◆◆构建YARN集群上的Spark集群:
注意:在yarn集群上部署spark,即添加HADOOP_CONF_DIR到spark-env.sh中,不论要运行本地spark-shell还是yarn集群spark-shell,必须先启动yarn集群。
(1)只需要修改spark-env.sh环境配置即可:
(2)添加如下配置:
export HADOOP_CONF_DIR =/opt/hadoop/etc/hadoop
export SPARK_LOCAL_IP=你自己的IP
(3)优化配置
#将spark的类库jar包上传到hdfs上,省的每次都上传
Spark1.* 版本
export SPARK_JAR=hdfs://server1.cloud.briup.com:9000/user/spark/share/lib/spark-assembly.jar
Spark2. * 版本spark-defaults.conf
spark.yarn.jars hdfs://computer1.cloud.briup.com:9000/spark_lib/jars/*
或者
spark.yarn.archive hdfs://computer1.cloud.briup.com:9000/spark_lib/jars
◆◆◆◆◆构建Hive集群上的Spark集群:
(1)将hive-site.xml添加到 $SPARK_HOME/conf/目录下;
(2)集群运行模式下,需要将Hive的元数据的连接jar包配置到执行器节点;
spark.executor.extraClassPath $HIVE_HOME/lib/my sql-connector-java-5.1.22.jar
(3)设置warehouse
spark.sql.warehouse.dir hdfs://computer1.cloud.briup.com:9000/user/hive/warehouse/
(4)测试
在本地测试只能通过 --driver-class-path 选项将Hive的元数据的连接jar包添加到Driver中。
spark-sql --driver-class-path $HIVE_HOME/lib/mysql-connector-java-5.1.22.jar
2.Spark常用命令
➢spark-shell
➢spark-submit
➢spark-sql
(1)spark-shell命令
格式:
./bin/spark-shell [options]
[options]可选参数 可通过spark-shell–help查看
Eg:spark-shell --master local[3] --name mySparkShell
➢ 行数统计
val lines=sc.textFile("/opt/software/spark/README.md")
lines.count() 统计个数,行动方法,在详细界面会出现一个有向无环图
然后在浏览器进入4040端口,发现有如下界面:
点击“Description”下蓝色的“count at <console>:26”两次,则出现下面的页面:
lines.first() 显示第一行内容,行动方法
其中:sc是默认封装好的上下文对象,叫做sparkContext对象,一个应用只能产生一个sparkContext对象。写java代码时需要获取这个对象,但在交互式解析器中,这个对象是默认存在的,可以直接用sc去调用它的一系列转化方法
(2)spark-submit命令
格式:
Usage: spark-submit [options] <app jar | python file | R file> [app arguments]
Usage: spark-submit --kill [submission ID] --master [spark://…]
Usage: spark-submit --status [submission ID] --master [spark://…]
Usage: spark-submit run-example [options] example-class [example args]
[options]可选参数 可通过spark-submit --help查看
<app jar>表示包含应用入口的jar包
[app arguments]传给应用的选项
常用标记:
①spark-submit --master 集群URL →寻找集群的入口地址→运行jar包时必须指定的!
spark-submit --master spark://hadoopPD:7077
②spark-submit --deploy-mode 工作模式 → 可选项
③spark-submit --class 应用程序的主类 → 运行jar包时必须指定的!
spark-submit --class 全包名 类名
④spark-submit --name 应用的名称 → 可选项
spark-submit --name 给应用起一个名字
⑤spark-submit --jars 额外依赖的第三方jar包 → 运行jar包时必须指定的!
⑥spark-submit --files 需要分发到各节点的数据文件 → 可选项
⑦spark-submit --executor-memory 执行器内存大小 → 可选项
⑧spark-submit --driver-memory 驱动器内存大小 → 可选项
⑨spark-submit --conf prop=value标记设置SparkConf配置选项 → 可选项
⑩spark-submit --properties-file 指定一个包含键值对的属性文件 → 可选项
如:spark-submit --master local --class com.briup.scala.First XXX.jar args1
其中args1指的是参数,如果要传参就继续在后面加,如-D
(3)spark-sql命令
在终端根目录输入:spark-sql,可以进入sql命令行界面,输入show databases;查看数据库信息,退出命令:quit;
3.Spark内置的运行机制
➢驱动器程序(Driver Program)
驱动器程序里产生一个sparkContext对象,包含应用的main函数,并定义了集群上的分布式数据集(RDD),并对分布式数据集应用相关操作。sparkContext对象默认可以看作是程序的入口。
➢执行器(executor):执行代码时由执行器执行,执行器在从节点上,而真正执行任务的是Task。
➢中间的Cluster Manager是集群管理者,如果是集群的形式,它就是master;如果是在yarn集群上,它就是Recourse Manager,是可以灵活变动的。
➢sc(SparkContext)
首先,sparkContext应用产生一个Driver Program,而Driver Program里面有sparkContext对象,sparkContext对象想要执行的话,就需要先向集群进行注册,让集群的主节点给它分配资源,分配后,集群要向从节点汇报情况。
然后,从节点启动executor执行引擎来真正执行任务,从节点启动执行器后,再向sparkContext对象查看它的任务有哪些,sparkContext对象将任务分发给executor执行器后,executor执行器启动一个线程来执行Task任务,执行完成后,
sparkContext对象要向集群的主节点进行汇报,汇报这个集群已经执行完成,执行后要进行注销操作,集群要把sparkContext对象所给它分配的资源进行回收。
4.构建spark的maven项目:
(1)在IDEA中“New Project”新建一个项目,在左侧选择“Maven”,右侧选中模板“Create from archetype”,选择倒数第五个scala模板,即“org.scala-tools.Archetypes:scala-archetype-simple”。
(2)点击“NEXT”,输入项目名“spark_project1”,之后再点击“NEXT”,最后点击“FINISH”。构建成功后需要等一段时间将pom文件依赖加载完毕。
新构建的“pom.xml”文件是不可以使用的(是错误的),需要更改。
(3)修改pom.xml文件,更改过程如下:
①将<inceptionYear>2008</inceptionYear>中的2008改为2021或者直接把这一行删掉。
②将下面代码中的2.7.0改为2.12.8
<properties>
<scala.version>2.7.0</scala.version>
</properties>
然后在“<scala.version>2.12.8</scala.version>”下面加一行
“<spark.version>2.4.2</spark.version>”作为spark的版本号
③将下面代码删掉(不删也行):我这里删了
<repositories>
<repository>
<id>scala-tools.org</id>
<name>Scala-Tools Maven2 Repository</name>
<url>http://scala-tools.org/repo-releases</url>
</repository>
</repositories>
<pluginRepositories>
<pluginRepository>
<id>scala-tools.org</id>
<name>Scala-Tools Maven2 Repository</name>
<url>http://scala-tools.org/repo-releases</url>
</pluginRepository>
</pluginRepositories>
④将下面代码中的“<scope>test</scope>”删掉
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.4</version>
<scope>test</scope>
</dependency>
⑤将下面的代码删掉:
<dependency>
<groupId>org.specs</groupId>
<artifactId>specs</artifactId>
<version>1.2.5</version>
<scope>test</scope>
</dependency>
⑥将下面的代码删掉:
<configuration>
<scalaVersion>${scala.version}</scalaVersion>
<args>
<arg>-target:jvm-1.5</arg>
</args>
</configuration>
⑦进入项目的目录结构,删掉“AppTest”和“MySpec”文件,将“org.example”文件夹也删掉。
src->test->scala->org.example->AppTest和MySpec
⑧进入项目的目录结构,将“App”文件删掉,将“org.example”文件夹也删掉。
src->main->scala->org.example->App
⑨在pom文件的第三行,将“<groupId>org.example</groupId>”修改为“<groupId>com.briup</groupId>”。
这里先更新一下pom文件,看看有没有报错,发现是成功的。
⑩目前在pom文件中只加入了内置的scala依赖,而spark依赖还没有导入,在pom文件的标签中加入下列代码,导入spark依赖:(依赖非常多,需要网络环境好一些)
<dependency>
<groupId>org.apache.spark</groupId>
<artifactId>spark-core_2.12</artifactId>
<version>${spark.version}</version>
</dependency>
⑪最后更新一下pom.xml文件,报了很多错误信息,报错信息如下:(一小部分)
could not transfer artifact com.twitter:chill_2.12:jar:0.9.3 from/to central
cannot resolve io.dropwizard.metrics:metrics-core:3.1.5
… …
解决办法:
★★★第一步:更改maven路径
打开IDEA路径“File”->“Settings”->“Build, Execution, Deployment”->“Build Tools”->“Maven”,然后修改“Maven home directory”右侧的内容为“D:/maven/apache-maven-3.5.4”,修改“User settings file”右侧的内容为“D:\maven\apache-maven-3.5.4\conf\settings.xml”,修改“Local repository”右侧的内容为“D:\maven\maven-repository”,然后点击“Apply”->“OK”。
★★★第二步:解决maven原镜像下载慢的问题
打开IDEA路径“File”->“Settings”->“Build, Execution, Deployment”->“Build Tools”->“Maven”,然后找到“User settings file”右侧的setting.xml路径“D:\maven\apache-maven-3.5.4\conf\settings.xml”,在这个setting.xml文件的<mirrors></mirrors>节点中添加以下代码:
<mirror>
<id>nexus-aliyun</id>
<mirrorOf>central</mirrorOf>
<name>Nexus aliyun</name>
<url>http://maven.aliyun.com/nexus/content/groups/public</url>
</mirror>
参考链接:https://blog.csdn.net/buyueliuying/article/details/78623503
全部加载后发现再次报错,但这次的报错信息不多,信息如下(其中一个):
Cannot resolve plugin org.scala-tools:maven-scala-plugin:<unknown>
解决办法:首先,IDEA插件自动生成的pom文件中scala的版本是2.7,这里需要修改成与本地scala一致的版本号,我的是2.12.8,报签中的<scala.version>2.12.8</scala.version>,这个在之前就已经修改过了,所以这里不做修改;然后,在pom.xml文件中添加如下依赖:
<dependency>
<groupId>org.scala-tools</groupId>
<artifactId>maven-scala-plugin</artifactId>
<version>2.12</version>
</dependency>
<dependency>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-eclipse-plugin</artifactId>
<version>2.5.1</version>
</dependency>
这次更新后的pom.xml文件就成功了,不再报错。
参考链接:https://blog.csdn.net/Adnerly/article/details/106767529
⑫最终的pom.xml文件内容为:
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.briup</groupId>
<artifactId>spark_project1</artifactId>
<version>1.0-SNAPSHOT</version>
<properties>
<scala.version>2.12.8</scala.version>
<spark.version>2.4.2</spark.version>
</properties>
<dependencies>
<dependency>
<groupId>org.scala-lang</groupId>
<artifactId>scala-library</artifactId>
<version>${scala.version}</version>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.4</version>
</dependency>
<dependency>
<groupId>org.apache.spark</groupId>
<artifactId>spark-core_2.12</artifactId>
<version>${spark.version}</version>
</dependency>
<dependency>
<groupId>org.scala-tools</groupId>
<artifactId>maven-scala-plugin</artifactId>
<version>2.12</version>
</dependency>
<dependency>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-eclipse-plugin</artifactId>
<version>2.5.1</version>
</dependency>
</dependencies>
<build>
<sourceDirectory>src/main/scala</sourceDirectory>
<testSourceDirectory>src/test/scala</testSourceDirectory>
<plugins>
<plugin>
<groupId>org.scala-tools</groupId>
<artifactId>maven-scala-plugin</artifactId>
<executions>
<execution>
<goals>
<goal>compile</goal>
<goal>testCompile</goal>
</goals>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-eclipse-plugin</artifactId>
<configuration>
<downloadSources>true</downloadSources>
<buildcommands>
<buildcommand>ch.epfl.lamp.sdt.core.scalabuilder</buildcommand>
</buildcommands>
<additionalProjectnatures>
<projectnature>ch.epfl.lamp.sdt.core.scalanature</projectnature>
</additionalProjectnatures>
<classpathContainers>
<classpathContainer>org.eclipse.jdt.launching.JRE_CONTAINER</classpathContainer>
<classpathContainer>ch.epfl.lamp.sdt.launching.SCALA_CONTAINER</classpathContainer>
</classpathContainers>
</configuration>
</plugin>
</plugins>
</build>
<reporting>
<plugins>
<plugin>
<groupId>org.scala-tools</groupId>
<artifactId>maven-scala-plugin</artifactId>
<configuration>
<scalaVersion>${scala.version}</scalaVersion>
</configuration>
</plugin>
</plugins>
</reporting>
</project>
5.构建独立应用环境
代码编写结构如下:
写spark代码时的程序入口,每次都需要做的操作如下。
(1)获取SparkConf对象:val conf=new SparkConf
(2)获取SparkContext对象:val sc=new SparkContext(conf)
(3)获取RDD对象:val rdd:RDD[T]=sc.方法(参数)
根据RDD所对应的一系列转化方法和行动方法来构建代码。
(4)关闭SparkContext对象:sc.stop()
如:一个简单的词频统计案例
package com.briup
import org.apache.spark.{SparkConf, SparkContext}
object FirstSpark {
def main(args: Array[String]): Unit = {
//1.获取SparkConf对象
val conf = new SparkConf()
conf.setMaster("local[*]") //设置master,运行到本地模式
conf.setAppName("词频统计") //设置程序的名字
//2.利用SparkConf对象获取SparkContext对象
val sc = new SparkContext(conf)
sc.setLogLevel("warn") //设置日志级别,设置后,SparkContext对象会在日志的最后一行显示
println(sc) //打印SparkContext对象
//3.利用SparkContext对象获取RDD对象
//4.调用转化方法或者行动方法
//5.关闭SparkContext对象
sc.stop()
}
}
运行报错,报错信息为:
21/09/07 10:26:07 ERROR Shell: Failed to locate the winutils binary in the hadoop binary path
java.io.IOException: Could not locate executable null\bin\winutils.exe in the Hadoop binaries.
这个错误不用管,忽略即可。不过我搜索了一下,发现出现问题的原因是:无法定位可执行文件winutil。在使用spark开发时用到了hadoop工具,而Hadoop运行在Linux下。所以需要使用winutils插件。
参考链接:https://blog.csdn.net/sugar_HIT/article/details/102807103
继续编写FirstSpark程序并运行。
package com.briup
import org.apache.spark.rdd.RDD
import org.apache.spark.{SparkConf, SparkContext}
/*
* 1.编写代码
* 2.打成jar包到集群上运行:
* 前提:将“conf.setMaster("local[*]")”这一行注释掉;输出到控制台还是文件里面二选一
* 3.打开虚拟机,开启主节点集群和从节点集群
* start-master.sh
* start-slave.sh spark://hadoopPD:7077
* jps查看是否有Master和Worker进程,有的话继续下一步操作
* 4.将jar包上传到虚拟机上面(两种方式):
* (1)在“target”目录下找到刚刚打包成功的jar包(XXX.jar文件),右键选择“Deployment”->“Upload to hadoopPD”,在虚拟机中ls查看是否上传成功
* (2)直接复制jar包粘贴到虚拟机的家目录下面
* 5.提交任务,命令如下:
* (1)将数据输入到文件中
* spark-submit --master spark://hadoopPD:7077 --class com.briup.FirstSpark spark_project1-1.0-SNAPSHOT.jar /opt/software/spark/README.md /home/briup/wordcount
* (2)将数据直接输出到控制台上
* spark-submit --master spark://hadoopPD:7077 --class com.briup.FirstSpark spark_project1-1.0-SNAPSHOT.jar /opt/software/spark/README.md
* */
object FirstSpark {
def main(args: Array[String]): Unit = {
/*
* 简单判断参数:如果参数args的长度小于2,则直接退出系统
* */
if(args.length<2){
// println("请输入文件路径")
System.exit(0)
}
//1.获取SparkConf对象
val conf = new SparkConf()
// conf.setMaster("local[*]") //设置master,运行到本地模式,如果要运行集群模式,这一行必须注释掉
conf.setAppName("词频统计") //设置程序的名字
//2.利用SparkConf对象获取SparkContext对象
val sc = new SparkContext(conf)
sc.setLogLevel("warn") //设置日志级别,设置后,SparkContext对象会在日志的最后一行显示
println(sc) //打印SparkContext对象
/*
* 3.利用SparkContext对象获取RDD对象
* 获取RDD方式:读取文件
* 读取外部数据集获取RDD对象:这里的"data/words.txt"路径是写死的路径,如果想自己输入路径,不把路径写死,需要使用args参数
* 先右击项目“spark_project1”,然后选择“New”->“Directory”,输入名字“data”,在该目录下创建一个“File”,取名为“words.txt”
* 在该文件下输入下列内容:
* hello world
* mapreduce world
* hello nihao
* hello
* 双击“textRDD”对象,把鼠标往左移动,会发现一个黄色小灯泡,选择“Add type annotation to value definition”,会自动出现该对象的类型
* */
// val textRDD: RDD[String] = sc.textFile("data/words.txt")
val textRDD: RDD[String] = sc.textFile(args(0)) //输入路径
/*
* 4.根据业务需求调用转化方法或者行动方法
* 一开始想不到flatMap方法,用的是map方法,然后查看它的类型,在[]中还有一个array数组,即[[X,Y,Z]]的形式,两层数组包围的形式无法统计次数,
* 所以改变一下函数,变为flatMap(),查看类型,是[X,Y,Z]形式
* [[X,Y,Z]]--->[X,Y,Z],所以map()--->flatMap()
* */
val RDD: RDD[String] = textRDD.flatMap((x:String)=>{x.split(" ")})
//[hello,world,nihao...]--->(hello,1)(world,1)
val mapRDD: RDD[(String, Int)] = RDD.map((x)=> {(x, 1)})
/*
* 变形过程:
* 原始为((x,y)=>x+y),由于x和y都只出现了一次,所以可以用下划线代替,变为_+_的形式
* */
val wordCountRDD: RDD[(String, Int)] = mapRDD.reduceByKey(_+_)
//将计算结果输出到控制台
wordCountRDD.foreach(println)
//将计算结果输出到文件里:如果这个方法不可行,那就手动打成jar包去虚拟机提交
// wordCountRDD.saveAsTextFile("data/file1")
// wordCountRDD.saveAsTextFile(args(1)) //输出路径
//5.关闭SparkContext对象
sc.stop()
}
}
6.配置:如何直接上传jar包到虚拟机中(只在本项目中起作用)
(1)在IDEA中点击“Tools”->“Deployment”->“Configuration…”->左上角的“+”号->点击“SFTP”->输入名字“hadoopPD”。
(2)然后在新出现的界面中填写内容,配置完这个内容,就可以自动上传jar包了。
先在“Connection”标签下设置:填写“Host”为自己的IP地址“192.168.255.136”->“User name”是虚拟机里面的用户名“briup”->“Password”是用户名的密码“briup123”->“Root path”是jar包上传的位置,这里设置成“/home/briup”。
然后在“Mappings”标签下设置:“Local path”是每次jar包的生成位置,设置为该项目的“target”目录下,即“D:\idea2019\spark_project1\target”->“Deployment path”和“Web path”都设置为“/”。
配置完成后,再进入“Connection”标签下,点击“TEST CONNECTION”按钮进行测试(前提是虚拟机是打开的),然后就弹出测试成功的弹框,点击“OK”关闭。
(3)然后点击右侧的“Maven”的“install”打成jar包,在“target”目录下找到刚刚打包成功的jar包(XXX.jar文件),右键选择“Deployment”->“Upload to hadoopPD”,然后就上传成功了。
(在这个过程中发现idea的tools下面没有deployment选项,解决办法:进入File->Settings->Plugins,勾选FTP/SFTP Connectivity(ex.Remote Hosts Access)插件,没有的话在市场上下载一下)
注意:
①问题:
在IDEA里面下载IDEA插件的时候,MarketPlace那个圈圈总是转很久然后加载不出来。
②解决方案(win10):
打开控制面板–>系统和安全–>windows defender 防火墙–>启用和关闭windows defender 防火墙,然后把两个开启都设置为关闭,这个时候再去IDEA里面下载插件就可以了。下载完需要把防火墙设置改回去。
参考链接:
https://blog.csdn.net/qq_36986067/article/details/110954429