現有一份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