spark-9.sparkcore_6_實例練習

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

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章