使用环境
Windows下使用IDEA开发工具
Windows环境配置了JDK1.8环境与Scala环境
准备事项
本文WordCount案例预实现将Linux中的HDFS中的文件读取出来
统计字符出现次数,并将结果存放到HDFS目录中
配置Hadoop环境中的权限
修改hadoop中的配置文件hdfs-site.xml
将Hadoop中的配置文件存放到IDEA项目中的resource中
IDEA中的pom.xml配置文件
使用了Maven管理依赖
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.huadian</groupId>
<artifactId>spark-learning</artifactId>
<version>1.0-SNAPSHOT</version>
<repositories>
<repository>
<id>aliyun</id>
<url>http://maven.aliyun.com/nexus/content/groups/public/</url>
</repository>
<repository>
<id>cloudera</id>
<url>https://repository.cloudera.com/artifactory/cloudera-repos/</url>
</repository>
<repository>
<id>jboss</id>
<url>http://repository.jboss.com/nexus/content/groups/public</url>
</repository>
</repositories>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<maven.compiler.source>1.7</maven.compiler.source>
<maven.compiler.target>1.7</maven.compiler.target>
<hadoop.version>2.6.0-cdh5.7.6</hadoop.version>
<spark.version>2.2.0</spark.version>
</properties>
<dependencies>
<dependency>
<groupId>org.apache.spark</groupId>
<artifactId>spark-core_2.11</artifactId>
<version>${spark.version}</version>
</dependency>
<dependency>
<groupId>org.apache.spark</groupId>
<artifactId>spark-sql_2.11</artifactId>
<version>${spark.version}</version>
</dependency>
<dependency>
<groupId>org.apache.hadoop</groupId>
<artifactId>hadoop-client</artifactId>
<version>${hadoop.version}</version>
</dependency>
</dependencies>
<build>
<pluginManagement><!-- lock down plugins versions to avoid using Maven defaults (may be moved to parent pom) -->
<plugins>
<plugin>
<artifactId>maven-clean-plugin</artifactId>
<version>3.0.0</version>
</plugin>
<!-- see http://maven.apache.org/ref/current/maven-core/default-bindings.html#Plugin_bindings_for_jar_packaging -->
<plugin>
<artifactId>maven-resources-plugin</artifactId>
<version>3.0.2</version>
</plugin>
<plugin>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.7.0</version>
</plugin>
<plugin>
<artifactId>maven-surefire-plugin</artifactId>
<version>2.20.1</version>
</plugin>
<plugin>
<artifactId>maven-jar-plugin</artifactId>
<version>3.0.2</version>
</plugin>
<plugin>
<artifactId>maven-install-plugin</artifactId>
<version>2.5.2</version>
</plugin>
<plugin>
<artifactId>maven-deploy-plugin</artifactId>
<version>2.8.2</version>
</plugin>
</plugins>
</pluginManagement>
</build>
</project>
使用SparkContext实现WordCount
import org.apache.spark.rdd.RDD
import org.apache.spark.{SparkConf, SparkContext}
object SparkContext{
//scala程序的入口,也是spark application运行Driver
def main(args: Array[String]): Unit = {
//Spark app 配置:应用的名字和Master运行的位置
val sparkConf = new SparkConf()
.setAppName("SparkAppTemplate")
.setMaster("local[2]")
//创建sparkContext对象:主要用于读取需要处理的数据,封装在RDD集合中;调度jobs执行
val sc = new SparkContext(sparkConf)
sc.setLogLevel("WARN")
//第一步:数据的读取(输入)
val inputRDD: RDD[String] = sc.textFile("/wc.input")
println(s"count:${inputRDD.count()}")
println(s"first:${inputRDD.first()}")
//第二步:数据的处理(分析)
//分割 ->(key,1) ->分组
val wordCountRDD: RDD[(String, Int)] = inputRDD
//.flatMap(item => item.split(" "))
.flatMap(_.split(" "))
//.map(word =>(word,1))
.map((_,1))
//.reduceByKey((a,b)=>a+b)
.reduceByKey(_ + _)
//第三步:数据的输出(输出)
wordCountRDD.foreach(println)
wordCountRDD.saveAsTextFile("/wc-output/"+System.currentTimeMillis())
//inputRDD.unpersist()
//开发测试的时候,为了对每个spark app页面监控查看job的执行情况,
//spark app运行结束4040端口就没了
//关闭资源
sc.stop()
}
}
使用SparkSession实现WordCount
package com.huadian.bigdata.spark.core
import org.apache.spark.rdd.RDD
import org.apache.spark.sql.{Dataset, SparkSession}
import org.apache.spark.{SparkConf, SparkContext}
/**
* Spark Application开发模板
*/
object SparkSessionWordCount {
//scala程序的入口,也是spark application运行Driver
def main(args: Array[String]): Unit = {
//在spark 2.x中不推荐使用sparkContext对象读取数据,而是推荐SparkSession
val spark = SparkSession.builder
.appName("Simple Application")
.master("local[2]")
.getOrCreate()
//设置日志级别
spark.sparkContext.setLogLevel("WARN")
//第一步:数据的读取(输入)
//DataSet = RDD + schema
//如果RDD是一个人的话,到底有什么属性,我们是不知道的,只有执行的时候才知道
//如果是DataSet的话,有name,age字段,以及对应数据类型
val inputRDD: RDD[String] = spark.read.textFile("/wc.input").rdd
//第二步:数据的处理(分析)
val wordCountRDD: RDD[(String, Int)] = inputRDD.flatMap(_.split(" ")).map((_,1)).reduceByKey(_ + _)
//第三步:数据的输出(输出)
wordCountRDD.foreach(println)
println("===========输出前三方式1==========")
wordCountRDD
.map(tuple=>tuple.swap)
//.map(_.swap)
.top(3)
.foreach(println)
println("=======输出前三方式2===========")
wordCountRDD
.top(3)(OrderUtils.SecondValueOrder)
.foreach(println)
//开发测试的时候,为了对每个spark app页面监控查看job的执行情况,
//spark app运行结束4040端口就没了
//关闭资源
spark.stop()
}
object OrderUtils{
object SecondValueOrder extends scala.math.Ordering[(String,Int)]{
override def compare(x: (String, Int), y: (String, Int)): Int = x._2 - y._2
}
}
}
案例:用户行为数据行为分析
本案例运行在Windows环境下,IDEA中
数据格式
第一项为用户访问时间
第二项为用户访问网址
第三项为用户会话id
2013-05-19 13:00:00 http://www.taobao.com/17/?tracker_u=1624169&type=1 B58W48U4WKZCJ5D1T3Z9ZY88RU7QA7B1
实现思路
第一步,读取数据文件
第二步:处理数据文件
第三步:提取时间数据与用户会话id数据
第四步:按照用户会话id分组,键为用户会话id,值为访问时间
第五步:计算会话时间,判断用户停留时间区间,返回用户停留时间区间,键为用户停留时间,值为1
第六步:按照用户停留时间区间进行聚合统计用户停留时间区间
第七步:输出结果
代码实现
import org.apache.spark.rdd.RDD
import org.apache.spark.sql.SparkSession
import org.apache.spark.{SparkConf, SparkContext}
object SparkApp2 {
val TIME_LENGTH_0010:String = "0-10"
val TIME_LENGTH_1120:String = "11-20"
val TIME_LENGTH_2130:String = "21-30"
val TIME_LENGTH_3000:String = "30++"
def main(args: Array[String]): Unit = {
//在spark 2.x中不推荐使用sparkContext对象读取数据,而是推荐SparkSession
val spark = SparkSession.builder
.appName("Simple Application")
.master("local[2]")
.getOrCreate()
spark.sparkContext.setLogLevel("WARN")
//第一步:数据的读取(输入)
//DataSet = RDD + schema
//如果RDD是一个人的话,到底有什么属性,我们是不知道的,只有执行的时候才知道
//如果是DataSet的话,有name,age字段,以及对应数据类型
// 第一步,读取数据文件
val first: RDD[String] = spark.read.textFile("file:///E:\\JavaWork\\20190801\\page_views.data").rdd
// 第二步:处理数据文件
val second: RDD[(String, Long)] = first.map{
// 第三步:提取时间数据与用户会话id数据
line=>{
val arr: Array[String] = line.split("\t")
import java.text.SimpleDateFormat
//获取时间,为时间戳格式,方便运算
val time: Long = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").parse(arr(0)).getTime
//返回值
(arr(2),time)
}
}
// 第四步:按照用户会话id分组,键为用户会话id,值为访问时间
val fourth: RDD[(String, Iterable[Long])] = second.groupByKey()
// 第五步:计算会话时间,判断用户停留时间区间,返回用户停留时间区间,键为用户停留时间,值为1
val fifth: RDD[(String, Int)] = fourth.map{
case (sessionId:String,iter:Iterable[Long])=>{
//最大的访问时间
val maxTackTime = iter.max
//最小的访问时间
val minTackTime = iter.min
//访问的会话时间
val timeLength = (maxTackTime - minTackTime)/1000.0
if(timeLength >30){
(TIME_LENGTH_3000,1)
}else if (timeLength >20){
(TIME_LENGTH_2130,1)
}else if (timeLength >10){
(TIME_LENGTH_1120,1)
}else{
(TIME_LENGTH_0010,1)
}
}
}
// 第六步:按照用户停留时间区间进行聚合统计用户停留时间区间
val sixth: RDD[(String, Int)] = fifth.reduceByKey(_+_)
// 第七步:输出结果
sixth.foreach(println)
//输出各个RDD的依赖关系
println(sixth.toDebugString)
Thread.sleep(1000000000)
//关闭资源
spark.stop()
}
}