利用Scala语言开发Spark应用程序

开发 前端 Spark
park内核是由Scala语言开发的,因此使用Scala语言开发Spark应用程序是自然而然的事情。如果你对Scala语言还不太熟悉,可以阅读网络教程A Scala Tutorial for Java Programmers或者相关Scala书籍进行学习。

Spark内核是由Scala语言开发的,因此使用Scala语言开发Spark应用程序是自然而然的事情。如果你对Scala语言还不太熟悉,可以阅读网络教程A Scala Tutorial for Java Programmers或者相关Scala书籍进行学习。

本文将介绍3个Scala Spark编程实例,分别是WordCount、TopK和SparkJoin,分别代表了Spark的三种典型应用。

1. WordCount编程实例

WordCount是一个最简单的分布式应用实例,主要功能是统计输入目录中所有单词出现的总次数,编写步骤如下:

步骤1:创建一个SparkContext对象,该对象有四个参数:Spark master位置、应用程序名称,Spark安装目录和jar存放位置,对于Spark On YARN而言,最重要的是前两个参数,***个参数指定为“yarn-standalone”,第二个参数是自定义的字符串,举例如下:

  1. val sc = new SparkContext(args(0), "WordCount", 
  2.     System.getenv("SPARK_HOME"), Seq(System.getenv("SPARK_TEST_JAR"))) 
  3.  

步骤2:读取输入数据。我们要从HDFS上读取文本数据,可以使用SparkCon

  1. val textFile = sc.textFile(args(1)) 

当然,Spark允许你采用任何Hadoop InputFormat,比如二进制输入格式SequenceFileInputFormat,此时你可以使用SparkContext中的hadoopRDD函数,举例如下:

  1. val inputFormatClass = classOf[SequenceFileInputFormat[Text,Text]] 
  2. var hadoopRdd = sc.hadoopRDD(conf, inputFormatClass, classOf[Text], classOf[Text]) 

或者直接创建一个HadoopRDD对象:

  1. var hadoopRdd = new HadoopRDD(sc, conf, 
  2.      classOf[SequenceFileInputFormat[Text,Text, classOf[Text], classOf[Text]) 

步骤3:通过RDD转换算子操作和转换RDD,对于WordCount而言,首先需要从输入数据中每行字符串中解析出单词,然后将相同单词放到一个桶中,***统计每个桶中每个单词出现的频率,举例如下:

  1. val result = hadoopRdd.flatMap{ 
  2.         case(key, value)  => value.toString().split("\\s+"); 
  3. }.map(word => (word, 1)). reduceByKey (_ + _) 

其中,flatMap函数可以将一条记录转换成多条记录(一对多关系),map函数将一条记录转换为另一条记录(一对一关系),reduceByKey函数将key相同的数据划分到一个桶中,并以key为单位分组进行计算,这些函数的具体含义可参考:Spark Transformation。

步骤4:将产生的RDD数据集保存到HDFS上。可以使用SparkContext中的saveAsTextFile哈数将数据集保存到HDFS目 录下,默认采用Hadoop提供的TextOutputFormat,每条记录以“(key,value)”的形式打印输出,你也可以采用 saveAsSequenceFile函数将数据保存为SequenceFile格式等,举例如下:

  1. result.saveAsSequenceFile(args(2)) 

当然,一般我们写Spark程序时,需要包含以下两个头文件:

  1. import org.apache.spark._ 
  2. import SparkContext._ 

WordCount完整程序已在“Apache Spark学习:利用Eclipse构建Spark集成开发环境”一文中进行了介绍,在次不赘述。

需要注意的是,指定输入输出文件时,需要指定hdfs的URI,比如输入目录是hdfs://hadoop-test/tmp/input,输出目 录是hdfs://hadoop-test/tmp/output,其中,“hdfs://hadoop-test”是由Hadoop配置文件core- site.xml中参数fs.default.name指定的,具体替换成你的配置即可。

2. TopK编程实例

TopK程序的任务是对一堆文本进行词频统计,并返回出现频率***的K个词。如果采用MapReduce实现,则需要编写两个作 业:WordCount和TopK,而使用Spark则只需一个作业,其中WordCount部分已由前面实现了,接下来顺着前面的实现,找到Top K个词。注意,本文的实现并不是***的,有很大改进空间。

步骤1:首先需要对所有词按照词频排序,如下:

  1. val sorted = result.map { 
  2.   case(key, value) => (value, key); //exchange key and value 
  3. }.sortByKey(true, 1) 

步骤2:返回前K个:

  1. val topK = sorted.top(args(3).toInt) 

步骤3:将K各词打印出来:

  1. topK.foreach(println) 

注意,对于应用程序标准输出的内容,YARN将保存到Container的stdout日志中。在YARN中,每个Container存在三个日志 文件,分别是stdout、stderr和syslog,前两个保存的是标准输出产生的内容,第三个保存的是log4j打印的日志,通常只有第三个日志中 有内容。

本程序完整代码、编译好的jar包和运行脚本可以从这里下载。下载之后,按照“Apache Spark学习:利用Eclipse构建Spark集成开发环境”一文操作流程运行即可。

3. SparkJoin编程实例

在推荐领域有一个著名的开放测试集是movielens给的,下载链接是:http://grouplens.org/datasets/movielens/,该测试集包含三个文件,分别是ratings.dat、sers.dat、movies.dat,具体介绍可阅读:README.txt,本节给出的SparkJoin实例则通过连接ratings.dat和movies.dat两个文件得到平均得分超过4.0的电影列表,采用的数据集是:ml-1m。程序代码如下:

  1. import org.apache.spark._ 
  2. import SparkContext._ 
  3. object SparkJoin { 
  4.   def main(args: Array[String]) { 
  5.     if (args.length != 4 ){ 
  6.       println("usage is org.test.WordCount <master> <rating> <movie> <output>"
  7.       return 
  8.     } 
  9.     val sc = new SparkContext(args(0), "WordCount"
  10.     System.getenv("SPARK_HOME"), Seq(System.getenv("SPARK_TEST_JAR"))) 
  11.   
  12.     // Read rating from HDFS file 
  13.     val textFile = sc.textFile(args(1)) 
  14.   
  15.     //extract (movieid, rating) 
  16.     val rating = textFile.map(line => { 
  17.         val fileds = line.split("::"
  18.         (fileds(1).toInt, fileds(2).toDouble) 
  19.        }) 
  20.   
  21.     val movieScores = rating 
  22.        .groupByKey() 
  23.        .map(data => { 
  24.          val avg = data._2.sum / data._2.size 
  25.          (data._1, avg) 
  26.        }) 
  27.   
  28.      // Read movie from HDFS file 
  29.      val movies = sc.textFile(args(2)) 
  30.      val movieskey = movies.map(line => { 
  31.        val fileds = line.split("::"
  32.         (fileds(0).toInt, fileds(1)) 
  33.      }).keyBy(tup => tup._1) 
  34.   
  35.      // by join, we get <movie, averageRating, movieName> 
  36.      val result = movieScores 
  37.        .keyBy(tup => tup._1) 
  38.        .join(movieskey) 
  39.        .filter(f => f._2._1._2 > 4.0) 
  40.        .map(f => (f._1, f._2._1._2, f._2._2._2)) 
  41.   
  42.     result.saveAsTextFile(args(3)) 
  43.   } 

你可以从这里下载代码、编译好的jar包和运行脚本。

这个程序直接使用Spark编写有些麻烦,可以直接在Shark上编写HQL实现,Shark是基于Spark的类似Hive的交互式查询引擎,具体可参考:Shark

4. 总结

Spark 程序设计对Scala语言的要求不高,正如Hadoop程序设计对Java语言要求不高一样,只要掌握了最基本的语法就能编写程序,且常见的语法和表达方式是很少的。通常,刚开始仿照官方实例编写程序,包括Scala、Java和Python三种语言实例。

原文链接:http://dongxicheng.org/framework-on-yarn/spark-scala-writing-application/

责任编辑:陈四芳 来源: dongxicheng.org
相关推荐

2010-11-18 15:52:32

QMLMeeGo

2012-06-07 09:15:14

ibmdw

2013-02-21 14:15:41

开发Tizen

2013-02-21 14:14:40

开发Tizen

2012-02-08 15:06:31

ibmdw

2022-09-19 00:37:13

SaaS云计算开发

2012-03-20 09:20:40

Go语言

2011-04-01 11:01:02

应用程序BlackBerryJava

2012-06-08 09:28:15

EclipseScalaAndroid

2013-11-19 15:35:01

2009-07-29 17:42:47

ibmdwWeb2.0

2009-08-27 11:53:45

ibmdw云计算

2017-08-09 17:09:47

2011-12-06 10:10:59

云计算移动应用

2011-03-31 13:15:18

BlackBerry

2018-12-11 11:41:14

物联网应用程序IOT

2011-02-22 10:23:43

2009-09-24 17:21:17

加速Hibernate

2010-10-15 09:39:22

MeeGoQt

2013-08-08 09:48:10

Web
点赞
收藏

51CTO技术栈公众号