spark程序提交执行,spark-shell,算子

文章目录

  • spark-shell
    • spark-shell里的内容
    • spark-submit
    • spark-class
  • spark的一些函数
    • 两种方法读文件
    • transformations和actions
  • 综合程序
    • 打包
    • 提交

把上一次编译后的包解压。

spark程序提交执行,spark-shell,算子_第1张图片
本地启动spark,可以在4040看到sparkUI
spark程序提交执行,spark-shell,算子_第2张图片
spark默认程序名字

spark程序提交执行,spark-shell,算子_第3张图片

spark-shell

spark-shell里的内容

调用spark-submit,默认名字Spark shell,$@相当于获取用户输入的模式(比如local)

"${SPARK_HOME}"/bin/spark-submit --class org.apache.spark.repl.Main --name "Spark shell" "$@"

spark-submit

调用了spark-class,传给spark-shell的参数被继承下来了

exec "${SPARK_HOME}"/bin/spark-class org.apache.spark.deploy.SparkSubmit "$@"

spark-class

加载spark-env,环境参数

. "${SPARK_HOME}"/bin/load-spark-env.sh

spark的一些函数

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

object Spark02 {
  def main(args: Array[String]): Unit = {
    val sparkConf=new SparkConf()
      //在spark-shell运行的时候再指定,这里的优先级要比在shell里更高,appname可以默认
      //shell里有内置
      //.setMaster("local[2]").setAppName("Spark02")

    val sc =new SparkContext(sparkConf)

    //创建rdd方法1,第一个参数是数组,第二个参数是默认切片
//    val rdd = sc.parallelize(Array(1,2,3,4,5))
    //collect把rdd里所有元素以数组方式返回
//    rdd.collect().foreach(println)

    //文件数据创建rdd,要保证每个节点下面相同路径有相同文件,返回的是一个字符串的rdd
    //第一个参数路径,第二个参数是最小分区数,分区数会影响到最终存储时生成文件的个数
    //读本地文件,建议加file声明
    //foreach是个action, 遇到action,就是一个job
    
    val rdd = sc.textFile("file:///E:/新建文件夹/ruoze wenjian shiping/asd.txt")
    rdd.collect().foreach(println)
    //注意top和collect都会内存加载所有数据,很大的数据不能直接collect,返回的是所有数据的数组,不然driver会挂掉,可以用take
    rdd.top(3)
    //默认升序,第一个参数是函数,第二个参数是排序方法
    rdd.sortBy(x=>x)


    //存储文件
    rdd.saveAsTextFile("file:///E:/新建文件夹/ruoze wenjian shiping/asd.txt")

  }

注意,虽然说一个action,一个job但是要注意action算子输入的是不是rdd,如果不是就不算。

比如下面用了两个action,但是只有1个job,因为collect的结果是array。

scala> rdd1.collect().foreach(x=>x)

两种方法读文件

假如集群有三台机器,三台机器都得有这个文件

scala> sc.textFile("hdfs://hadoop000:9000//g5/asd.txt")

textFile也可以读文件夹和压缩文件

scala> sc.wholeTextFiles("hdfs://hadoop000:9000//g5/asd.txt").collect

wholeTextFiles返回key-value形式,key是文件名,value是它包含的所有内容

默认情况下,文件存储的每个block(hdfs默认128M)都会被创建一个partition。你可以申请更多的partition。要注意,partition数量不要比block更少,不然每个task要处理的数据量会更多,一个文件有可能会被拆成一个很大的和一个很小的文件。

transformations和actions

transformations,rdd之间转换相当于作用transformation
rdda ?> rddb map filter
actions 返回一个结果到driver端,可以理解为客户端

transformation不会被立即执行,当action发生才会执行

综合程序

import java.net.URI

import org.apache.hadoop.conf.Configuration
import org.apache.hadoop.fs.{FileSystem, Path}
import org.apache.spark.{SparkConf, SparkContext}

/**
  * 这里我们是要把程序提交到spark上执行,
  * 所以读取文件和写文件应当由传入参数指定而不是写死
  * 输入:args(0)
  * 输出:args(1)
  */
object LogApp {
  def main(args: Array[String]): Unit = {
    val sparkConf=new SparkConf()
      //在spark-shell运行的时候再指定,这里的优先级要比在shell里更高,appname
      //shell里有内置
      //.setMaster("local[2]").setAppName("Spark02")

    val sc =new SparkContext(sparkConf)

    //写到hdfs要检测文件是否存在,存在要删掉,不然报错
    //val configuration = new Configuration
    val uri = new URI("hdfs://192.168.137.190:9000" )

    val fileSystem = FileSystem.get(uri,sc.hadoopConfiguration,"hadoop")
    if (fileSystem.exists(new Path(args(1)))){
      fileSystem.delete(new Path(args(1)),true)
    }

    //统计每个域名的流量和1
//    val lines = sc.textFile("file:///F:/ruozedata_workplace/g5-spark/generatefile")
//    lines.map(x=> {
//      val temp=x.split("\t")
//      //域名前面是hattps//,把后面的截取出来,然后域名后面的用户名以/分割
//      //原数据有的流量会多一个-
//      //注意流量要转为Long类型,不然字符串是拼接的
//      (temp(0).substring(8).split("/")(0),temp(2).replace("-","").toLong)
//    }).reduceByKey(_+_).collect().foreach(println)

    //统计每个域名流量和工业写法2
    val lines = sc.textFile(args(0))
    lines.map(x =>{
      val temp=x.split("\t")
      val domain = temp(0).substring(8).split("/")(0)
      //这里考虑到如果流量还有不标准的数据,会报错出问题,这里先给个默认值
      var response = 0L
      //出错就默认值输出错误咯
      try{
        response = temp(2).replace("-","").toLong
      } catch {
        case exception: Exception =>println("......")
      }
      (domain,response)
    }).reduceByKey(_+_).collect().foreach(println)


    //访问次数最多的url,排序
    //sortBy默认是升序排列
    //val lines = sc.textFile(args(0))
    lines.map(x=>{
      val temp = x.split("\t")
      val url = temp(0)
      var response = 0L
      try{
        response=temp(2).replace("-","").toLong
      }catch {
        case exception: Exception => println("!!!!!")
      }
      (temp(0),response)
      //注意take后面加不了save,因为他的返回值是数组,saveastextfile要输入rdd的算子
      //sortby输入是什么类型,输出就是什么类型
    }).reduceByKey(_+_).sortBy(_._2,false).saveAsTextFile(args(1))//take(3)//.collect()

    //求每个域名下访问次数最多的URL 排序
    val ac = lines.map(x=>{
      val temp = x.split("\t")
      val url = temp(0)
      val domain =temp(0).substring(8).split("/")(0)
      var response = 0L

      try {
         response = temp(2).replace("-","").toLong
      }catch {
        case exception: Exception=>println("fuckfuckfuck")
      }

      ((domain,url),response)
    }).reduceByKey(_+_)

    //(www.baidu.com,CompactBuffer(((www.baidu.com,https://www.baidu.com/),11)))
    val bc = ac.groupBy(_._1._1)//.foreach(println)

    var dom = bc.map(x=>{
      //注意这里的sortby不是spark的sortby,是scala的,因为输入不是rdd
      val top2 = x._2.toList.sortBy(x => x._2).reverse.take(1)
      top2
    })

    dom.foreach(x=>{
      println(x)
    })

    sc.stop()
  }

}

打包

注意中文文件报错,要改为英文
spark程序提交执行,spark-shell,算子_第4张图片
spark程序提交执行,spark-shell,算子_第5张图片
生成的jar包会在工程目录下的target文件夹下
spark程序提交执行,spark-shell,算子_第6张图片

提交

将代码放到一个shell文件里,注意\后面不要有空格
class是程序入口的主类,name是程序名字,后面是跑哪个程序
两个路径分别是程序传入的参数,一个是从哪里取,一个是输出到哪里

$SPARK_HOME/bin/spark-submit \
--master local[2] \
--class com.ruozedata.bigdata.core02.LogApp \
--name LogServerApp \
/home/hadoop/data/g5-spark-1.0.jar \
hdfs://hadoop000:9000/g5/generatefile hdfs://hadoop000:9000/g5/

给代码文件加个可执行的权限

chmod +x ....

然后运行即可

你可能感兴趣的:(大数据知识)