IDEA中使用Maven开发Spark应用程序

31 篇文章 2 订阅
23 篇文章 9 订阅
1 环境搭建
1.1 使用maven创建spark项目

这里写图片描述
如上图所示点击next创建自己的spark项目;
这里写图片描述
对maven进行修改

1.2 修改pom.xml
<!--依赖的版本-->
<properties>
      <scala.version>2.11.8</scala.version>
      <spark.version>2.2.0</spark.version>
      <hadoop.version>2.6.0-cdh5.7.0</hadoop.version>
</properties>

<!--jar包下载的创库-->
<repositories>
    <repository>
      <id>cloudera</id>
      <name>cloudera</name>
      <url>https://repository.cloudera.com/artifactory/cloudera-repos</url>
    </repository>
</repositories>

<!--scala depedency-->
    <dependency>
      <groupId>org.scala-lang</groupId>
      <artifactId>scala-library</artifactId>
      <version>${scala.version}</version>
    </dependency>

    <!--spark core depedency-->
    <dependency>
      <groupId>org.apache.spark</groupId>
      <artifactId>spark-core_2.11</artifactId>
      <version>${spark.version}</version>
    </dependency>

<!--hadoop-client depedency-->
    <dependency>
      <groupId>org.apache.hadoop</groupId>
      <artifactId>hadoop-client</artifactId>
      <version>${hadoop.version}</version>
    </dependency>
2 词频统计代码开发
import org.apache.spark.{SparkConf, SparkContext}
/**
  * Created by grace on 2018/4/27.
  */
object WordCountApp {
  def main(args: Array[String]): Unit = {
    //创建一个SparkConf
    val conf=new SparkConf();
    //sparkContext中传递一个SparkConf
    val sc=new SparkContext(conf);
    //接受一个文件
    val textFile=sc.textFile(args(0));

    //词频统计
    // (这里注意了,自己的文件是按照什么切分的,
    //作者就因为文件中的单词按照空格切分,代码中按照“\t”切分了,一直得不到想要的结果)
    val wc=textFile.flatMap(line =>line.split(" ")).map(x=>(x,1)).reduceByKey(_+_);

    //控制台输出结果
    wc.collect().foreach(println)

    //把结果存入到hdfs上
    //saveAsTextFile这个方法可以传递codec选择压缩方式进行存储
    wc.saveAsTextFile(args(1))
    //关闭
    sc.stop();
  }
}

注意: saveAsTextFile这个方法

/**
   * Save this RDD as a compressed text file, using string representations of elements.
   */
  def saveAsTextFile(path: String, codec: Class[_ <: CompressionCodec]): Unit = withScope {
    // https://issues.apache.org/jira/browse/SPARK-2075
    val nullWritableClassTag = implicitly[ClassTag[NullWritable]]
    val textClassTag = implicitly[ClassTag[Text]]
    val r = this.mapPartitions { iter =>
      val text = new Text()
      iter.map { x =>
        text.set(x.toString)
        (NullWritable.get(), text)
      }
    }
    RDD.rddToPairRDDFunctions(r)(nullWritableClassTag, textClassTag, null)
      .saveAsHadoopFile[TextOutputFormat[NullWritable, Text]](path, codec)
  }

通过源码我们可以看出saveAsTextFile这个方法可以传递codec选择压缩方式进行存储def saveAsTextFile(path: String, codec: Class[_ <: CompressionCodec]) 可以传递两个参数:保存路径和压缩格式,大家可以自己测试下。

3 打包上传

这里写图片描述
这里写图片描述
点击package运行打包成功可以再target陌路下找到该jar包,这时候就可以上传了

这里写图片描述

4 提交应用程序(spark-submit)

**注意:**这里作者出现了几个错误,详见该博客

  • 输入文件
[hadoop@hadoop data]$ cat input.txt 
hello java
hello hadoop
hello hive
hello sqoop
hello hdfs
hello spark
  • 任务提交
如果没有配置`SPARK_HOME`需要再bin目录下提交
spark-submit \
--class cn.zhangyu.WordCountApp \
--master local[2] \
/home/hadoop/lib/wordcount-1.0-SNAPSHOT.jar \
/input	/output 

其中/input为输入文件的目录(hdfs上),不存在会报错
/output为输出文件的目录
如果不行修改成:
./spark-submit \
--class cn.zhangyu.WordCountApp \
/home/hadoop/lib/spark_test-1.0.jar \
hdfs://主机名或者ip:端口号/输入文件目录 hdfs://主机名或者ip:端口号/输出文件目录	  
这个端口号是配置再core-site.xml中的。	  
  • 控制台输出结果
(hive,1)
(hello,6)
(java,1)
(sqoop,1)
(spark,1)
(hadoop,1)
(hdfs,1)
  • hdfs输出结果
[hadoop@hadoop data]$ hdfs dfs -ls /output
Found 3 items
-rw-r--r--   3 hadoop supergroup          0 2018-04-21 03:54 /output/_SUCCESS
-rw-r--r--   3 hadoop supergroup         39 2018-04-21 03:54 /output/part-00000.deflate
-rw-r--r--   3 hadoop supergroup         31 2018-04-21 03:54 /output/part-00001.deflate
[hadoop@hadoop data]$ hdfs dfs -text /output/part-00000.deflate 
18/04/21 03:57:17 INFO zlib.ZlibFactory: Successfully loaded & initialized native-zlib library
18/04/21 03:57:17 INFO compress.CodecPool: Got brand-new decompressor [.deflate]
(hive,1)
(hello,6)
(java,1)
(sqoop,1)

注意:

18/04/21 03:54:07 INFO FileInputFormat: Total input paths to process : 1

大家在日志中会发现这句话,先猜测下是什么意思呢?

5处理多个文件
这里又上传了四个文件
[hadoop@hadoop data]$ hdfs dfs -put input.txt  /input/1
[hadoop@hadoop data]$ hdfs dfs -put input.txt  /input/2
[hadoop@hadoop data]$ hdfs dfs -put input.txt  /input/3
[hadoop@hadoop data]$ hdfs dfs -ls  /input             
Found 4 items
-rw-r--r--   3 hadoop supergroup         70 2018-04-21 04:06 /input/1
-rw-r--r--   3 hadoop supergroup         70 2018-04-21 04:06 /input/2
-rw-r--r--   3 hadoop supergroup         70 2018-04-21 04:06 /input/3
-rw-r--r--   3 hadoop supergroup         70 2018-04-20 19:27 /input/input.txt
  • 提交任务
spark-submit \
--class cn.zhangyu.WordCountApp \
--master local[2] \
/home/hadoop/lib/wordcount-1.0-SNAPSHOT.jar \
/input	/output1
  • 结果
查看结果没毛病都乘了4
(hive,4)
(spark,4)
(hadoop,4)
(hdfs,4)
(hello,24)
(java,4)
(sqoop,4)

这时候大家再看日志,有没有发现这样一句话:

18/04/21 04:07:37 INFO FileInputFormat: Total input paths to process : 4

熟悉吗,应该知道什么意思了把,也就是split数量,为什么这样说呢,因为我们测试用的文件很小(小于128MB)如果文件大于128,这里个数就需要和128进行比较了。

6 文件匹配规则
spark-submit \
--class cn.zhangyu.WordCountApp \
--master local[2] \
/home/hadoop/lib/wordcount-1.0-SNAPSHOT.jar \
/input/*.txt	 /output2

这里输入文件只会带有.txt结尾的。

  • 结果
(hive,1)
(hello,6)
(java,1)
(sqoop,1)
(spark,1)
(hadoop,1)
(hdfs,1)
7 wordcount进行排序
import org.apache.spark.{SparkConf, SparkContext}
/**
  * Created by grace on 2018/4/27.
  */
object WordCountApp {
  def main(args: Array[String]): Unit = {
    //创建一个SparkConf
    val conf=new SparkConf();
    //sparkContext中传递一个SparkConf
    val sc=new SparkContext(conf);
    //接受一个文件
    val textFile=sc.textFile(args(0));

    //词频统计
    // (这里注意了,自己的文件是按照什么切分的,作者就因为文件中的单词按照空格切分,代码中按照“\t”切分了,一直得不到想要的结果)
    val wc=textFile.flatMap(line =>line.split(" ")).map(x=>(x,1)).reduceByKey(_+_);

    //根据value进行排序
    // 1 map(x=>(x._2,x._1)) 这里相当于把key和value位置互换
    // 2 sortByKey(false) 因为sortByKey()默认是按照升序排列的,所以传递一个false
    /*
    源码:sortByKey默认是ascending=true
    def sortByKey(ascending : scala.Boolean = { /* compiled code */ }, numPartitions : scala.Int = { /* compiled code */ })
     */
    // 3 .map(x=>(x._2,x._1)) 在进行反转一次,得到我们想要的结果
    val sort=wc.map(x=>(x._2,x._1)).sortByKey(false).map(x=>(x._2,x._1))
    //控制台输出结果
    wc.collect().foreach(println)

    //把结果存入到hdfs上
    //saveAsTextFile这个方法可以传递codec选择压缩方式进行存储
    wc.saveAsTextFile(args(1))
    //关闭
    sc.stop();
  }
}

提示: 这样每次改变代码都要打包上传,比较麻烦,可以使用spark-shell进行测试。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值