大数据之spark学习记录二: Spark的安装与上手
文章目录
Spark安装
下载Sparkhttp://spark.apache.org/,注意版本的选择
spark和hadoop的版本对应,我这里是hadoop2.7–spark2.1.1
spark和scala的版本对应,我这里是spark2.1.1–scala2.11
解压下载的.tgz压缩包
tar -zxvf yourspark.tgz -C 指定的目录位置
看个人喜好重命名spark
mv spark-2.1.1-bin-hadoop2.7/ spark
本地模式
Local 模式就是指的只在一台计算机上来运行 Spark.
通常用于测试的目的来使用 Local 模式, 实际的生产环境中不会使用 Local 模式.
cp -r spark spark-local
为避免多种运行模式之间繁琐的修改,直接拷贝出一个单独的spark软件包命名为spark-local,接下来本地模式的安装就在该安装包下进行
进入该目录可以看到spark的目录结构如下:
其中conf目录下是一些Spark的配置文件
local模式下无需对默认配置进行修改
使用官方测试jar包提交计算 π \pi π的job,测试本地模式
bin/spark-submit --master local[2] --class org.apache.spark.examples.SparkPi ./examples/jars/spark-examples_2.11-2.1.1.jar 100
或者使用官方提供的测试命令
./bin/run-example SparkPi 10
这里对spark发布应用程序的脚本参数做一个说明
语法:
./bin/spark-submit \
--class <main-class> \
--master <master-url> \
--deploy-mode <deploy-mode> \
--conf <key>=<value> \
... # other options
<application-jar> \
[application-arguments]
-
--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 6
指定所有executor使用的cpu核数为6个 -
--executor-cores
表示每个executor使用的 cpu 的核数
关于 Master URL 的说明
Master URL | Meaning |
---|---|
local | Run Spark locally with one worker thread (i.e. no parallelism at all). |
local[K] | Run Spark locally with K worker threads (ideally, set this to the number of cores on your machine). |
local[*] | Run Spark locally with as many worker threads as logical cores on your machine. |
spark://HOST:PORT | Connect to the given Spark standalone cluster master. The port must be whichever one your master is configured to use, which is 7077 by default. |
mesos://HOST:PORT | Connect to the given Mesos cluster. The port must be whichever one your is configured to use, which is 5050 by default. Or, for a Mesos cluster using ZooKeeper, use mesos://zk://… To submit with --deploy-mode cluster, the HOST:PORT should be configured to connect to the MesosClusterDispatcher. |
yarn | Connect to a YARNcluster in client or cluster mode depending on the value of --deploy-mode. The cluster location will be found based on the HADOOP_CONF_DIR or YARN_CONF_DIR variable. |
spark还为我们提供了一个交互式命令窗口(类似于 Scala 的 REPL)
在 Spark-shell 中使用 Spark 来统计文件中各个单词的数量.
步骤1: 创建 2 个文本文件分并别在 a.txt 和 b.txt 内输入一些单词.
mkdir input
cd input
echo hello spark hello scala hello bigdata spark scala bigdata >> a.txt
echo hello spark hello scala bigdata spark scala >> b.txt
步骤2: 打开 Spark-shell
bin/spark-shell
步骤3: 运行 wordcount 程序
scala> sc.textFile("./input").flatMap(_.split("\\W+")).map((_,1)).reduceByKey(_ + _).collect
res4: Array[(String, Int)] = Array((scala,4), (hello,5), (spark,4), (bigdata,3))
步骤4: 登录http://yourIP:4040查看程序运行
Standalone 模式
只有Spark,没有其余的大数据框架如hadoop.zookeeper参与的运行模型称之为独立模型Standalone
这个要和 Hadoop 中的 Standalone 区别开来. 这里的 Standalone 是指只用 Spark 来搭建一个集群, 不需要借助其他的框架.是相对于 Yarn 和 Mesos 来说的.
基本配置
步骤1: 复制 spark, 并命名为spark-standalone
cp -r spark spark-standalone
步骤2: 进入配置文件目录conf, 配置spark-evn.sh
cd conf/
cp spark-env.sh.template spark-env.sh
在spark-env.sh文件中配置如下内容:
SPARK_MASTER_HOST=hadoop102
SPARK_MASTER_PORT=7077 # 默认端口就是7077, 可以省略不配
步骤3: 修改 slaves 文件, 添加 worker 节点
cp slaves.template slaves
在slaves文件中配置如下内容:
hadoop102
hadoop103
hadoop104
步骤4: 分发spark-standalone
xsync spark-standalone
步骤5: 在master节点启动 Spark 集群
sbin/start-all.sh
对于Standalone模式,Spark提供的WebUI外部接口:
master:8080
worker:8081
dirver:4040 --程序结束就不能访问了,所以需要配置历史服务器
而内部的master接口默认为7077
测试计算Pi的Application
bin/spark-submit \
--class org.apache.spark.examples.SparkPi \
--master spark://hadoop102:7077 \
--executor-memory 1G \
--total-executor-cores 6 \
--executor-cores 2 \
./examples/jars/spark-examples_2.11-2.1.1.jar 100
测试spark shell wordCount
bin/spark-shell --master spark://hadoop102:7077
需要指名master,否则运行的是本地模式
sc.textFile("input").flatMap(_.split("\\W+")).map((_,1)).reduceByKey(_+_).collect
可以看到结果是有了,但是报了一大堆错误
比如:Caused by: java.io.FileNotFoundException: File file:/opt/module/spark-standalone/input/a.txt does not exist
可以根据字面意思猜测是因为其他worker节点上并没有input这个数据
Standalone模式并不涉及到分布式存储即HDFS
我们不妨分发一一下再试着运行
配置 Spark 任务历史服务器(Standalone 模式)
在 Spark-shell 没有退出之前, 我们是可以看到正在执行的任务的日志情况:http://masterIP:4040. 但是退出 Spark-shell 之后, 执行的所有任务记录全部丢失.
所以需要配置任务的历史服务器, 方便在任何需要的时候去查看日志.
步骤1: 配置spark-default.conf文件, 开启 Log
cp spark-defaults.conf.template spark-defaults.conf
在spark-defaults.conf文件中, 添加如下内容:
spark.eventLog.enabled true
spark.eventLog.dir hdfs://hadoop102:9000/spark-log
注意:hdfs://hadoop102:9000/spark-log 目录必须提前存在, 名字随意
步骤2: 修改spark-env.sh文件,添加如下配置.
export SPARK_HISTORY_OPTS="-Dspark.history.ui.port=18080 -Dspark.history.retainedApplications=30 -Dspark.history.fs.logDirectory=hdfs://hadoop102:9000/spark-log"
步骤3: 分发配置文件
xsync conf/
步骤4: 启动历史服务
需要先启动 HDFS
start-dfs.sh
然后再启动:
sbin/start-history-server.sh
步骤5: 启动任务, 查看历史服务器(18080)
bin/spark-submit \
--class org.apache.spark.examples.SparkPi \
--master spark://hadoop102:7077 \
--executor-memory 1G \
./examples/jars/spark-examples_2.11-2.1.1.jar 100
HA配置(Standalone)
由于Spark默认的master和hadoop的namenode一样,只有一个,所以一旦这个管家宕机,整个大数据集群就会陷入瘫痪状态,在生产环境中,必须配置高可用(HA),同样,与其他大数据框架类似,通过Zookeeper来配置高可用。
这样,就可以启动多个 master, 先启动的处于 Active 状态, 其他的都处于 Standby 状态,当master挂掉,通过选举机制就可以找到新的Leader作为master。
步骤1: 给 spark-env.sh 添加如下配置
# 注释掉如下内容:
#SPARK_MASTER_HOST=hadoop102
#SPARK_MASTER_PORT=7077
# 添加上如下内容:
export SPARK_DAEMON_JAVA_OPTS="-Dspark.deploy.recoveryMode=ZOOKEEPER
-Dspark.deploy.zookeeper.url=hadoop102:2181,hadoop103:2181,hadoop104:2181
-Dspark.deploy.zookeeper.dir=/spark"
步骤2: 分发配置文件
xsync spark-env.sh
步骤3: 启动 Zookeeper
zkstart.sh
#!/bin/bash
for i in atguigu@hadoop102 atguigu@hadoop103 atguigu@hadoop104
do
echo "================ $i ================"
ssh $i '/opt/module/zookeeper-3.4.10/bin/zkServer.sh start'
done
步骤4: 在 原master启动全部节点
sbin/start-all.sh
sbin/start-history-server.sh
会在当前节点启动一个 master
步骤5: 在 hadoop103 启动一个 master
sbin/start-master.sh
步骤6: 查看 master 的状态
步骤7: 杀死 hadoop102 的 master 进程
hadoop103 的 master 会自动切换成 Active
Yarn模式(开发重点)
Spark 客户端可以直接连接 Yarn,不需要额外构建Spark集群。
有 client 和 cluster 两种模式,主要区别在于:Driver 程序的运行节点不同。
-
client:Driver程序运行在客户端,适用于交互、调试,希望立即看到app的输出
-
cluster:Driver程序运行在由 RM(ResourceManager)启动的 AM(AplicationMaster)上, 适用于生产环境。
基本配置
步骤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, 并命名为spark-yarn
cp -r spark spark-yarn
步骤3: 修改spark-evn.sh文件
配置日志服务(同Standalone模式)
并添加如下配置: 告诉 spark 客户端 yarn 相关配置
YARN_CONF_DIR=/opt/module/hadoop-2.7.2/etc/hadoop
步骤4: 执行一段程序
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
注意master 由hadoop102变为了yarn
日志服务
在前面的页面中点击 history 无法直接连接到 spark 的日志.
可以在spark-default.conf中添加如下配置达到上述目的
spark.yarn.historyServer.address=hadoop102:18080
spark.history.ui.port=18080
可能碰到的问题:
如果在 yarn 日志端无法查看到具体的日志, 则在yarn-site.xml中添加如下配置
<property>
<name>yarn.log.server.url</name>
<value>http://hadoop104:19888/jobhistory/logs</value>
</property>
然后记得分发一下。
yarn spark shell
bin/spark-shell --master yarn
跑一个wordCount,先把之前创建的input上传到hdfs根目录
hadoop fs -put input /
然后运行scala脚本
scala> sc.textFile("hdfs://hadoop102:9000/input").flatMap(_.split("\\W+")).map((_,1)).reduceByKey(_ + _).collect
res0: Array[(String, Int)] = Array((scala,4), (hello,5), (spark,4), (bigdata,3))
几种spark 运行模式的对比
模式 | Spark安装机器数 | 需启动的进程 | 所属者 |
---|---|---|---|
Local | 1 | 无 | Spark |
Standalone | 多台 | Master及Worker | Spark |
Yarn | 1 | Yarn及HDFS | Hadoop |
Spark实现WordCount
测试环境下(local)开发
(1)首先创建maven项目
(2)增加scala插件
(3)在pom文件中添加依赖关系
<dependencies>
<!-- https://mvnrepository.com/artifact/org.apache.spark/spark-core -->
<dependency>
<groupId>org.apache.spark</groupId>
<artifactId>spark-core_2.12</artifactId>
<version>2.4.5</version>
</dependency>
</dependencies>
<build>
<plugins>
<!-- 打包插件, 否则 scala 类不会编译并打包进去 -->
<plugin>
<groupId>net.alchim31.maven</groupId>
<artifactId>scala-maven-plugin</artifactId>
<version>3.4.6</version>
<executions>
<execution>
<goals>
<goal>compile</goal>
<goal>testCompile</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
(4)创建scala目录并标记为源码
(5)创建scala-Object类
(6)编写代码(scala)
package com.chanzany.bigdata.spark.core
import org.apache.spark.rdd.RDD
import org.apache.spark.{SparkConf, SparkContext}
object Spark01_WordCount {
def main(args: Array[String]): Unit = {
//TODO Spark -WordCount
/**
* spark是一个计算框架
* 开发人员使用Spark框架的API实现计算功能
*/
//TODO 1. 准备Spark环境
//setMaster:设定Spark环境的位置
val sparkConf = new SparkConf().setMaster("local").setAppName("wordCount")
//TODO 2. 建立与Spark的连接
val context = new SparkContext(sparkConf)
//TODO 3. 实现业务操作
//TODO 3.1 读取指定目录下的数据文件(多个)
// 参数path可以指向单一文件也可以指向文件目录
// RDD:更适合并行计算的数据模型
val fileRDD: RDD[String] = context.textFile("input")
//TODO 3.2 将读取的内容进行扁平化操作(切分word)
val wordRDD: RDD[String] = fileRDD.flatMap(line => {
line.split(" ")
})
//TODO 3.3 将分词后的数据进行分组(word,Iterable)
val groupRDD: RDD[(String, Iterable[String])] = wordRDD.groupBy(word => word)
//TODO 3.4 将分组后的数据进行聚合:(word,count)
val mapRDD: RDD[(String, Int)] = groupRDD.map {
case (word, iter) => (word, iter.size)
}
//TODO 3.5 将聚合的结果打印到控制台(或者写入一个新的文件)
val wordCountTuples: Array[(String, Int)] = mapRDD.collect()
println(wordCountTuples.mkString(","))
//TODO 4. 释放连接
context.stop()
}
}
input目录下的文件内容如下:
控制台的输出如下所示:
如果嫌控制台输出的INFO日子太多,可以通过修改log4f.properties配置文件,设置打印级别为ERROR
#log4j.rootCategory=INFO, console log4j.rootCategory=ERROR, console
如果利用scala的函数编程思想以及采用Spark-scala的专有API(reduceByKey
),上面的代码可以改进为如下样子,同时因为要在集群中进行测试,所以注意设置sc.textFile(path=args(0))
def main(args: Array[String]): Unit = {
// 1. 创建 SparkConf对象, 并设置 App名字, 并设置为 local 模式
// 打包的时候需要把master的设置去掉,在提交的时候使用 --master来设置
val conf: SparkConf = new SparkConf().setAppName("WordCount").setMaster("local[2]")
// 2. 创建SparkContext对象
val sc = new SparkContext(conf)
// 3. 使用sc创建RDD并执行相应的transformation和action
val wordAndCount: Array[(String, Int)] = sc.textFile(ClassLoader.getSystemResource("words.txt").getPath)
.flatMap(_.split(" "))
.map((_, 1))
.reduceByKey(_ + _)
.collect()
wordAndCount.foreach(println)
// 4. 关闭连接
sc.stop()
}
打包项目到生产环境(Yarn)中运行
使用maven->Lifecycle–>clean–>package打包当前项目,然后可以在target目录中找到相应的jar包把该jar包丢到spark-yarn安装目录
使用如下命令运行该jar包的主程序
bin/spark-submit \
> --master yarn \
> --deploy-mode client \
> --class com.chanzany.bigdata.spark.core.Spark02_WordCount \
> ./spark-plugins-1.0-SNAPSHOT.jar \
> hdfs://hadoop102:9000/input
参考致谢
尚硅谷大数据:http://www.atguigu.com/bigdata_video.shtml#bigdata_b
spark2.1.1-document:https://spark.apache.org/docs/2.1.1/
杨磊:循序渐进学spark