Spark:01基础环境

image.png

一、Spark 框架概述

  • 官方对Spark的一个介绍
At a high level, every Spark application consists of a driver program 
#每个Spark程序都会包含一个驱动程序:Driver

that runs the user’s main function 
#这个driver运行在用户的main方法中

and executes various parallel operations on a cluster. 
#并且在集群中执行各种并行化操作 
 
The main abstraction Spark provides is a resilient distributed dataset (RDD), 
#Spark中提供了一个主要的抽象:RDD【弹性分布式数据集】【SparkCore中的核心数据结构】

which is a collection of elements partitioned across the nodes of the cluster 
# 被分区存储在各个节点中的一个元素的集合【类似于MapReduce中的分片的存在,所有分片构建一个RDD】

that can be operated on in parallel.
#可以被并行化的操作

RDDs are created by starting with a file in the Hadoop file system (or any other Hadoop-supported file system), 
#RDD可以从一个Hadoop文件系统中被创建

or an existing Scala collection in the driver program, and transforming it. 
#或者从一个Scala的集合中进行创建,由driver来实现,并且对RDD进行转换

Users may also ask Spark to persist an RDD in memory,
#用户可以将RDD中的数据持久化【缓存】在内存中,

allowing it to be reused efficiently across parallel operations. 
#方便多次使用

Finally, RDDs automatically recover from node failures.
#最终,RDD会自动的从失败中恢复

理解:RDD类似于scala中的集合,但是RDD是分布式的,RDD集合中的数据分区存储在不同的机器上

MapReduceSpark
数据存储结构磁盘HDFS文件系统使用内存构建弹性分布式数据集RDD对数据进行运算和缓存
编程范式Map+ReduceDAG(有向无环图):Transformation+action
中间结果存储中间结果落体磁盘,IO及序列化反序列化代价比较大中间结果储存在内存中,速度比磁盘多几个数量级
运行方式Task以进程方式维护,任务启动慢Task以线程方式维护,任务启动快

image.png
在这里插入图片描述

  • 常用的数据源

    • SparkCore:HDFS、HBASE
    • SparkSQL:Hive、结构化数据【MySQL、Json、文件、Parquet】
    • SparkStreaming:Kafka、HBASE、Redis
  • 运行在各种分布式资源平台中

    • http://spark.apache.org/docs/2.4.5/
    • Standalone
      • Spark自带的集群资源管理平台
    • Messos
      • 类似于YARN,国内应用的不多
    • YARN
      • 将Spark的程序放在YARN运行,由YARN做资源管理
    • Kubernetes
      • 新一代的分布式资源容器,类似于Docker

二、Spark环境部署测试

1、版本与编译

  • 版本

    • 1.x:早期的大数据平台所使用的版本,功能性能都有一些缺陷
    • 2.x:目前企业中应用最多的版本
      • 2.4.5
    • 3.x:最新的版本,增加了很多新的特性,用来提高性能
      • 目前暂时没有对应的应用环境
  • 发行厂商

    • Apache:http://archive.apache.org/dist/spark/spark-2.4.5/
    • CDH
      • 为什么不用Apache,而选用Cloudera公司的产品
        • 基于稳定性的考虑
      • Cloudera所提供的Spark版本是有缺陷的
        • Spark的编译好的包中是没有SparkSQL的
        • Cloudera公司自己有Impala
  • 基于以上的问题,需要基于Cloudera公司的依赖,自己编译Spark

    spark-2.4.5-bin-cdh5.16.2-2.11.tgz

2、部署模式

  • 本地模式
    • 一般用于测试开发,没有分布式的主从架构
    • 将程序直接在本地启动一个JVM来运行
  • 集群模式
    • 一般用于生产环境,有分布式主从架构
    • 将程序提交给分布式资源平台去运行
    • 第一种:Standalone
      • Spark自带的集群资源管理
    • 第二种:YARN
      • 将Spark程序提交给YARN运行

3、架构组成

  • 主从架构模式
    • 主节点:管理集群
    • 从节点:负责实现计算
  • Standalone
    • 主:Master
    • 从:Worker
  • YARN
    • 主:ResourceManger
    • 从:NodeManager

Master单点故障:启动多个Master

如何保证同一时刻只有一个Master,并且能自动切换:Zookeeper

任何一个分布式主从架构要不依赖于Zookeeper解决单点故障问题,要不自身实现了类似于Zookeeper的功能
如:Kafka依赖Zookeeper;ES实现了类似于Zookeeper的主动选举、自动切换功能

4、本地模式(Local)

  • 参考附录一导入虚拟机

  • 参考附录二安装本地环境

    • 第一台机器恢复到快照3
    • 启动第一台机器即可
  • 启动HDFS

    hadoop-daemon.sh start namenode
    hadoop-daemon.sh start datanode
    
  • 测试

    • 启动Spark-shell

      cd /export/server/spark
      bin/spark-shell --master local[2]
      
      • spark-shell是Spark提供的一个交互式的Spark程序,可以通过命令行直接写Spark代码
      • –master:指定程序运行在哪个模式上
      • local:表示本地模式
        • [2]:运行这个程序,给定几核CPU
    • 创建测试文件

      hdfs dfs -mkdir /datas
      vim wordcount.data
      
      hadoop spark hbase
      hive hive hive hive
      hadoop spark spark
      
      hdfs dfs -put wordcount.data /datas
      
    • 观察Spark-shell日志

      Setting default log level to "WARN".
      #默认日志级别为WARN级别
      To adjust logging level use sc.setLogLevel(newLevel). For SparkR, use setLogLevel(newLevel).
      #如果你要修改日志级别,你要sc.setLogLevel(“INFO”)
      Spark context Web UI available at http://node1.itcast.cn:4040
      #每一个Spark程序都会自动开放一个Web监控界面,端口从4040开始,第二个程序的端口4041,依次类推
      Spark context available as 'sc' (master = local[2], app id = local-1608102687971).
      #创建了一个对象:sc:SparkContext
      Spark session available as 'spark'.
      #创建了一个对象:spark:SparkSession
      
      • SparkContext对象就是上午提到的driver program
      • SparkSession对象是新一代的driver program:里面包含了一个SparkContext对象
        • 用于替代老的SparkContext
    • 测试WordCount

      • Input:读HDFS中/datas/wordcount.data

        //调用sparkContext的方法读HDFS文件,存入RDD对象中
        scala> val inputRdd = sc.textFile("/datas/wordcount.data")
        inputRdd: org.apache.spark.rdd.RDD[String] = /datas/wordcount.data MapPartitionsRDD[1] at textFile at <console>:24
        //查看RDD的第一行数据
        scala> inputRdd.first
        res0: String = hadoop spark hbase
        //统计RDD的行数
        scala> inputRdd.count
        res1: Long = 3
        
      • Transform:实现词频统计

        • flatMap:RDD[String]

          scala> inputRdd.flatMap(line => line.trim.split("\\s+"))
          res2: org.apache.spark.rdd.RDD[String] = MapPartitionsRDD[2] at flatMap at <console>:26
          
          scala> inputRdd.flatMap(line => line.trim.split("\\s+")).foreach(println)
          hadoop
          spark
          hbase
          hive
          hive
          hive
          hive
          hadoop
          spark
          spark
          
        • map:RDD[(String,Int)]

          scala> inputRdd.flatMap(line => line.trim.split("\\s+")).map(word => (word,1)).foreach(println)
          (hadoop,1)
          (spark,1)
          (hbase,1)
          (hive,1)
          (hive,1)
          (hive,1)
          (hive,1)
          (hadoop,1)
          (spark,1)
          (spark,1)
          
        • reduceByKey:功能 = groupByKey + reduce:RDD[(String, Int)]

          scala> val rsRDD = inputRdd.flatMap(line => line.trim.split("\\s+")).map(word => (word,1)).reduceByKey((tmp,item)=> tmp+item)
          rsRDD: org.apache.spark.rdd.RDD[(String, Int)] = ShuffledRDD[8] at reduceByKey at <console>:25
          
          scala> rsRDD.foreach(println)
          (hive,4)
          (spark,3)
          (hadoop,2)
          (hbase,1)
          
      • Output

        rsRDD.saveAsTextFile("/datas/output/output1")
        

        在这里插入图片描述
        在这里插入图片描述

    • 测试运行Jar包

      • spark-submit:用于运行Spark的jar包的

      • Spark

        spark-submit 
        [选项]
        --class 指定运行哪个类
        xxxx.jar  
        args #几个task=几核CPU运行
        
        SPARK_HOME=/export/server/spark 
        ${SPARK_HOME}/bin/spark-submit \
        --master local[2] \
        --class org.apache.spark.examples.SparkPi \
        ${SPARK_HOME}/examples/jars/spark-examples_2.11-2.4.5.jar \
        10
        

      注:第二个spark程序,4041访问

5、集群模式(Standalone)

  • 参考附录三安装集群环境

    • 先将第一台机器恢复到快照4
      在这里插入图片描述
  • 启动Spark Standalone集群

    • 启动HDFS:第一台机器执行

      start-dfs.sh
      #创建一个目录,用于存储Spark程序的运行日志
      hdfs dfs -mkdir -p /spark/eventLogs/
      
    • 启动Master:第一台机器

      /export/server/spark/sbin/start-master.sh
      

      在这里插入图片描述

    • 启动Worker:第一台机器

      /export/server/spark/sbin/start-slaves.sh
      

      在这里插入图片描述

    • 查看WebUI

      node1:8080
      

      在这里插入图片描述

    • 启动HistoryServer

      /export/server/spark/sbin/start-history-server.sh
      

      在这里插入图片描述

    • 访问WebUI

      node1:18080
      

      在这里插入图片描述

  • 测试

    SPARK_HOME=/export/server/spark
    ${SPARK_HOME}/bin/spark-submit \
    --master spark://node1:7077 \
    --class org.apache.spark.examples.SparkPi \
    ${SPARK_HOME}/examples/jars/spark-examples_2.11-2.4.5.jar \
    10
    

    在这里插入图片描述

6、HA集群

  • 关闭所有Spark进程

    /export/server/spark/sbin/stop-slaves.sh 
    /export/server/spark/sbin/stop-master.sh 
    /export/server/spark/sbin/stop-history-server.sh
    
  • 修改配置文件

    cd /export/server/spark/conf/
    vim spark-env.sh
    
    #注释60行
    #SPARK_MASTER_HOST=node1
    #添加68行
    SPARK_DAEMON_JAVA_OPTS="-Dspark.deploy.recoveryMode=ZOOKEEPER -Dspark.deploy.zookeeper.url=node1:2181,node2:2181,node3:2181 -Dspark.deploy.zookeeper.dir=/spark-ha"
    
  • 分发

    cd /export/server/spark/conf
    scp -r spark-env.sh node2:$PWD
    scp -r spark-env.sh node3:$PWD
    
  • 启动ZK

    zookeeper-daemons.sh start
    zookeeper-daemons.sh status
    
  • 启动Master

    • 第一台

      /export/server/spark/sbin/start-master.sh
      
    • 第二台

      /export/server/spark/sbin/start-master.sh
      
  • 启动Worker

    /export/server/spark/sbin/start-slaves.sh 
    
  • 测试

    SPARK_HOME=/export/server/spark
    ${SPARK_HOME}/bin/spark-submit \
    --master spark://node1:7077,node2:7077 \ #把可用的Master都写上
    --class org.apache.spark.examples.SparkPi \
    ${SPARK_HOME}/examples/jars/spark-examples_2.11-2.4.5.jar \
    100
    

三、Spark应用组成(重点总结放着这了)

1、应用组件

在这里插入图片描述

Spark Application运行到集群上时,由两部分组成:一个Driver Program 和 多个Executor

  • 第一、Driver Program
    • 运行程序的MAIN函数,创建SparkContext对象
    • SparkContext 会和Cluster Manager交互,包括向它申请计算资源等;
    • SparkContext 允许driver 通过资源管理器访问集群
    • 资源管理器可以是Yarn,或则spark集群管理器。
  • 第二、Executors
    • 相当于一个线程池,每个线程运行一个Task任务,一个Task运行需要1 Core CPU,可以认为Executor中线程数就等于CPU Core核数;
    • Executor是在Worker Node上的一个进程,负责运行任务,及将数据存在内存或者磁盘上;
    • 一个Spark Application可以有多个,可以设置个数和资源信息;

在这里插入图片描述

用户程序从最开始的提交到最终的计算执行,需要经历以下几个阶段:

1)、用户程序创建 SparkContext 时,新创建的 SparkContext 实例会连接到 ClusterManager。 Cluster Manager 会根据用户提交时设置的 CPU 和内存等信息为本次提交分配计算资源,启动 Executor。

2)、Driver进程开始解析代码,构建DAG,Driver将程序划分为不同的执行阶段Stage,每个执行阶段Stage由一组完全相同Task组成,这些Task分别作用于待处理数据的不同分区。在阶段划分完成和Task创建后, Driver会向Executor发送 Task;

3)、Executor在接收到Task后,会下载Task的运行时依赖,在准备好Task的执行环境后,会开始执行Task,并且将Task的运行状态汇报给Driver;

4)、Driver会根据收到的Task的运行状态来处理不同的状态更新。 Task分为两种:一种是Shuffle Map Task,它实现数据的重新洗牌,洗牌的结果保存到Executor 所在节点的文件系统中;另外一种是Result Task,它负责生成结果数据;

5)、Driver 会不断地调用Task,将Task发送到Executor执行,Driver监控所有Task的运行,在所有的Task 都正确执行或者超过执行次数的限制仍然没有执行成功时停止。

在这里插入图片描述

  • 一个分区用一个Task,为什么这里两个分区需要四个Task?

    • shuffle将所有数据写入磁盘,stage0中的task将数据输出,task结束
  • 数据什么时候产生?

    • Task在Executor中运行时产生
  • 一个Rdd分区数越高,并行度就越高么?

    • no,当executor核数不够,多个task无法实现并行
  • Stage为什么是全局编号的(Application中不同job,stage全局编号)?

    • 每一个stage中有单独的task程序,
    • 每次按照stage来运行task程序,
    • 若不同job的stage编号相同,无法区分task是否运行过
  • 数据的构建有些在Executor,有些在Driver,有什么区别?

    • Driver:解析和运行所有代码:逻辑计划

      • 一个:内存在一台机器上,内存比较小

      • 普通类型的实例,触发函数的返回值类型:String、Array等

      • top只能用于小数据,所以top可以不走shuffle就能实现全局排序

        • top将RDD的分布式数据全部放到了driver中做排序
          在这里插入图片描述
    • Executor:Task:物理计划

      • 多个:分布式内存
      • RDD的数据:分布式存储和分布式计算
    • task运行完把数据存到所在的executor,当代码用到数据时,把数据发给driver(代码的执行在driver)

      println(inputRdd.first())
      //inputRdd.first()的数据在executor上
      //当需要打印时,将数据发给driver
      
    • 解析和运行所有代码在driver,但数据的构建有些在driver有些在executor

      • RDD的数据在executor上构建
      • 触发类型的返回值放在driver

2、Web监控

在这里插入图片描述

  • Application:Spark程序(如这里的Spark shell程序)
  • job:Spark 中的 action 操作(如 save、collect、foreach),会生成一个 Job。
    • 以前MapReduce:一个Application就是一个Job
    • 现在Spark:一个Application可以多个job
  • Stage:每个Job会划分为多个阶段,每个阶段会用多个Task来实现这个阶段的处理过程:执行计划
    • 为什么需要Stage?
      • 程序是基于lazy模式构建RDD,最终触发job的运行,通过DAG一步步执行
    • stage的划分规则?
      • 是否产生shuffle过程
    • stage怎么变成Task呢?
      • Stage中每个RDD的每个分区需要使用一个Task来运行处理
  • Task:线程
    • 线程运行在进程中
    • MapReduce以进程方式来运行Task:每个Task都需要重新申请资源
    • Spark中的运行进程Executor是不会直接运行一个Task就释放的,等待所有Task的运行完成才会释放
  • RDD的构建只构建了血脉关系,并没有真正的放数据
  • 什么时候数据才会在RDD的分区里面呢?
    • 只有在RDD的数据被使用的时候,才会根据血脉关系进行回溯

四、开发环境搭建测试

1、创建Maven工程引入依赖

2、WordCount开发

package bigdata.itcast.cn.spark.scala.wordcount

import org.apache.spark.rdd.RDD
import org.apache.spark.{SparkConf, SparkContext}

/**
  * @ClassName SparkCoreWordCount
  * @Description TODO 自己开发代码来实现Wordcount
  */
object SparkCoreWordCount {
  def main(args: Array[String]): Unit = {
    /**
      * step1:先构建SparkContext:初始化资源对象
      */

    //构建一个SparkConf:用于管理当前程序的所有配置
    val conf = new SparkConf()
      //给当前程序设置一个名字
      .setAppName(this.getClass.getSimpleName.stripSuffix("$"))
      //设置当前程序运行的模式
      .setMaster("local[2]")
    //构建一个SparkContext对象
    val sc = new SparkContext(conf)
    //调整日志级别
    sc.setLogLevel("WARN")

    /**
      * step2:处理数据
      */
    //todo:1-读取数据
    val inputRdd: RDD[String] = sc.textFile("/datas/wordcount.data")
    //todo:2-处理数据
    val rsRdd = inputRdd
        .filter(line => null != line && line.trim.length >0)
        .flatMap(line => line.trim.split("\\s+"))
        .map(word => word -> 1)
        .reduceByKey((tmp,item) => tmp+item)
    
    //todo:3-保存结果
    rsRdd.foreach(println)

    /**
      * step3:释放资源
      */
    Thread.sleep(1000000L)
    sc.stop()
  }
}

本地模式下,单机没有Executors,只有driver;

有Executors才能进行分布式的计算运行

3、基础模板开发

package bigdata.itcast.cn.spark.scala.mode

import org.apache.spark.rdd.RDD
import org.apache.spark.{SparkConf, SparkContext}

/**
  * @ClassName SparkCoreMode
  * @Description TODO SparkCore的基础模板
  */
object SparkCoreMode {
  def main(args: Array[String]): Unit = {
    /**
      * step1:先构建SparkContext:初始化资源对象
      */

    //构建一个SparkConf:用于管理当前程序的所有配置
    val conf = new SparkConf()
      //给当前程序设置一个名字
      .setAppName(this.getClass.getSimpleName.stripSuffix("$"))
      //设置当前程序运行的模式
      .setMaster("local[2]")
    //构建一个SparkContext对象
    val sc = new SparkContext(conf)
    //调整日志级别
    sc.setLogLevel("WARN")

    /**
      * step2:处理数据
      */
    //todo:1-读取数据
    //todo:2-处理数据
    //todo:3-保存结果

    /**
      * step3:释放资源
      */
    Thread.sleep(1000000L)
    sc.stop()
  }
}

4、TopKey开发

案例:基于word count选出前三个个数最多的单词

package bigdata.itcast.cn.spark.scala.topkey

import org.apache.spark.rdd.RDD
import org.apache.spark.{SparkConf, SparkContext}

/**
  * @ClassName SparkCoreWCTopKey
  * @Description TODO Spark Core实现词频统计,并且排序
  */
object SparkCoreWCTopKey {
  def main(args: Array[String]): Unit = {
    /**
      * step1:初始化一个SparkContext
      */
    //构建配置对象
    val conf = new SparkConf()
      .setAppName(this.getClass.getSimpleName.stripSuffix("$"))
      .setMaster("local[2]")
    //构建SparkContext的实例,如果存在,直接获取,如果不存在,就构建
    val sc = SparkContext.getOrCreate(conf)
    //调整日志级别
    sc.setLogLevel("WARN")


    /**
      * step2:实现数据的处理过程:读取、转换、保存
      */
    //todo:1-读取
    val inputRdd: RDD[String] = sc.textFile("datas/wordcount/wordcount.data")
    println(s"first line = ${inputRdd.first()}")
    println(s"count = ${inputRdd.count()}")
    //todo:2-转换
    val rsRdd = inputRdd
        //对非法数据的过滤:def filter(f: T => Boolean)
        .filter(line => null != line && line.trim.length > 0)
        //提取所有单词,放到一个集合中
        .flatMap(line => line.trim.split("\\s+"))
        //转换为二元组
        .map(word => (word,1))
        //按照单词分组聚合
        .reduceByKey((tmp,item) => tmp+item)
        
        //方式一:sortByKey:只能对二元组类型进行排序,会调用collect或save方法,运用RDD中的数据,触发程序运行
        //只能对Key排序,所以交换位置
        .map(tuple => tuple.swap)
        .sortByKey(ascending = false)
        .take(3)      
        
        //方式二:sortBy
        .sortBy(tuple => -tuple._2)
        .take(3)
        
        //方式三:top:直接对数据进行排序,根据key自动降序排序,取前N个值
        .top(3)(Ordering.by(tuple => tuple._2)) //自定义比较器
        .foreach(println)
    //todo:3-保存

    /**
      * step3:释放资源
      */
    Thread.sleep(1000000L)
    sc.stop()
  }
}

三种排序

  • sortByKey
    在这里插入图片描述

  • sortBy

    def sortBy[K](
          f: (T) => K,//指定按照谁进行排序
          ascending: Boolean = true,
          numPartitions: Int = this.partitions.length)
    

    在这里插入图片描述

  • top:小数据量的排序选取中是比较合适的,返回值是数组,加载到driver内存

    def top(num: Int)(implicit ord: Ordering[T]): Array[T]
    

    在这里插入图片描述

五、Standalone集群运行

1、spark-submit

  • 先将程序打成jar包

    package bigdata.itcast.cn.spark.scala.wordcount
    
    import org.apache.spark.rdd.RDD
    import org.apache.spark.{SparkConf, SparkContext}
    
    /**
      * @ClassName SparkCoreWordCount
      * @Description TODO 自己开发代码来实现Wordcount
      */
    object SparkCoreWordCount {
      def main(args: Array[String]): Unit = {
        /**
          * step1:先构建SparkContext:初始化资源对象
          */
    
        //构建一个SparkConf:用于管理当前程序的所有配置
        val conf = new SparkConf()
          //给当前程序设置一个名字
          .setAppName(this.getClass.getSimpleName.stripSuffix("$"))
          //设置当前程序运行的模式
    //      .setMaster("local[2]")
        //构建一个SparkContext对象
        val sc = new SparkContext(conf)
        //调整日志级别
        sc.setLogLevel("WARN")
    
        /**
          * step2:处理数据
          */
        //todo:1-读取数据
        //使用args(0)作为输入路径
        val inputRdd: RDD[String] = sc.textFile(args(0))
        //todo:2-处理数据
        val rsRdd = inputRdd
            .filter(line => null != line && line.trim.length >0)
            .flatMap(line => line.trim.split("\\s+"))
            .map(word => word -> 1)
            .reduceByKey((tmp,item) => tmp+item)
    
        //todo:3-保存结果
        rsRdd.foreach(println)
        rsRdd.saveAsTextFile(args(1)+"-"+System.currentTimeMillis())
    
        /**
          * step3:释放资源
          */
    //    Thread.sleep(1000000L)
        sc.stop()
      }
    }
    

    在这里插入图片描述

  • 上传到Linux上,并将jar包放到HDFS:方便在任何一台机器直接运行

    hdfs dfs -mkdir /spark/apps
    hdfs dfs -put spark-chapter01_2.11-1.0.0.jar.jar /spark/apps/
    

在这里插入图片描述

  • 运行:spark-submit

    • 用法

      [root@node1 spark]# bin/spark-submit -h
      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:
        --master MASTER_URL         spark://host:port, mesos://host:port, yarn,
                                    k8s://https://host:port, or local (Default: local[*]).
        --deploy-mode DEPLOY_MODE   Whether to launch the driver program locally ("client") or
                                    on one of the worker machines inside the cluster ("cluster")
                                    (Default: client).
        --class CLASS_NAME          Your application's main class (for Java / Scala apps).
        --name NAME                 A name of your application.
        --jars JARS                 Comma-separated list of jars to include on the driver
                                    and executor classpaths.
        --packages                  Comma-separated list of maven coordinates of jars to include
                                    on the driver and executor classpaths. Will search the local
                                    maven repo, then maven central and any additional remote
                                    repositories given by --repositories. The format for the
                                    coordinates should be groupId:artifactId:version.
        --exclude-packages          Comma-separated list of groupId:artifactId, to exclude while
                                    resolving the dependencies provided in --packages to avoid
                                    dependency conflicts.
        --repositories              Comma-separated list of additional remote repositories to
                                    search for the maven coordinates given with --packages.
        --py-files PY_FILES         Comma-separated list of .zip, .egg, or .py files to place
                                    on the PYTHONPATH for Python apps.
        --files FILES               Comma-separated list of files to be placed in the working
                                    directory of each executor. File paths of these files
                                    in executors can be accessed via SparkFiles.get(fileName).
      
        --conf PROP=VALUE           Arbitrary Spark configuration property.
        --properties-file FILE      Path to a file from which to load extra properties. If not
                                    specified, this will look for conf/spark-defaults.conf.
      
        --driver-memory MEM         Memory for driver (e.g. 1000M, 2G) (Default: 1024M).
        --driver-java-options       Extra Java options to pass to the driver.
        --driver-library-path       Extra library path entries to pass to the driver.
        --driver-class-path         Extra class path entries to pass to the driver. Note that
                                    jars added with --jars are automatically included in the
                                    classpath.
      
        --executor-memory MEM       Memory per executor (e.g. 1000M, 2G) (Default: 1G).
      
        --proxy-user NAME           User to impersonate when submitting the application.
                                    This argument does not work with --principal / --keytab.
      
        --help, -h                  Show this help message and exit.
        --verbose, -v               Print additional debug output.
        --version,                  Print the version of current Spark.
      
       Cluster deploy mode only:
        --driver-cores NUM          Number of cores used by the driver, only in cluster mode
                                    (Default: 1).
      
       Spark standalone or Mesos with cluster deploy mode only:
        --supervise                 If given, restarts the driver on failure.
        --kill SUBMISSION_ID        If given, kills the driver specified.
        --status SUBMISSION_ID      If given, requests the status of the driver specified.
      
       Spark standalone and Mesos only:
        --total-executor-cores NUM  Total cores for all executors.
      
       Spark standalone and YARN only:
        --executor-cores NUM        Number of cores per executor. (Default: 1 in YARN mode,
                                    or all available cores on the worker in standalone mode)
      
       YARN-only:
        --queue QUEUE_NAME          The YARN queue to submit to (Default: "default").
        --num-executors NUM         Number of executors to launch (Default: 2).
                                    If dynamic allocation is enabled, the initial number of
                                    executors will be at least NUM.
        --archives ARCHIVES         Comma separated list of archives to be extracted into the
                                    working directory of each executor.
        --principal PRINCIPAL       Principal to be used to login to KDC, while running on
                                    secure HDFS.
        --keytab KEYTAB             The full path to the file that contains the keytab for the
                                    principal specified above. This keytab will be copied to
                                    the node running the Application Master via the Secure
                                    Distributed Cache, for renewing the login tickets and the
                                    delegation tokens periodically.
      
    • 常用的选项

      • 提交的选项

        --master:用于指定提交的模式,local、Standalone、yarn、messos、k8s
        	local[2]
        	spark://host:7077
        	yarn
        

        在这里插入图片描述

        --deploy-mode:指定deploy模式,client、cluster两种模式
        --class:指定运行jar包中的哪个类
        --jars:用于指定添加需要的一些额外的包
        --conf:临时的修改Spark的属性配置
        
      • Driver进程资源的配置

        --driver-memory MEM:driver进程的内存资源
        
      • Executor进程的资源配置

        • 通用属性

          --executor-memory:每个Executor能够使用的内存(Default: 1G).
          
        • Spark standalone and Mesos

          --total-executor-cores:所有Executor总共使用的CPU核数
          
        • Spark standalone and YARN

          --executor-cores:指定每个Executor能用几核CPU
          
        • YARN-only

          --num-executors:指定Executor的个数
          
        • 问题:Standalone集群中,如何指定Executor的个数

          • 个数 = --total-executor-cores / --executor-cores

2、本地模式提交

SPARK_HOME=/export/server/spark
$SPARK_HOME/bin/spark-submit \
--master local[2] \
--class cn.itcast.spark.pack.WordCountPack \
hdfs://node1:8020/spark/apps/spark_project-1.0-SNAPSHOT.jar \
/datas/wordcount.data \
/datas/output

3、Standalone集群提交

  • 直接提交

    SPARK_HOME=/export/server/spark
    $SPARK_HOME/bin/spark-submit \
    --master spark://node1:7077 \
    --class cn.itcast.spark.pack.WordCountPack \
    hdfs://node1:8020/spark/apps/spark_project-1.0-SNAPSHOT.jar \
    /datas/wordcount.data \
    /datas/output
    

    在这里插入图片描述

  • 调整Executor和Driver的资源

    SPARK_HOME=/export/server/spark
    $SPARK_HOME/bin/spark-submit \
    --master spark://node1:7077 \
    --driver-memory 512M \
    --executor-memory 512M \
    --executor-cores 1 \
    --total-executor-cores 2 \
    --class cn.itcast.spark.pack.WordCountPack \
    hdfs://node1:8020/spark/apps/spark_project-1.0-SNAPSHOT.jar \
    /datas/wordcount.data \
    /datas/output
    

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Hlwg2HwW-1608858976349)(Spark%E6%95%99%E7%A8%8B.assets/image-20201217114030881.png)]

六、Spark on YARN

1、应用场景

  • 公司的硬件资源有限,Spark集群和Hadoop集群共用同一套硬件:所有资源也是共用的
    • 一台从节点:DataNode、NodeManger、Hadoop程序、Spark程序
  • 统一化资源管理平台:将MapReduce、Spark的程序都运行在YARN中
    • 主:ResourceManger
      • 将Spark的程序提交给YARN
    • 从:NodeManger
      • Executor启动在NodeManger中
    • 这里不需要再启动Master和Worker

2、集群配置

  • 修改yarn-site.xml

    <property>
    	    <name>yarn.log-aggregation-enable</name>
    	    <value>true</value>
    </property>
    <property>
    	    <name>yarn.log-aggregation.retain-seconds</name>
    	    <value>604800</value>
    </property>
    <property>
            <name>yarn.log.server.url</name>
            <value>http://node1:19888/jobhistory/logs</value>
    </property>
    <property>
    	    <name>yarn.nodemanager.pmem-check-enabled</name>
    	    <value>false</value>
    </property>
    <property>
    	    <name>yarn.nodemanager.vmem-check-enabled</name>
    	    <value>false</value>
    </property>
    
  • 分发

    cd /export/server/hadoop/etc/hadoop
    scp -r yarn-site.xml root@node2:$PWD
    scp -r yarn-site.xml root@node3:$PWD
    
  • 关闭Spark集群

    cd /export/server/spark
    sbin/stop-master.sh
    sbin/stop-slaves.sh
    sbin/stop-history-server.sh
    
  • 修改spark-env.sh

    #添加yarn的地址
    YARN_CONF_DIR=/export/server/hadoop/etc/hadoop
    
  • 配置HDFS上Spark jar包的存储位置:解决YARN运行Spark没有Spark的依赖包

    hdfs dfs -mkdir -p /spark/apps/jars/
    hdfs dfs -put /export/server/spark/jars/* /spark/apps/jars/
    
  • 修改spark-defaults.conf

    #为了在8088中能直接访问Spark程序的监控,所以这里这里做了转接,如果在yarn中点击history,就转接18080
    spark.yarn.historyServer.address   node1:18080
    #指定yarn运行时的spark的jar包的地址
    spark.yarn.jars  hdfs://node1:8020/spark/apps/jars/*
    
  • 分发

    cd /export/server/spark/conf/
    scp spark-env.sh spark-defaults.conf node2:$PWD
    scp spark-env.sh spark-defaults.conf node3:$PWD
    

3、启动测试

  • 启动YARN

    start-yarn.sh
    
  • 启动Jobhistoryserver

    mr-jobhistory-daemon.sh start historyserver
    
  • 启动Spark的HistoryServer

    /export/server/spark/sbin/start-history-server.sh 
    
  • 提交程序

    SPARK_HOME=/export/server/spark
    $SPARK_HOME/bin/spark-submit \
    --master yarn \
    --driver-memory 512M \
    --executor-memory 512M \
    --executor-cores 1 \
    --num-executors 3 \
    --class cn.itcast.spark.pack.WordCountPack \
    hdfs://node1:8020/spark/apps/spark_project-1.0-SNAPSHOT.jar \
    /datas/wordcount.data \
    /datas/output
    

七、DeployMode

1、问题与功能

  • driver:每次driver进程都启动在提交程序的客户端机器上

  • executor:个数和资源由用户自己指定,分配在哪些从节点,由集群自动分配管理

  • 如果driver都启动在一台机器,会导致两个问题

    • 这台机器的负载会很高
    • 如果这台机器故障,会导致driver进程失效,影响所有程序的运行
  • 解决:deploy模式:决定driver进程启动在哪台机器

    • client
    • cluster

2、client(开发不用,了解即可)

  • 默认的模式,一般用于测试环境
  • driver进程启动在客户端这台机器

3、cluster

  • 工作中一般生产时肯定选用cluster模式
  • Driver会随机分配在某台从节点中启动

4、区别

  • Driver运行的位置不同

  • client模式

    SPARK_HOME=/export/server/spark
    $SPARK_HOME/bin/spark-submit \
    --master spark://node1:7077 \
    --driver-memory 512M \
    --executor-memory 512M \
    --executor-cores 1 \
    --total-executor-cores 2 \
    --class cn.itcast.spark.pack.WordCountPack \
    hdfs://node1:8020/spark/apps/spark_project-1.0-SNAPSHOT.jar \
    /datas/wordcount.data \
    /datas/output
    
    
    SPARK_HOME=/export/server/spark
    $SPARK_HOME/bin/spark-submit \
    --master spark://node1:7077 \
    --deploy-mode client \
    --driver-memory 512M \
    --executor-memory 512M \
    --executor-cores 1 \
    --total-executor-cores 2 \
    --class cn.itcast.spark.pack.WordCountPack \
    hdfs://node1:8020/spark/apps/spark_project-1.0-SNAPSHOT.jar \
    /datas/wordcount.data \
    /datas/output
    

    在这里插入图片描述

  • cluster

    SPARK_HOME=/export/server/spark
    $SPARK_HOME/bin/spark-submit \
    --master spark://node1:7077 \
    --deploy-mode cluster \
    --driver-memory 512M \
    --executor-memory 512M \
    --executor-cores 1 \
    --total-executor-cores 2 \
    --class cn.itcast.spark.pack.WordCountPack \
    hdfs://node1:8020/spark/apps/spark_project-1.0-SNAPSHOT.jar \
    /datas/wordcount.data \
    /datas/output
    

    在这里插入图片描述
    在这里插入图片描述

5、Spark on YARN上的区别(面试中容易问到)

  • Spark on YARN client: driver进程启动在客户端
    在这里插入图片描述

  • Spark on YARN cluster: driver进程启动在NodeManger中
    在这里插入图片描述

    什么叫流量激增?
    咱们来想象一下。比如你的executor有100个,task有1000个。每个stage运行的时候,都有1000个task提交到executor上面去运行,平均每个executor有10个task。接下来问题来了,driver要频繁地跟executor上运行的1000个task进行通信。通信消息特别多,通信的频率特别高。运行完一个stage,接着运行下一个stage,又是频繁的通信。
    在整个spark运行的生命周期内,都会频繁的去进行通信和调度。所有这一切通信和调度都是从你的本地机器上发出去的,和接收到的。这是最要人命的地方。你的本地机器,很可能在30分钟内(spark作业运行的周期内),进行频繁大量的网络通信。那么此时,你的本地机器的网络通信负载是非常非常高的。会导致你的本地机器的网卡流量会激增!!!
    多个spark程序并行,cluster 模式下,不同的driver运行在不同的机器上,避免流量激增!

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值