Spark summer-framework

1.1 框架设计原理

​ 框架设计思想可以采取两种模式,一种是MVC,另外一种是三层架构,由于我们这里没有页面展示的需求,所以我们暂时采取三层架构的方式。

  1. .三层架构的概念

    1. Controller:控制层,封装调度作用,数据的流转过程
    2. Service: 服务层,封装实际的计算逻辑
    3. DAO :Data Access Object,数据访问对象,专门用于和一些关系型数据互相访问,用来和数据源的连接
  2. .调用的顺序
    在这里插入图片描述

  3. .架构中一些其他的内容

    1. bean : 用来封装一个bean类,对数据的一些封装,采用样例类,声明在包对象中
    2. helper:辅助类,如累加器类
    3. Apllication : 应用程序,主程序
    4. Util : 工具类

1.2 框架搭建

在这里插入图片描述

1.2.1 Util

EnvUtils

– 如何实现三层框架共享数据呢?

  1. 实现原理:在当前线程中创建一个内存,将共享数据存放在这个内存中,这样三层架构均可以使用。
  2. 实现方式:
    a、在线程中一直就保留着可以共享数据的空间
    b、JDK API 提供了一个工具类,可以直接访问这个空间
    c、只要调用这个工具类(ThreadLocal)将数据存入到共享数据中,也可以从这个内存中调用共享内存中的数据
  3. 具体的步骤:
    a、"创建"一个共享数据 : 案例如下:
    “private val scLocal = new ThreadLocal[SparkContext] "
    b、将共享数据"放进"共享空间中
    “scLocal.set(sc)”
    c、从当前线程的共享空间中"获取"共享数据
    “scLocal.get()”
    d、将共享数据从共享空间中"清除”
    “scLocal.remove()”
package com.ifeng.summer.foramework.util

import org.apache.spark.{SparkConf, SparkContext}

object EnvUtils {

  // 创建一个共享数据
  private val scLocal = new ThreadLocal[SparkContext]

  //获取环境对象
  def getEnv() = {

    //从当前线程的共享空间中获取环境对象
    var sc: SparkContext = scLocal.get()

    if (sc == null) {
      val sparkConf: SparkConf = new SparkConf().setMaster("local[*]").setAppName("SparkApplication")
      sc = new SparkContext(sparkConf)
      scLocal.set(sc)

    }
    sc

  }

  // 清除对象
  def clean() = {
    getEnv().stop()

    // 将共享内存中的数据清除
    scLocal.remove()


  }

}

PropertiesUtil

–动态获取连接的资源,将需要连接的资源配置文件放置在配置文件中,从配置文件中读取连接需要的资源,这样,当我们需要更换连接的资源时,只要修改配置文件即可。

这种思想是非常重要的,类似hadoop的MR,将资源和计算分离开,做资源的调度,扩展起来就非常的方便。

package com.ifeng.summer.foramework.util

import java.util.ResourceBundle

object PropertiesUtil {

  //绑定配置文件
  val summer: ResourceBundle = ResourceBundle.getBundle("summers")

  def getValue(key: String): String = {

    //传入一个key,返回一个value
    summer.getString(key)

  }


}

1.2.2 core

TApplication

package com.ifeng.summer.foramework.core
import java.net.{InetAddress, ServerSocket, Socket}

import com.ifeng.summer.foramework.util.{EnvUtils, PropertiesUtil}
import org.apache.spark.{SparkConf, SparkContext}


trait TApplication {

  var envdata: Any = null
  //第一步:初始化环境

  def start(t: String)(op: => Unit) = {

    if (t == "Socket") {
      envdata = new Socket(PropertiesUtil.getValue("serverhost")
        , PropertiesUtil.getValue("serverport").toInt)
    } else if (t == "ServerSocket") {
      envdata = new ServerSocket(PropertiesUtil.getValue("serverport").toInt)
    } else if (t == "Spark") {
      envdata = EnvUtils.getEnv()
    }

    //业务逻辑
    try {
      op
    } catch {
      case ex: Exception => println("op执行失败,原因是:" + ex.getMessage)
    }

    //环境关闭
    if (t == "ServerSocket") {
      val ServerSocket = envdata.asInstanceOf[ServerSocket]
      if (!ServerSocket.isClosed) {
        ServerSocket.close()
      }
    } else if (t == "Socket") {
      val socket = envdata.asInstanceOf[Socket]
      if (!socket.isClosed) {
        socket.close()
      }
    } else if (t == "Spark") {
      EnvUtils.clean()
    }

  }

}

TController

package com.ifeng.summer.foramework.core

trait TController {

  //执行控制
  def execute() : Unit

}

TService

package com.ifeng.summer.foramework.core

trait TService {

  //数据分析
  def analysis() : Any

  //数据分析
  def analysis(data :Any) : Any

}

TDAO

package com.ifeng.summer.foramework.core

import com.ifeng.summer.foramework.util.EnvUtils
import org.apache.spark.rdd.RDD

trait TDAO {

  def readFile(path :String) ={

    val fileRDD: RDD[String] = EnvUtils.getEnv().textFile(path)
    fileRDD

  }

}

封装

1 更改trait
object WordCountApplication extends  App { //extend App 不用main直接运行

由于extend了App
class Application 无法再次extend
改成 trait TApplication

object WordCountApplication extends  App with TApplication



```java
trait TApplication


    if (t == "Socket") {
      envdata = new Socket(
        PropertiesUtil.getValue("serverhost"),
        PropertiesUtil.getValue("serverport").toInt)
    } else if (t == "ServerSocket") {
      envdata = new ServerSocket(PropertiesUtil.getValue("serverport").toInt)
//    } else if (t == "Spark") {
//      envdata = EnvUtils.getEnv()
    } else if (t == "Spark") {
      val sparkConf = new SparkConf().setAppName("SparkApplication").setMaster("local")
      envdata = new SparkContext(sparkConf)
    }




    // TODO 3 环境关闭
    if (t == "ServerSocket") {
      val ServerSocket = envdata.asInstanceOf[ServerSocket]
      if (!ServerSocket.isClosed) {
        ServerSocket.close()
      }
    } else if (t == "Socket") {
      val socket = envdata.asInstanceOf[Socket]
      if (!socket.isClosed) {
        socket.close()
      }
    } else if (t == "Spark") {
//      EnvUtils.clean()
      val sc = envdata.asInstanceOf[SparkContext]
      sc.stop()
    }


2 添加依赖

需要在WordCountApplication  中添加如下依赖

```java
            <dependency>
                <groupId>org.ifeng</groupId>
                <artifactId>summer_framework</artifactId>
                <version>1.0</version>
            </dependency>
3 WordCountApplication

1 在start 中写逻辑业务
2 val sc = envdata.asInstanceOf[SparkContext] //Tapplication 中copy

object WordCountApplication extends  App with TApplication{ //extend App 不用main直接运行

  start("Spark"){


    val sc = envdata.asInstanceOf[SparkContext] //Tapplication 中copy

    val rdd1 = sc.parallelize(List("a","b","c","d","e","a"))

    val newRDD: RDD[Map[String, Int]] = rdd1.map(word => Map[String, Int]((word, 1)))

    val reduceWC: Map[String, Int] = newRDD.reduce(
      (map1, map2) => {
        map1.foldLeft(map2)(
          (map, kv) => {
            val word = kv._1
            val count = kv._2
            map.updated(word, map.getOrElse(word, 0) + count)
          }
        )
      }
    )

  reduceWC.foreach(println)
  }

三层架构

在这里插入图片描述

线程中的一块
在这里插入图片描述
在三层架构中,可以在线程中开辟一块空间,共享数据的内存空间,广播变量的思想

package com.ifeng.summer.foramework.util

import org.apache.spark.{SparkConf, SparkContext}

object EnvUtils {

  // 创建一个共享数据
  private val scLocal = new ThreadLocal[SparkContext]

  //获取环境对象
  def getEnv() = {

    // TODO 从当前线程的共享空间中获取环境对象
    var sc: SparkContext = scLocal.get()

    if (sc == null) {
      // TODO 如果获取不到环境变量,那么创建新的环境变量,保存到内存中
      val sparkConf: SparkConf = new SparkConf().setMaster("local[*]").setAppName("SparkApplication")
      sc = new SparkContext(sparkConf)
      // 保存到共享内存中
      scLocal.set(sc)

    }
    sc

  }

  // TODO 清除对象
  def clean() = {
    getEnv().stop()

    // 将共享内存中的数据清除掉
    scLocal.remove()


  }

}

在这里插入图片描述

在这里插入图片描述

/*
*   WordCont 控制器
* */


class WordCountController extends TController{

  //Controller 中应该走向Service
  private val WordCountService = new WordCountService

  override def execute(): Unit = {

    //调用WordCountService的逻辑
    WordCountService.analysis()
  }
}

/*
*   数据分析
* */


class WordCountService extends TService{

  //Service 应该访问DAO
  private val WordCountDAO = new WordCountDAO


  override def analysis(): Any = {
    null
  }

  override def analysis(data: Any): Any = ???
}
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

oifengo

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值