Spark经典案例(广播、自定义排序、缓冲)--------------根据需求进行日志的分析

数据的相关信息:
数据地址:
链接:https://pan.baidu.com/s/1kFCbYlpYW3xROAl9VvBlIg 密码:12tw

                          ipAddress: String, // IP地址
                          clientId: String, // 客户端唯一标识符
                          userId: String, // 用户唯一标识符
                          serverTime: String, // 服务器时间
                          method: String, // 请求类型/方式
                          endpoint: String, // 请求的资源
                          protocol: String, // 请求的协议名称
                          responseCode: Int, // 请求返回值:比如:200、401
                          contentSize: Long // 返回的结果数据大小

需求一:求contentSize(返回的结果数据大小)的平均值、最小值、最大值
需求二:求各个不同返回值的出现的数据
需求三:获取访问次数超过N次的IP地址
需求四: 获取访问次数最多的前K个endpoint的值 =====> TopN

package caseTest
/**
*
*

  •                       ipAddress: String, // IP地址
                          clientId: String, // 客户端唯一标识符
                          userId: String, // 用户唯一标识符
                          serverTime: String, // 服务器时间
                          method: String, // 请求类型/方式
                          endpoint: String, // 请求的资源
                          protocol: String, // 请求的协议名称
                          responseCode: Int, // 请求返回值:比如:200、401
                          contentSize: Long // 返回的结果数据大小
    

*/
import org.apache.log4j.{Level, Logger}
import org.apache.spark.{SparkConf, SparkContext}
import org.apache.spark.rdd.RDD

object NeedAllWithTeacher {
def main(args: Array[String]): Unit = {
Logger.getLogger(“org.apache.spark”).setLevel(Level.OFF)
val conf = new SparkConf()
conf.setAppName(“Need1”).setMaster(“local”)
val sc = new SparkContext(conf)
val lines: RDD[String] = sc.textFile(“D:\data\in\access_2013_05_31.log”)
//对数据进行过滤,空的过滤出去
val apacheAccessLog = lines.filter(line => ApacheAccessLog.isValidateLogLine(line)).map(line => {
//对数据进行转换处理
val log = ApacheAccessLog.parseLogLine(line)
log
})
//对多次使用的rdd进行cache
apacheAccessLog.cache()
//需求一:求contentSize(返回的结果数据大小)的平均值、最小值、最大值
//提取计算所需要的字段
val contentSizeRDD = apacheAccessLog.map(log => {
log.contentSize
})
//对重复使用的RDD进行cache
contentSizeRDD.cache()

//开始计算平均值,最小值、最大值
val totalContentSize = contentSizeRDD.sum()
val totalCount = contentSizeRDD.count()
val avgSize = totalContentSize * 1.0 / totalCount
val minSize = contentSizeRDD.min()
val maxSize = contentSizeRDD.max()

//当RDD不使用的时候,进行unpersist释放缓存
contentSizeRDD.unpersist()
println(s"ContentSize Avg:${avgSize},Min: ${minSize},Max: ${maxSize}")

//需求二:求各个不同返回值的出现的数据

//提取需要的字段数据,转换为key/value ,方便进行reduceBykey操作
//使用reduceBykey函数,按照key进行分组后,计算每个Key出现的次数
val responseCodeResultRDD = apacheAccessLog.map(log => (log.responseCode, 1)).reduceByKey(_ + _)
//结果输出
println(s"ResponseCode: ${responseCodeResultRDD.collect().mkString(",")}")


//需求三:获取访问次数超过N次的IP地址
//需求三额外:对IP地址进行限制,部分黑名单IP地址不统计
val blackIP = Array("200-55-104-193.dsl.prima.net.ar","208-38-57-205.ip.cal.raddiant.net")
//由于集合比较大,将集合的内容广播出去
val broadCastIP = sc.broadcast(blackIP)
val N = 10
val ipAddressRDD = apacheAccessLog
  //过滤地址在黑名单中的数据
  .filter(log => !broadCastIP.value.contains(log.ipAddress))
  //获取计算需要的IP地址数据,并将返回值转换为key/value键值对类型
  .map(log => (log.ipAddress,1L))
//使用reduceBykey函数进行聚合操作
  .reduceByKey(_+_)
//过滤数据,要求IP地址必须出现N次以上
  .filter(tuple => tuple._2>N)
//获取满足条件的IP地址,为了展示方便,将下面这行代码注释
//    .map(tuple=> tuple._1)
//结果输出
println(s"""IP Address :${ipAddressRDD.collect().mkString(",")}""")



//需求四: 获取访问次数最多的前K个endpoint的值 =====> TopN
val K = 10
val topKValues = apacheAccessLog
//获取计算需要的IP地址数据,并将返回值转换为Key/value键值对类型
  .map(log => (log.endpoint,1))
//获得每个enpoint对应的出现次数
  .reduceByKey(_+_)
//获取前10个元素,而且使用我们自定义的排序类
  .top(K)(LogSorting.TupleOrdering)
//如果只需要endpoint的值,不需要出现次数,那么可以通过map函数进行转换
 //   .map(_._1)
//结果输出
println(s"""TopK values:${topKValues.mkString(",")}""")
//对不再使用的RDD,去除cache

sc.stop()

}
}

自定义排序的代码:
package caseTest

object LogSorting {
object TupleOrdering extends scala.math.Ordering[(String,Int)]{
override def compare(x: (String, Int), y: (String, Int)): Int = {
//按照出现的次数进行比较,也就是按照二元组的第二个元素进行比较
x._2.compare(y._2)
}
}
}

猜你喜欢

转载自blog.csdn.net/qq_41166135/article/details/82883982