现有一份CDN数据,该数据的格式为:
IP | 命中率 | 响应时间 | 请求时间 | 请求方法 | 请求URL | 请求协议 | 状态码 | 响应大小 | referer | 用户代理 |
---|
一条样例数据如下:
100.79.121.48 HIT 33 [15/Feb/2017:00:00:46 +0800] "GET http://cdn.v.abc.com.cn/videojs/video.js HTTP/1.1" 200 174055 "http://www.abc.com.cn/" "Mozilla/4.0+(compatible;+MSIE+6.0;+Windows+NT+5.1;+Trident/4.0;)"
处理需求:
- 需求1:计算独立IP数
- 需求2:统计每个视频独立IP数
- 需求3:统计一天中每个小时的流量
scala代码如下:
package com.dengdan.spark
import org.apache.spark.rdd.RDD
import org.apache.spark.{SparkConf, SparkContext}
import org.slf4j.LoggerFactory
import scala.util.matching.Regex
/**
* CDN流量统计
*/
object CdnStatics {
/**
* 日志对象,该程序中并未使用
*/
val logger = LoggerFactory.getLogger(CdnStatics.getClass)
/**
* IP地址模式
*/
val IPPattern = "((?:(?:25[0-5]|2[0-4]\\d|((1\\d{2})|([1-9]?\\d)))\\.){3}(?:25[0-5]|2[0-4]\\d|((1\\d{2})|([1-9]?\\d))))".r
/**
* 视频文件名模式
*/
val videoPattern = "([0-9]+).mp4".r
/**
* [15/Feb/2017:11:17:13 +0800] 匹配 2017:11 按每小时播放量统计
*/
val timePattern = ".*(2017):([0-9]{2}):[0-9]{2}:[0-9]{2}.*".r
/**
* 匹配http响应码和请求数据大小
*/
val httpSizePattern = ".*\\s(200|206|304)\\s([0-9]+)\\s.*".r
/**
* 主方法
*
* @param args
*/
def main(args: Array[String]): Unit = {
val sparkConf = new SparkConf().setAppName("CdnStatics").setMaster("local[*]")
val sc = new SparkContext(sparkConf)
//读入文件到内存
val data = sc.textFile("D:\\idea_workspace2020\\spark\\sparkcore\\sparkcore_cdn\\src\\main\\resources\\cdn.txt").cache()
println("------------------------------------------------------")
println(s"data的分区数 = ${data.partitions.size}") // 3
println("------------------------------------------------------")
//需求1:统计独立IP访问量TOP10
println("---------------------需求1:统计独立IP访问量TOP10---------------------------------")
ipStatics(data)
//需求2:统计每个视频独立IP数
println("---------------------需求2:统计每个视频独立IP数---------------------------------")
videoIpStatics(data)
//需求3:统计一天中每个小时间的流量
println("----------------------需求3:统计一天中每个小时间的流量--------------------------------")
flowOfHour(data)
println("-------------------------------------------------------------------------------")
sc.stop()
}
/**
* 需求1 统计独立IP访问量TOP10
*
* @param data 输入RDD
* @return
*/
def ipStatics(data: RDD[String]): Unit = {
//1.统计独立IP数
val ipNums = data.map(x => (IPPattern.findFirstIn(x).get, 1)).reduceByKey(_ + _).sortBy(_._2, false)
//2.输出IP访问量前10
ipNums.take(10).foreach(println)
//3.,打印独立IP数
println("独立IP的个数:" + ipNums.count())
}
/**
* 需求2:统计每个视频独立IP数
*
* @param data
*/
def videoIpStatics(data: RDD[String]): Unit = {
//获取文件名与IP的元组
def getFileNameAndIp(line: String): (String, String) = {
(videoPattern.findFirstIn(line).mkString, IPPattern.findFirstIn(line).mkString)
}
data.filter(x => x.matches(".*([0-9]+)\\.mp4.*")).map(x => getFileNameAndIp(x)).groupByKey().map(x => (x._1, x._2.toList.distinct))
.sortBy(_._2.size, false).take(10).foreach(x => println("视频:" + x._1 + "独立IP数:" + x._2.size))
}
/**
* 需求3:统计一天中每个小时间的流量
*
* @param data
* @return
*/
def flowOfHour(data: RDD[String]): Unit = {
def isMatch(pattern: Regex, str: String): Boolean = {
str match {
case pattern(_*) => true
case _ => false
}
}
//获取日志中小时和http 请求体大小
def getTimeAndSize(line: String) = {
var res = ("", 0L)
try {
val httpSizePattern(code, size) = line
val timePattern(year, hour) = line
res = (hour, size.toLong)
} catch {
case ex: Exception => ex.printStackTrace()
}
res
}
//统计一天中每个小时的流量
data.filter(x => isMatch(httpSizePattern, x)).filter(x => isMatch(timePattern, x)).map(x => getTimeAndSize(x)).groupByKey()
.map(x => (x._1, x._2.sum)).sortByKey().foreach(x => println(x._1 + "时 CDN流量=" + x._2 / (1024 * 1024 * 1024) + "G"))
}
}
运行结果:
------------------------------------------------------
data的分区数 = 3
------------------------------------------------------
---------------------需求1:统计独立IP访问量TOP10---------------------------------
(114.55.227.102,9348)
(220.191.255.197,2640)
(115.236.173.94,2476)
(183.129.221.102,2187)
(112.53.73.66,1794)
(115.236.173.95,1650)
(220.191.254.129,1278)
(218.88.25.200,751)
(183.129.221.104,569)
(115.236.173.93,529)
独立IP的个数:43649
---------------------需求2:统计每个视频独立IP数---------------------------------
视频:141081.mp4独立IP数:2393
视频:140995.mp4独立IP数:2050
视频:141027.mp4独立IP数:1784
视频:141090.mp4独立IP数:1702
视频:141032.mp4独立IP数:1528
视频:89973.mp4独立IP数:1523
视频:141080.mp4独立IP数:1425
视频:141035.mp4独立IP数:1321
视频:141082.mp4独立IP数:1272
视频:140938.mp4独立IP数:816
----------------------需求3:统计一天中每个小时间的流量--------------------------------
16时 CDN流量=45G
00时 CDN流量=14G
08时 CDN流量=43G
01时 CDN流量=3G
17时 CDN流量=44G
02时 CDN流量=5G
09时 CDN流量=52G
03时 CDN流量=3G
18时 CDN流量=45G
04时 CDN流量=3G
10时 CDN流量=61G
05时 CDN流量=4G
19时 CDN流量=51G
06时 CDN流量=11G
11时 CDN流量=45G
07时 CDN流量=22G
20时 CDN流量=55G
12时 CDN流量=46G
21时 CDN流量=53G
13时 CDN流量=51G
14时 CDN流量=55G
15时 CDN流量=45G
22时 CDN流量=42G
23时 CDN流量=25G
-------------------------------------------------------------------------------
Process finished with exit code 0