Spark:Task not serializable

package HomeWork.Core_logAnaly
import org.apache.spark.{SparkConf, SparkContext}

/***
  * User:yunfei
  * Date:22/10/23
  * Description:
  * 日志文件格式:
  * 域名 流量 资源  ip  访问时间
  *
  * www.zhibo8.com	3040	https://www.zhibo8.com/video/music/djembe.pdf	10.0.0.1	[2017-07-13 19:19:00]
  *
  * */

class LogAnalyzer(fileName: String) extends Serializable {
              val lines=sc.textFile(fileName)
  @transient  val sc=createLocalSparkContext()
  /**
    * (1)task not serializable 出现“task not serializable"这个错误,一般是因为在map、filter等的参数使用了外部的变量,
    * 但是这个变量不能序列化(比如上面这个SparkContext)。特别是当引用了某个类(经常是当前类)的
    * (2)当引用了某个类(经常是当前类)的成员函数或变量时,会导致这个类的所有成员(整个类)都需要支持序列化。虽然许多情形下,当前类使用了“extends Serializable”声明支持序列化,
    * 但是由于某些字段不支持序列化,仍然会导致整个类序列化时出现问题,最终导致出现Task未序列化问题。
    * (3)解决办法:要么就直接在
    * 如果程序依赖的值相对固定,可取固定的值,或定义在map、filter等操作内部,或定义在scala
    * object对象中(类似于Java中的static变量)
    * 如果依赖值需要程序调用时动态指定(以函数参数形式),则在map、filter等操作时,可不直接引用该成员变量,
    * 而是在类似上面例子的getResult函数中根据成员变量的值重新定义一个局部变量,这样map等算子就无需引用类的成员变量。
    */

  def createLocalSparkContext()={
      val sparkconf=new SparkConf().setMaster("local[2]").setAppName("LogAnalyzer")
      new SparkContext(sparkconf)
  }
  def stopSparkContext()={
      sc.stop()
 }

  //TODO..,求每个域名的流量
  /**
    *(1)获取1,2字段
    *(2)按域名分组
    *(3)分组求和reduceBykey(_+_)
  **/
  def prinTrafficByDomain()={
    lines.map(x=>{
      val recod=x.split("\t")
      var traffic=0L  //这里用val要报错,好像是因为var才能tolong
      try {
        traffic=recod(LogAnalyzer.TRAFFIC_IDX).trim.toLong   //有问题就搞为0,例如遇到脏数据,比如是字符串(字符串tolong会有问题啊 ),就变为0
      }
      catch {
case e:Exception=>traffic=0L  //
      }
      (recod(0),traffic)
    }).reduceByKey(_+_).sortBy(_._2,false).foreach(println)
//回顾reduceBykey,它是将相同的key(域名),values(流量)相加,sortBy排序,false表示降序,true表示升序。
  }

  //TODO...求省份的访问次数
  /**
    * (1)获取ip
    * (2)改造数据结构,每个key赋值1,变为(省份,1)
    */
  def printByProvince()={
    lines.map(x=>{
      val record=x.split("\t")
      var province=""
      try {
        province=record(LogAnalyzer.IP_IDX).trim
      }
      catch {
        case e:Exception =>province=""
      }
      (province,1)
    }).reduceByKey(_+_).sortBy(_._2,false).take(40).foreach(println)
  }

  //TODO..求每个域名下访问次数最多的文件资源
  /**
    * (1)数据处理,由下面的资源文件的定义可知,需要去掉https://www.youku.com
    * https://www.youku.com/video/music/bass.mp4?key1=value1xxxxxxxx(后面x表示不同的访问同一个资源)
    * /video/music/bass.mp4 <-- 资源文件定义
    * (2)getResource方法取出资源文件。
    * (3)需求分析,首先是域名下的资源,所以数据结构应该是(域名,资源),其次需要求TopN的,所以应该是
    * ((域名,资源),1)
    * */
  def printMaxResourceByDomain()={
    lines.map(x=>{
      val record=x.split("\t")
      ((record(LogAnalyzer.DOMAIN_IDX),getResource(record(2))),1)
    })
  }.reduceByKey(_+_).groupBy(_._1._1)//xcz
    .mapValues(_.toList.sortBy(_._2).reverse.take(10)).map(_._2).foreach(println)



  //TODO...改造数据结构,得到资源文件
  def getResource(url:String)={
    val pathTemp=url.replaceFirst("//","")
    var pathIndex=pathTemp.indexOf("/")
    var path=""
    if (pathIndex != -1){
      path=pathTemp.substring(pathIndex)
      pathIndex=path.indexOf("?")
      if (pathIndex != -1){
        path= path.substring(0,pathIndex)
      }
      path
    }
  }
}
object LogAnalyzer{
  val APP_NAME = "LogAnalyzer"
  val DOMAIN_IDX = 0 //域名
  val TRAFFIC_IDX = 1 //流量
  val RESOURCE_IDX = 2 //资源
  val IP_IDX = 3 //ip
  val GET_TIME = 4 //访问时间
  def apply(fileName: String): LogAnalyzer = new LogAnalyzer(fileName)

}

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值