Spark伪分布式集群环境搭建
伪分布式,在一台机器上模拟所有的集群服务
Spark Standalone集群
spark自带一种资源管理调度系统,类似于Hadoop YARN
准备工作
- CentOS7.2以上的虚拟机
- JDK8.0以上
- hadoop-2.9.2.tar.gz
- spark-2.4.4-bin-without-hadoop.tgz
虚拟机初始化配置
网络
# 1. 虚拟机双网卡配置,添加网卡硬件,网络连接设置为NAT模式
# 2. 修改网卡的配置文件,ens33网卡(内网通信,静态地址) ens37网卡(外围通信,动态地址)
[root@SparkOnStandalone ~]# vi /etc/sysconfig/network-scripts/ifcfg-ens33
BOOTPROTO=static
IPADDR=192.168.197.201
NETMASK=255.255.255.0
# 重启网络服务
systemctl restart network.service
关闭防火墙
systemctl stop firewalld.service
# 取消开机自启动
systemctl disable firewalld
设置主机名
[root@SparkOnStandalone ~]# vi /etc/hostname
SparkOnStandalone
配置主机名和IP映射
[root@SparkOnStandalone ~]# vi /etc/hosts
192.168.197.201 SparkOnStandalone
将window系统下的host映射也进行配置
C:\Windows\System32\drivers\etc
目录下的hosts文件进行修改
配置SSH免密登录
# 创建密钥
ssh-keygen -t rsa
# 直接回车
# 将密钥copy需要免密登录的主机上
ssh-copy-id hostname
# 验证免密登录
ssh hostname
# exit 退出
安装JDK
将rpm安装包上传到系统中,使用rpm 命令进行安装 ,默认安装在/usr目录下
rpm -ivh jdk-8u171-linux-x64.rpm
安装Hadoop HDFS
将Hadoop文件上传到Linux系统中,解压到/usr目录下
tar -zxf hadoop-2.9.2.tar.gz -C /usr
配置Hadoop 配置文件
vi /usr/hadoop-2.9.2/etc/hadoop/core-site.xml
<!--nn访问入口-->
<property>
<name>fs.defaultFS</name>
<value>hdfs://SparkOnStandalone:9000</value>
</property>
<!--hdfs工作基础目录-->
<property>
<name>hadoop.tmp.dir</name>
<value>/usr/hadoop-2.9.2/hadoop-${user.name}</value>
</property>
vi /usr/hadoop-2.9.2/etc/hadoop/hdfs-site.xml
<!--block副本因子-->
<property>
<name>dfs.replication</name>
<value>1</value>
</property>
<!--配置Sencondary namenode所在物理主机-->
<property>
<name>dfs.namenode.secondary.http-address</name>
<value>SparkOnStandalone:50090</value>
</property>
<!--设置datanode最大文件操作数-->
<property>
<name>dfs.datanode.max.xcievers</name>
<value>4096</value>
</property>
<!--设置datanode并行处理能力-->
<property>
<name>dfs.datanode.handler.count</name>
<value>6</value>
</property>
# 配置服务
vi /usr/hadoop-2.9.2/etc/hadoop/slaves
hostname
修改环境变量配置
修改的为用户环境配置
[root@SparkOnStandalone ~]# vi .bashrc
HADOOP_HOME=/usr/hadoop-2.9.2
JAVA_HOME=/usr/java/latest
PATH=$PATH:$JAVA_HOME/bin:$HADOOP_HOME/bin:$HADOOP_HOME/sbin
CLASSPATH=.
export HADOOP_HOME
export JAVA_HOME
export PATH
export CLASSPATH
# 刷新配置信息
[root@SparkOnStandalone ~]# source .bashrc
初始化NameNode
[root@SparkOnStandalone ~] hdfs namenode -format
启动HDFS
启动完成后通过访问web 或者jps检车是否正常启动
[root@SparkOnStandalone ~]# start-dfs.sh
Starting namenodes on [SparkOnStandalone]
SparkOnStandalone: starting namenode, logging to /usr/hadoop-2.9.2/logs/hadoop-root-namenode-SparkOnStandalone.out
SparkOnStandalone: starting datanode, logging to /usr/hadoop-2.9.2/logs/hadoop-root-datanode-SparkOnStandalone.out
Starting secondary namenodes [SparkOnStandalone]
SparkOnStandalone: starting secondarynamenode, logging to /usr/hadoop-2.9.2/logs/hadoop-root-secondarynamenode-SparkOnStandalone.out
[root@SparkOnStandalone ~]# jps
11266 NameNode
11847 Jps
11416 DataNode
11611 SecondaryNameNode
或者访问: http://192.168.197.201:50070
安装Spark
# 解压文件到`/usr`目录下
tar -zxf spark-2.4.4-bin-without-hadoop.tgz -C /usr
# 文件名过长,操作不方便,修改文件名
mv spark-2.4.4-bin-without-hadoop/ spark-2.4.4
配置Spark
conf 目录下提供的有配置模板,对模板复制一份后进行修改配置
[root@SparkOnStandalone conf]# cp slaves.template slaves
[root@SparkOnStandalone conf]# cp spark-env.sh.template spark-env.sh
[root@SparkOnStandalone conf]# cp spark-defaults.conf.template spark-defaults.conf
[root@SparkOnStandalone conf]# vi spark-env.sh
SPARK_WORKER_INSTANCES=1
SPARK_MASTER_HOST=SparkOnStandalone
SPARK_MASTER_PORT=7077
SPARK_WORKER_CORES=4
SPARK_WORKER_MEMORY=2g
LD_LIBRARY_PATH=/usr/hadoop-2.9.2/lib/native
SPARK_DIST_CLASSPATH=$(hadoop classpath)
export SPARK_MASTER_HOST
export SPARK_MASTER_PORT
export SPARK_WORKER_CORES
export SPARK_WORKER_MEMORY
export LD_LIBRARY_PATH
export SPARK_DIST_CLASSPATH
export SPARK_WORKER_INSTANCES
[root@SparkOnStandalone conf]# vi slaves
SparkOnStandalone `hostname`
启动SparkStandalone 伪分布式模式集群
进入
spark/sbin
目录下,执行./start-all.sh
[root@SparkOnStandalone spark-2.4.4]# cd sbin/
[root@SparkOnStandalone sbin]# ls
slaves.sh start-history-server.sh start-slave.sh stop-master.sh stop-slaves.sh
spark-config.sh start-master.sh start-slaves.sh stop-mesos-dispatcher.sh stop-thriftserver.sh
spark-daemon.sh start-mesos-dispatcher.sh start-thriftserver.sh stop-mesos-shuffle-service.sh
spark-daemons.sh start-mesos-shuffle-service.sh stop-all.sh stop-shuffle-service.sh
start-all.sh start-shuffle-service.sh stop-history-server.sh stop-slave.sh
[root@SparkOnStandalone sbin]# ./start-all.sh
starting org.apache.spark.deploy.master.Master, logging to /usr/spark-2.4.4/logs/spark-root-org.apache.spark.deploy.master.Master-1-SparkOnStandalone.out
SparkOnStandalone: starting org.apache.spark.deploy.worker.Worker, logging to /usr/spark-2.4.4/logs/spark-root-org.apache.spark.deploy.worker.Worker-1-SparkOnStandalone.out
验证服务
# 方法1
[root@SparkOnStandalone sbin]# jps
17216 Master
11266 NameNode
17347 Worker
11416 DataNode
11611 SecondaryNameNode
17612 Jps
# 方法2
http://192.168.197.201:8080/
Spark应用开发
第一种方式:Shell终端
编写一些简单的Spark应用,主要用于测试;
[root@SparkOnStandalone spark-2.4.4]# ./bin/spark-shell --help
# spark应用运行环境地址
--master MASTER_URL spark://host:port, mesos://host:port, yarn,
k8s://https://host:port, or local (Default: local[*]).
# 当前任务所占用计算服务的核心数量
--total-executor-cores NUM Total cores for all executors.
# 每一个计算服务所占用的核心数量
--executor-cores NUM Number of cores per executor. (Default: 1 in YARN mode,
or all available cores on the worker in standalone mode)
具体的使用方法
[root@SparkOnStandalone spark-2.4.4]# ./bin/spark-shell --master spark://SparkOnStandalone:7077 --total-executor-cores 2
Setting default log level to "WARN".
To adjust logging level use sc.setLogLevel(newLevel). For SparkR, use setLogLevel(newLevel).
Spark context Web UI available at http://SparkOnStandalone:4040
Spark context available as 'sc' (master = spark://SparkOnStandalone:7077, app id = app-20200113145247-0000).
Spark session available as 'spark'.
Welcome to
____ __
/ __/__ ___ _____/ /__
_\ \/ _ \/ _ `/ __/ '_/
/___/ .__/\_,_/_/ /_/\_\ version 2.4.4
/_/
Using Scala version 2.11.12 (Java HotSpot(TM) 64-Bit Server VM, Java 1.8.0_171)
Type in expressions to have them evaluated.
Type :help for more information.
scala>
- Spark context available as ‘sc’:应用上下文对象,包装了spark应用运行所需的环境信息; 别名
SparkContext = sc
- Spark session available as ‘spark’.: Spark SQL中关键对象,别名
SparkSession = spark
编写Spark版本WordCount
# 1. 准备数据源,来源于HDFS
[root@SparkOnStandalone ~]# vi data.txt
[root@SparkOnStandalone ~]# hdfs dfs -put data.txt /
[root@SparkOnStandalone ~]# hdfs dfs -ls /
Found 1 items
-rw-r--r-- 1 root supergroup 58 2020-01-13 15:01 /data.txt
# 2. 开发Spark应用
# rdd 类似于Scala的集合
val rdd = sc.textFile("hdfs://SparkOnStandalone:9000/data.txt")
rdd
.flatMap(_.split("\\s"))
.map((_,1))
.groupBy(_._1)
.map(t2 => (t2._1,t2._2.size))
.sortBy(_._1,false)
.saveAsTextFile("hdfs://SparkOnStandalone:9000/result2")
# 3. 查看运行结果
[root@SparkOnStandalone ~]# hdfs dfs -cat /result/*
(Very,1)
(To,1)
(Spark,2)
(Simple,1)
(Hello,2)
(Hadoop,2)
(Good,1)
第二种方式:IDE
引入依赖
<!-- https://mvnrepository.com/artifact/org.apache.spark/spark-core -->
<dependency>
<groupId>org.apache.spark</groupId>
<artifactId>spark-core_2.11</artifactId>
<version>2.4.4</version>
</dependency>
package demo
import org.apache.spark.rdd.RDD
import org.apache.spark.{SparkConf, SparkContext}
object FirstWordCount{
def main(args: Array[String]): Unit = {
// 初始化SC
val conf = new SparkConf()
conf.setAppName("wordcount")
conf.setMaster("spark://SparkOnStandalone:7077")
val sc = new SparkContext(conf)
println("运行的核心数量: " + sc.defaultParallelism)
// 通过SC 构建数据源 rdd类似于scala集合
val rdd: RDD[String] = sc.textFile("hdfs://SparkOnStandalone:9000/data.txt")
// 数据处理
rdd
.flatMap(_.split("\\s"))
.map((str: String) => (str,1L))
.groupByKey()
.map((t2:(String,Iterable[Long])) => (t2._1,t2._2.size))
.sortBy(_._2,true)
.saveAsTextFile("hdfs://SparkOnStandalone:9000/result4")
// 关闭程序
sc.stop()
}
}
远程提交
- 使用Maven 将项目打包为jar包
- 检查打包的jar中是否包含有class文件,如果没有,选择Build-> Build Project重新编译下项目再次打包
- 将jar包上传至Linux服务器中
- 提交运行Spark应用 (total-executor-cores 执行任务线程数)
[root@SparkOnStandalone spark-2.4.4]# ./bin/spark-submit
[root@SparkOnStandalone spark-2.4.4]# ./bin/spark-submit --master spark://SparkOnStandalone:7077 --class demo.FirstWordCount --total-executor-cores 2 /root/spark-day1-1.0-SNAPSHOT.jar
本地模拟运行
- 本地hostname中配置IP 映射
- 修改Spark应用代码
val conf = new SparkConf()
conf.setAppName("wordcount")
conf.setMaster("local[3]") // local 本地 [*] 核心数量=CPU核心数量
val sc = new SparkContext(conf)
- 由于是本地运行,本地用户提交计算结果到Hadoop中权限不足
org.apache.hadoop.security.AccessControlException
添加虚拟机参数:-DHADOOP_USER_NAME=root
Spark 工作原理
主要角色
- 集群管理器(ClusterManager): 在Standalone集群中是Master,负责整个分布式集群的资源管理和调度;
- 计算节点(ComputerNode):在Standalone集群中是Worker,负责提供节点计算资源(CPU、网络、IO、磁盘等)和Task的真正处理;
- 驱动程序(Driver JVM进程):负责初始化SparkContext,将Spark Job拆分为多个Stage,每一个Stage包含了一个支持分布式并且计算TaskSet(Task的集合),最终将每一个Stage任务集提交到计算节点运行;
- 核心(Cores): 能够同时运行的最大线程数量,超过Cores数量外的线程会等待执行;
- 并行度(parallel): 任务的并行度和TaskSet中的Task数量是相同的,Task最终会由计算容器(Executor)中的线程进行处理计算;