上篇:第1章 大数据Spark概述
(1)官网地址
http://spark.apache.org/
(2)文档查看地址
https://spark.apache.org/docs/2.1.1/
(3)下载地址
https://spark.apache.org/downloads.html
Spark的驱动器是执行开发程序中的main方法的进程。它负责开发人员编写的用来创建SparkContext、创建RDD,以及进行RDD的转化操作和行动操作代码的执行。如果你是用spark
shell,那么当你启动Spark shell的时候,系统后台自启了一个Spark驱动器程序,就是在Spark shell中预加载的一个叫作
sc的SparkContext对象。如果驱动器程序终止,那么Spark应用也就结束了。
主要负责:
(1)把用户程序转为作业(JOB)
(2)跟踪Executor的运行状况
(3)为执行器节点调度任务
(4)UI展示应用运行状况
Spark Executor是一个工作进程,负责在 Spark 作业中运行任务,任务间相互独立。
Spark应用启动时,Executor节点被同时启动,并且始终伴随着整个
Spark 应用的生命周期而存在。如果有Executor节点发生了故障或崩溃,
Spark应用也可以继续执行,会将出错节点上的任务调度到其他Executor节点上继续运行。
主要负责:
(1)负责运行组成 Spark 应用的任务,并将结果返回给驱动器进程;
(2)通过自身的块管理器(Block Manager)为用户程序中要求缓存的RDD提供内存式存储。RDD是直接缓存在Executor进程内的,因此任务可以在运行时充分利用缓存数据加速运算。
(1)上传并解压spark安装包spark-2.1.1-bin-hadoop2.7.tgz安装包
上传:
自己是上传到/usr/local/hadoop文件目录下的
解压:
[root@hadoop105 hadoop]# tar -zxvf spark-2.1.1-bin-hadoop2.7.tgz -C /usr/local/hadoop/module/
重命名:
[root@hadoop105 module]# mv spark-2.1.1-bin-hadoop2.7 spark
(2)官方求PI案例
[root@hadoop105 spark]# bin/spark-submit \
> --class org.apache.spark.examples.SparkPi \
> --executor-memory 1G \
> --total-executor-cores 2 \
> ./examples/jars/spark-examples_2.11-2.1.1.jar \
> 100
再执行一条命令,结果展示:
说明环境没问题!(该算法是利用蒙特·卡罗算法求PI)
[root@hadoop105 spark]# bin/spark-shell
......
Spark context Web UI available at http://192.168.219.105:4040
Spark context available as 'sc' (master = local[*], app id = local-1580564683773).
Spark session available as 'spark'.
Welcome to
____ __
/ __/__ ___ _____/ /__
_\ \/ _ \/ _ `/ __/ '_/
/___/ .__/\_,_/_/ /_/\_\ version 2.1.1
/_/
Using Scala version 2.11.8 (Java HotSpot(TM) 64-Bit Server VM, Java 1.8.0_144)
Type in expressions to have them evaluated.
Type :help for more information.
scala>
补充一下:
(1)基本语法
bin/spark-submit \
--class <main-class>
--master <master-url> \
--deploy-mode <deploy-mode> \
--conf <key>=<value> \
... # other options
<application-jar> \
[application-arguments]
(2)参数说明:
–master 指定Master的地址,默认为Local
–class: 你的应用的启动类 (如org.apache.spark.examples.SparkPi)
–deploy-mode: 是否发布你的驱动到worker节点(cluster) 或者作为一个本地客户端 (client) (default: client)
–conf: 任意的Spark配置属性, 格式key=value. 如果值包含空格,可以加引号“key=value”
application-jar: 打包好的应用jar,包含依赖. 这个URL在集群中全局可见。 比如hdfs:// 共享存储系统, 如果是
file:// path, 那么所有的节点的path都包含同样的jar
application-arguments: 传给main()方法的参数
–executor-memory 1G 指定每个executor可用内存为1G
–total-executor-cores 2 指定每个executor使用的cup核数为2个
(4)准备文件
[root@hadoop105 spark]# mkdir input
在input下创建2个文件:1.txt和2.txt,并输入以下内容
[root@hadoop105 input]# touch 1.txt
[root@hadoop105 input]# touch 2.txt
[root@hadoop105 input]#
添加输出内容:
[root@hadoop105 input]# vim 1.txt
hello atguigu
hello spark
[root@hadoop105 input]# vim 2.txt
hello atguigu
hello spark
执行sc查看spark的数据信息
scala> sc
res0: org.apache.spark.SparkContext = org.apache.spark.SparkContext@576a8b00
读取文件将会得到字符串,执行命令如下:
scala> sc.textFile("input")
res1: org.apache.spark.rdd.RDD[String] = input MapPartitionsRDD[1] at textFile at <console>:25
scala> sc.textFile("input").flatMap(_.split("")).map((_,1)).reduceByKey
reduceByKey reduceByKeyLocally
scala> sc.textFile("input").flatMap(_.split("")).map((_,1)).reduceByKey(_+_)
res4: org.apache.spark.rdd.RDD[(String, Int)] = ShuffledRDD[6] at reduceByKey at <console>:25
scala> sc.textFile("input").flatMap(_.split("")).map((_,1)).reduceByKey(_+_).co
coalesce collectAsMap combineByKeyWithClassTag copy countApproxDistinct countByKey countByValueApprox
cogroup collectAsync compute count countApproxDistinctByKey countByKeyApprox
collect combineByKey context countApprox countAsync countByValue
scala> sc.textFile("input").flatMap(_.split("")).map((_,1)).reduceByKey(_+_).collect
res5: Array[(String, Int)] = Array((p,2), (t,2), (h,4), (" ",4), (r,2), (l,8), (s,2), (e,4), (a,4), (i,2), (k,2), (u,4), (o,4), (g,4))
scala>
可登录http://hadoop105:4040
查看程序运行
可登录hadoop105:4040查看程序运行
(5)WordCount程序分析
提交任务分析:
数据流分析:
textFile(“input”):读取本地文件input文件夹数据;
flatMap(_.split(" ")):压平操作,按照空格分割符将一行数据映射成一个个单词;
map((_,1)):对每一个元素操作,将单词映射为元组;
reduceByKey(+):按照key将值进行聚合,相加;
collect:将数据收集到Driver端展示。
WordCount案例分析
构建一个由Master+Slave构成的Spark集群,Spark运行在集群中。
(1)进入spark安装目录下的conf文件夹
[root@hadoop105 local]# cd hadoop/module/spark/conf/
[root@hadoop105 conf]#
(2)修改配置文件名称
[root@hadoop105 conf]# mv slaves.template slaves
[root@hadoop105 conf]# vim slaves
Hadoop105
Hadoop106
Hadoop107
(3)修改spark-env.sh文件,添加如下配置:
[root@hadoop105 conf]# vim spark-env.sh
SPARK_MASTER_HOST=hadoop105
SPARK_MASTER_PORT=7077
(4)分发spark包到别的机器(hadoop106、Hadoop107)
[root@hadoop105 module]# scp -r spark/ hadoop106:/usr/local/hadoop/module/
[root@hadoop105 module]# scp -r spark/ hadoop107:/usr/local/hadoop/module/
(5)启动
[root@hadoop105 spark]$ sbin/start-all.sh
注意:如果遇到 “JAVA_HOME not set” 异常,可以在sbin目录下的spark-config.sh 文件中
[root@hadoop105 spark]# cd conf/
[root@hadoop105 conf]# vim spark-env.sh
#JAVA_HOME
export JAVA_HOME=/usr/local/java/module/jdk1.8
再次启动:
[root@hadoop105 spark]# sbin/start-all.sh
starting org.apache.spark.deploy.master.Master, logging to /usr/local/hadoop/module/spark/logs/spark-root-org.apache.spark.deploy.master.Master-1-hadoop105.out
hadoop107: starting org.apache.spark.deploy.worker.Worker, logging to /usr/local/hadoop/module/spark/logs/spark-root-org.apache.spark.deploy.worker.Worker-1-hadoop107.out
hadoop106: starting org.apache.spark.deploy.worker.Worker, logging to /usr/local/hadoop/module/spark/logs/spark-root-org.apache.spark.deploy.worker.Worker-1-hadoop106.out
hadoop105: starting org.apache.spark.deploy.worker.Worker, logging to /usr/local/hadoop/module/spark/logs/spark-root-org.apache.spark.deploy.worker.Worker-1-hadoop105.out
由于更改过配置参数,启动之前,需要重新分发到两台机器上!
[root@hadoop105 module]# scp -r spark/ hadoop106:/usr/local/hadoop/module/
[root@hadoop105 module]# scp -r spark/ hadoop107:/usr/local/hadoop/module/
(1)修改spark-default.conf.template名称
[root@hadoop105 spark]# cd conf/
[root@hadoop105 conf]# mv spark-defaults.conf.template spark-defaults.conf
[root@hadoop105 conf]#
(2)修改spark-default.conf文件,开启Log:
[root@hadoop105 conf]# vim spark-defaults.conf
spark.eventLog.enabled true
spark.eventLog.dir hdfs://hadoop105:9000/directory
注意:HDFS上的目录需要提前存在。
(3)修改spark-env.sh文件,添加如下配置:
[root@hadoop105 conf]# vim spark-env.sh
export SPARK_HISTORY_OPTS="-Dspark.history.ui.port=18080
-Dspark.history.retainedApplications=30
-Dspark.history.fs.logDirectory=hdfs://hadoop105:9000/directory"
参数描述:
spark.eventLog.dir:Application在运行过程中所有的信息均记录在该属性指定的路径下;
spark.history.ui.port=18080 WEBUI访问的端口号为18080
spark.history.fs.logDirectory=hdfs://hadoop105:9000/directory 配置了该属性后,在start-history-server.sh时就无需再显式的指定路径,Spark History Server页面只展示该指定路径下的信息
spark.history.retainedApplications=30指定保存Application历史记录的个数,如果超过这个值,旧的应用程序信息将被删除,这个是内存中的应用数,而不是页面上显示的应用数。
(4)分发配置文件
[root@hadoop105 module]# scp -r spark/ hadoop106:/usr/local/hadoop/module/
[root@hadoop105 module]# scp -r spark/ hadoop107:/usr/local/hadoop/module/
(5)启动历史服务
[root@hadoop105 spark]# sbin/start-history-server.sh
starting org.apache.spark.deploy.history.HistoryServer, logging to /usr/local/hadoop/module/spark/logs/spark-root-org.apache.spark.deploy.history.HistoryServer-1-hadoop105.out
(6)再次执行任务
[root@hadoop105 spark]# bin/spark-submit \
> --class org.apache.spark.examples.SparkPi \
> --master spark://hadoop105:7077 \
> --executor-memory 1G \
> --total-executor-cores 2 \
> ./examples/jars/spark-examples_2.11-2.1.1.jar \
> 100
出现错误信息:
java.lang.ClassNotFoundException: org.apache.spark.examples.SparkPi
at java.net.URLClassLoader.findClass(URLClassLoader.java:381)
at java.lang.ClassLoader.loadClass(ClassLoader.java:424)
at java.lang.ClassLoader.loadClass(ClassLoader.java:357)
at java.lang.Class.forName0(Native Method)
at java.lang.Class.forName(Class.java:348)
at org.apache.spark.util.Utils$.classForName(Utils.scala:229)
at org.apache.spark.deploy.SparkSubmit$.org$apache$spark$deploy$SparkSubmit$$runMain(SparkSubmit.scala:700)
at org.apache.spark.deploy.SparkSubmit$.doRunMain$1(SparkSubmit.scala:187)
at org.apache.spark.deploy.SparkSubmit$.submit(SparkSubmit.scala:212)
at org.apache.spark.deploy.SparkSubmit$.main(SparkSubmit.scala:126)
at org.apache.spark.deploy.SparkSubmit.main(SparkSubmit.scala)
(2)修改spark-env.sh文件添加如下配置:
[root@hadoop105 conf]# vim spark-env.sh
注释掉如下内容:
#SPARK_MASTER_HOST=hadoop105
#SPARK_MASTER_PORT=7077
添加上如下内容:
export SPARK_DAEMON_JAVA_OPTS="
-Dspark.deploy.recoveryMode=ZOOKEEPER
-Dspark.deploy.zookeeper.url=hadoop105,hadoop106,hadoop107
-Dspark.deploy.zookeeper.dir=/spark"
(3)分发配置文件
[rootu@hadoop105 conf]$ xsync spark-env.sh
(4)在hadoop105上启动全部节点
[root@hadoop105 spark]# sbin/start-all.sh
(5)在hadoop106上单独启动master节点
[root@hadoop106 spark]# sbin/start-master.sh
(6)spark HA集群访问
[root@hadoop105 spark]# /usr/local/hadoop/module/spark/bin/spark-shell \
> --master spark://hadoop105:7077,hadoop106:7077 \
> --executor-memory 2g \
> --total-executor-cores 2
构建工程ok
(1)创建一个Maven项目WordCount并导入依赖
<dependencies>
<dependency>
<groupId>org.apache.spark</groupId>
<artifactId>spark-core_2.11</artifactId>
<version>2.1.1</version>
</dependency>
</dependencies>
<build>
<finalName>WordCount</finalName>
<plugins>
<plugin>
<groupId>net.alchim31.maven</groupId>
<artifactId>scala-maven-plugin</artifactId>
<version>3.2.2</version>
<executions>
<execution>
<goals>
<goal>compile</goal>
<goal>testCompile</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
(2)在src/main文件下创建scala文件,scala文件标有颜色是正常的
并在scala文件目录下创建一个包,自己定义的包名为:com.study.bigdatabase,并在该包下创建一个WordCount类
scala语言主程序入口快捷键:main+Tab
我们尝试创建Spark上下文对象:val sc = new SparkContext()
,并快捷键:ctrl+鼠标 点击 new SparkContext查看源码:
测试Spark框架当前环境,其具体代码如下:
WordCoun.scala
package com.study.bigdatabase
import org.apache.spark.{SparkConf, SparkContext}
object WordCoun {
def main(args: Array[String]): Unit = {
//使用k开发工具完成Spark WordCount的开发
//Local模式
//创建SparkConf对象
//设置Sparkj计算框架y运行(部署)环境
//app id
val config: SparkConf = new SparkConf().setMaster("local[*]").setAppName("WordCount")
//创建Spark上下文对象
val sc = new SparkContext(config)
println(sc)
}
}
启动程序,控制台打印出信息:
我们点击项目栏目创建一个文件,取名:in
并在in文件夹下创建一个word.txt文件
word.txt
Hello Scala
Hello Spark
Hello World
Hello Hadoop
Hello Scala
其具体代码实现,如下:
package com.study.bigdatabase
import org.apache.spark.rdd.RDD
import org.apache.spark.{SparkConf, SparkContext}
object WordCoun {
def main(args: Array[String]): Unit = {
//使用k开发工具完成Spark WordCount的开发
//Local模式
//创建SparkConf对象
//设置Sparkj计算框架y运行(部署)环境
//app id
val config: SparkConf = new SparkConf().setMaster("local[*]").setAppName("WordCount")
//创建Spark上下文对象
val sc = new SparkContext(config)
//读取文件,将文件内容一行一行的读取出来
val lines:RDD[String] = sc.textFile("in")
//将一行一行的数据分解一个一个单词
val words:RDD[String] = lines.flatMap(_.split(" "))
//为了统计方便,将单词s数据结构进行转换
val wordToOne: RDD[(String,Int)] = words.map((_, 1))
//对转换结构后的数据进行分组聚合
val wordToSum:RDD[(String,Int)] = wordToOne.reduceByKey(_ + _)
//将统计结果采集后打印到控制台
val result:Array[(String,Int)] = wordToSum.collect()
//打印输出的数据
result.foreach(println)
}
}
启动其程序,控制台打印出信息:
同样在运行过程中,发生一些错误信息:
java.io.IOException: Could not locate executable null\bin\winutils.exe in the Hadoop binaries.
分析异常:根据提示应该是Hadoop binaries.中缺少winutils.exe这个配置。
解决方法:
(1)由于自己没有在hadoop配置环境,尝试配置一下看
window的hadoop环境设置
(2)重启idea工具即可,就解决问题
Spark客户端直接连接Yarn,不需要额外构建Spark集群。有yarn-client和yarn-cluster两种模式,
主要区别在于:Driver程序的运行节点。
yarn-client:Driver程序运行在客户端,适用于交互、调试,希望立即看到app的输出
yarn-cluster:Driver程序运行在由RM(ResourceManager)启动的AP(APPMaster)适用于生产环境。
(1)修改hadoop配置文件yarn-site.xml,添加如下内容:
<!--是否启动一个线程检查每个任务正使用的物理内存量,如果任务超出分配值,则直接将其杀掉,默认是true -->
<property>
<name>yarn.nodemanager.pmem-check-enabled</name>
<value>false</value>
</property>
<!--是否启动一个线程检查每个任务正使用的虚拟内存量,如果任务超出分配值,则直接将其杀掉,默认是true -->
<property>
<name>yarn.nodemanager.vmem-check-enabled</name>
<value>false</value>
</property>
(2)修改spark-env.sh,添加如下配置:
YARN_CONF_DIR=/usr/local/hadoop/module/hadoop-2.7.2/etc/hadoop
(3)分发配置文件(hadoop106、hadoop107)
[root@hadoop105 module]# scp -r hadoop-2.7.2/ hadoop106:/usr/local/hadoop/module/
[root@hadoop105 module]# scp -r hadoop-2.7.2/ hadoop107:/usr/local/hadoop/module/
(4)执行一个程序
[root@hadoop105 spark]# bin/spark-submit \
> --class org.apache.spark.examples.SparkPi \
> --master yarn \
> --deploy-mode client \
> ./examples/jars/spark-examples_2.11-2.1.1.jar \
> 100
注意:在提交任务之前需启动HDFS以及YARN集群。
再执行:
[root@hadoop105 spark]# bin/spark-shell --master yarn