Spark项目通用开发框架

每个公司内部都有一套自己的架子,一般新人来了就直接在已有的架子上开发业务。
以下仅仅作为记录下自己使用的架子,可以根据需要参考。

1. 大数据项目结构

项目的整体组织结构
在这里插入图片描述


目录说明
annotation自定义注解Runner和Task。
app用来放整个项目的各个任务。
test1和test2是具体开发的业务任务。
baseBaseRunner和BaseTask是两个基础类
enums用来定义任务的别名
FeatureContextApp主类在目录中的位置保持不变,如果移动,会影响扫描task和Runner

2. 类说明

2.1 公共接口类

package com.king.ml.base

import com.king.ml.enums.TaskNameEnum
import org.apache.spark.SparkConf
import org.apache.spark.internal.Logging
import org.apache.spark.sql.SparkSession
import org.joda.time.DateTime
import org.springframework.util.StopWatch

import scala.util.{Failure, Success, Try}

trait BaseTask extends Logging with Serializable {

  def taskName: TaskNameEnum.Value
  def initConf(sparkConf: SparkConf = new SparkConf()): SparkConf = sparkConf
  var runtime: StopWatch = _


  def around(implicit spark: SparkSession, currDate: DateTime = DateTime.now): Unit = {
    before
    Try {
      Class.forName(spark.conf.get("task.runner"))
        .newInstance()
        .asInstanceOf[BaseRunner]
        .run
    } match {
      case Success(_) => after
      case Failure(_) => afterThrowException
    }

  }


  private def before(implicit spark: SparkSession, currDate: DateTime): Unit = {

    val taskName = spark.conf.get("task.runner")
    println("开始执行任务 ...["+taskName+"]")
    runtime = new StopWatch(taskName)
    runtime.start(taskName)

  }

  private def after(implicit spark: SparkSession, currDate: DateTime): Unit = {
    val taskName = spark.conf.get("task.runner")
    runtime.stop()
    println("任务执行结束 ...["+ taskName+"],共耗时:" + runtime.getTotalTimeSeconds +"秒")
  }

  private def afterThrowException(implicit spark: SparkSession, currDate: DateTime): Unit = {
    val taskName = spark.conf.get("task.runner")
    runtime.stop()
    println("任务执行异常 ...[" + taskName + "],共耗时:" + runtime.getTotalTimeSeconds + "秒")
  }
}


通过一个公共的接口记录每个任务执行的具体日志信息。

在这里插入图片描述

2.2 TaskNameEnum指定每个任务的名称

  
object TaskNameEnum extends Enumeration {

  def getEnumType(source:String):TaskNameEnum.Value = {
    val values =TaskNameEnum.values.toList.filter(_.toString.toUpperCase == source.toUpperCase)
    values.length match {
      case 1 => values.head
      case _ => throw new IllegalArgumentException("该任务不存在")
    }
  }

  val Test1 = Value("ods.ods_test1")
  val Test2 = Value("ods.ods_test2")

}

这里的Test1和Test2表示任务的名称。

2.3 TaskRunner中编写任务的业务逻辑

package com.king.ml.app.test1

import com.king.ml.annotation.Runner
import com.king.ml.base.BaseRunner
import com.king.ml.enums.TaskNameEnum
import org.apache.spark.sql.SparkSession
import org.joda.time.DateTime


@Runner
class Test1TaskRunner extends BaseRunner{
  override def taskName: TaskNameEnum.Value = TaskNameEnum.Test1

  override def run(implicit spark: SparkSession, currDate: DateTime): Unit = {
    val cnt = spark.table("ods.ods_test1").count()
    println("===>总记录数为:")
    println("===>" + cnt)

  }
}

3. 任务执行脚本

在执行脚本中,任务主程序名不需要改变,只需要给任务传参枚举中任务名的值即可。

spark-submit \
--name 'test-ml' \
--master yarn \
--deploy-mode client \
--conf spark.port.maxRetries=100 \
--conf spark.dynamicAllocation.enabled=false \
--conf spark.yarn.executor.memoryOverhead=5120 \
--queue root.production \
--driver-memory 2g  --num-executors 2 --executor-memory 2g --executor-cores 1 \
--class com.king.ml.app.FeatureContextApp \
./ml/ml-demo.jar "ods.ods_test1"
  • 9
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

硅谷工具人

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

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

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

打赏作者

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

抵扣说明:

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

余额充值