Spark 2.x管理与开发-【Spark基础编程案例】案例二:创建自定义分区

一、需求

根据jsp文件的名字,将各自的访问日志放入到不同的分区文件

二、Scala代码实现

package coreExamples

import org.apache.spark.SparkConf
import org.apache.spark.SparkContext
import scala.collection.mutable.HashMap
import org.apache.spark.Partitioner

/**
 * Spark Core案例-2
 *   创建自定义分区-根据jsp名字分区
 */
object ZiDingYiFenQu {
  def main(args: Array[String]): Unit = {
    //创建SparkContext对象
    val conf = new SparkConf().setMaster("local").setAppName("ZiDingYiFenQu")
    val sc = new SparkContext(conf)
    /**
     * 读入日志解析
     * 192.168.88.1 - - [30/Jul/2017:12:54:42 +0800] "GET /MyDemoWeb/web.jsp HTTP/1.1" 200 239
     * (web.jsp,line)
     */
    val rdd1 = sc.textFile("D:/大数据高级资料及测试/Spark Core案例数据/localhost_access_log.2017-07-30.txt")
      .map(
        line => {
          //一、解析字符串

          //1.得到两个引号之间的东西
          val index1 = line.indexOf("\"")
          val index2 = line.lastIndexOf("\"")
          //GET /MyDemoWeb/web.jsp HTTP/1.1
          val line1 = line.substring(index1 + 1, index2)

          //2.得到两个空格之间的东西
          val index3 = line1.indexOf(" ")
          val index4 = line1.lastIndexOf(" ")
          // /MyDemoWeb/web.jsp
          val line2 = line1.substring(index3, index4)

          //3.得到得到最后一个/之后的字符串-jsp名字
          //web.jsp
          val jspName = line2.substring(line2.lastIndexOf("/") + 1)

          //4.返回jsp名字和所在的整句数据信息
          (jspName, line)
        })
    //取出jsp的名字并去重
    //(web.jsp,192.168.88.1 - - [30/Jul/2017:12:54:42 +0800] "GET /MyDemoWeb/web.jsp HTTP/1.1" 200 239)
    val jspList = rdd1.map(_._1).distinct().collect()
    //二、自定义分区规则-新建一个类
    val myPartitioner = new MyWebPartitioner(jspList)
    val rdd3 = rdd1.partitionBy(myPartitioner)
    //输出-最终文件夹不能已存在
    rdd3.saveAsTextFile("D:\\大数据高级资料及测试\\Spark Core案例数据\\test")
    sc.stop()
  }
}
/**
 * 自定义分区规则-新建一个类
 *jspList:是一个含有所有jsp名字的Array
 */
class MyWebPartitioner(jspList: Array[String]) extends Partitioner {
  //定义一个集合来保存分区的条件
  val partitionMap = new HashMap[String, Int]()
  var partID = 0 //分区号
  for (jsp <- jspList) {
    partitionMap.put(jsp, partID)
    partID += 1
  }

  //返回总共有多少个分区
  def numPartitions: Int = partitionMap.size

  //根据名字返回对应的分区
  //如果取到了就返回,否则就返回一个0
  def getPartition(key: Any): Int = partitionMap.getOrElse(key.toString(), 0)
}

三、结果

例如:part-00000文件中的内容:只包含了web.jsp的访问日志

 

 

博客园  ©  2004-2025
浙公网安备 33010602011771号 浙ICP备2021040463号-3