Spark 1.6 SparkSQL实践


数据源CDN日志。

每行日志数据格式:

序号

名称

说明

1

客户端IP

 

2

预留字段

 

3

预留字段

 

4

请求时间

格式为:[dd/MMM/yyyy:HH:mm:ss Z]

5

请求url

格式为:”GET url HTTP/1.1

6

Http状态

 

7

下载资源大小

单位:B(字节)

8

请求响应时间

单位:S(秒)

9

http HOST

 

10

referer

 

11

UA

格式:-UA

12

http_x_forwarded_for

 

13

cache_status

行日志举例:

122.96.47.110 - - [31/Mar/2015:18:39:18 +0800] "GET /proxy/url HTTP/1.1" 206 16986961 215.905 112.80.4.187 "-" "Xiaomi_2013023_TD/V1 Linux/3.4.5 Android/4.2.1 Release/03.11.2013 Browser/AppleWebKit534.30 Mobile Safari/534.30 MBBMS/2.2 System/Android 4.2.1;" "-" -

分析需求:

 (1)整体请求的平均响应时间                 并按照从大到小排序

 (2)各个IP请求的平均响应时间    并按照从大到小排序

  (3)  各个IP访问的总流量统计       并按照从大到小排序

  (4)  使用iphone/android访问的用户数

  (5)  不同http状态码占比情况


分析开始:

第一步加载数据源: 从hdfs文件系统读取日志文件,创建RDD对象


val rdds = sc.textFile("hdfs://132.bd:8020/spark/testdata/localhost.access.log")




第二步定义数据解析结构类: LogEntity


class LogEntity(val ip: String, val res1 : String, val res2: String,
                val timestamp : String, val url: String, val http_code : Int, val size: Long, val reponse : Float,
                val host : String, val refer: String, val ua : String, val forward: String, val cache_status : String) {
}
第三步定义 将行字符串(日志)转换成数据解析结构类的函数


def convert2 (line : String): LogEntity = {
    val regex = """([0-9|\.]+) (.|-) (.|-) (\[\w+\/\w+/\w+\:\w+\:\w+\:\w+) (\+\w+\]) (\"GET.+\") (\d+) (\d+) ([\d|\.]+) ([0-9|\.|\:]+) (\".+\") (\".+\") (\".+\") (.)""". r
    try {
      val regex(f1, f2, f3, f4, f5, f6, f7, f8, f9, f10, f11, f12, f13, f14) = line
      val l = new LogEntity( f1, f2, f3, f4 + f5, f6, f7.toInt , f8.toLong, f9.toFloat , f10 , f11 , f12 , f13 , f14 )
      return l
    } catch {
      case e: Exception => {
        return null
      }
    }
  }

第四步定义模式匹配类 用于生成DataFrame对象Schema

case class CDNLog(ip: String, res1: String, res2 : String,
                  timestamp: String , url : String, http_code: Int, size: Long, reponse: Float,
                  host: String, refer : String, ua: String, forward: String, cache_status: String ) 



第五步 创建sqlContext对象

import org.apache.spark.sql.SQLContext

val sqlc = new SQLContext(sc)


第六步 将RDD对象先进行结构类解析,然后过滤掉未解析成功的数据行,将解析后的LogEntity进行模式匹配,转换成CDNLog,并最终将RDD对象转换成DataFrame对象。


import sqlc.implicits._
val logs = rdds.map(x => convert2 (x)).filter (x=>x !=null).map (l => CDNLog (l.ip , l .res1, l .res2, l .timestamp, l .url, l .http_code, l .size, l .reponse, l .host, l .refer, l .ua, l .forward, l .cache_status)).toDF () 





至此我们实现了将日志文本数据转换成DataFrame的过程,

DataFrame是SparkSQL的核心概念,基于该对象我们可以有两种方式来实现对数据的分析

(1)将DataFrame 注册为一个临时内存表,从而使用SQL语句来实现数据统计分析

(2)基于DataFrame的API操作可以实现数据的统计分析



方式一:将DataFrame对象 logs注册为临时内存表,再使用sql语句进一步分析

         logs .registerTempTable( "cdnlog")   //将logs对象注册为临时内存表 命名为cdnlog

         val responses = sqlc.sql("select avg(reponse) as avg_response from cdnlog") //使用sql语句查询cdnlog数据表,查询平均响应时间。


           打印执行结果:  responses.show          

         

          即整体平均响应时间为:5.68s



方式二  使用DataFrame API实现所有需求 , 重点将详述该种方式来实现所有需求模型。

 (1)整体请求的平均响应时间                 并按照从大到小排序

使用DataFrame.agg函数


logs.agg(avg("reponse")).show





结果:所有用户平均访问响应时间5.68s



 (2)各个IP请求的平均响应时间    并按照从大到小排序


使用DataFrame.grouBy函数


logs.groupBy("ip").agg(avg("reponse") as "avgg").sort($"avgg" desc).show




结果展示了:各个IP访问的平均像一个时间(s)并按照从大到小顺序排序 


  (3)  各个IP访问的总流量统计       并按照从大到小排序

使用DataFrame.grouBy函数


logs.groupBy("ip").agg(sum("size") as "total-bytes").sort($"total-bytes" desc).show




结果展示了:各个IP的访问流量总和,以及按照流量大小进行了排序。

  (4)  使用iphone/android访问的用户数

使用DataFrame.filter函数


        总的访问用户数: 1253               logs.select("ip").distinct.count
       使用iphone的用户数:752           logs.filter(logs("ua").contains("iPhone")).select("ip").distinct.count
       使用android用户数:405             logs.filter(logs("ua").contains("Android")).select("ip").distinct.count


  (5)  不同http状态码占比情况


   依然是DataFrame.groupBy函数

logs.groupBy("http_code").count.sort($"count" desc).show



分析结果展示了:各个状态码的统计结果,以及排序。




总结: 本文主要通过一个数据例子,枚举了一些需求模型,并记录了SparkSQL实践的过程。 具体原理以及各个步骤原因没有熬述。

转载于:https://my.oschina.net/yjwxh/blog/609256

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值