spark基于源码进行离线任务监控

import javax.mail.Authenticator;
import javax.mail.Message.RecipientType;
import javax.mail.PasswordAuthentication;
import javax.mail.Session;
import javax.mail.Transport;
import javax.mail.internet.InternetAddress;
import javax.mail.internet.MimeMessage;
import java.util.Properties;

/**

  • Created by angel
    /
    public class MailUtil {
    /
    *

    • args[0]:接收人邮箱,以‘,’连接
    • args[1]:邮件标题
    • args[2]:邮件内容
    • @param args
    • @throws Exception
      */

    //问题 Properties这个怎么获取 有一个DataStruct类
    public static void sendMail(Properties props, String[] args) throws Exception{

     if(args.length != 3){
         System.out.println("请输入三个参数:\nargs[0]:接收人邮箱,以‘,’连接;\nargs[1]:邮件标题;\nargs[2]:邮件内容。");
         return;
     }
     String reciveEmails = args[0];
     String title = args[1];
     String content = args[2];
    
     // 构建授权信息,用于进行SMTP进行身份验证
     Authenticator authenticator = new Authenticator() {
         @Override
         protected PasswordAuthentication getPasswordAuthentication() {
             // 用户名、密码
             String userName = "####@163.com";
             String password = "qwe123";
             return new PasswordAuthentication(userName, password);
         }
     };
     // 使用环境属性和授权信息,创建邮件会话
     Session mailSession = Session.getInstance(props, authenticator);
     // 创建邮件消息
     MimeMessage message = new MimeMessage(mailSession);
     // 设置发件人
     InternetAddress form = new InternetAddress(
             "###@163.com");
     message.setFrom(form);
     // 设置收件人  "xxx@xxx.com,xxx@xxx.com,xxx@xxx.com"
     InternetAddress[] internetAddressTo = new InternetAddress().parse(reciveEmails);
     message.setRecipients(RecipientType.TO, internetAddressTo);
    
     // 设置邮件标题
     message.setSubject(title);
     // 设置邮件的内容体
     message.setContent(content, "text/html;charset=UTF-8");
     // 发送邮件
     Transport.send(message);
    

    }

    public static void main(String[] args) {
    Properties properties = new Properties();
    properties.setProperty(“mail.host”,“smtp.163.com”);
    properties.setProperty(“mail.transport.protocol”, “smtp”);
    properties.setProperty(“mail.smtp.auth”,“true”);
    String[] str = new String[]{"###@163.com", “spark任务监控” , “测试==============”};
    try {
    MailUtil.sendMail(properties , str);
    } catch (Exception e) {
    e.printStackTrace();
    }
    }
    }

import java.util
import java.util.Properties

import org.codehaus.jettison.json.JSONObject

/**

  • Created by angel

*/
object DataStruct {

/*转JSON/
def convertJson(tuples:(String , Any)*):JSONObject ={
tuples.foldLeft(new JSONObject()){
case (obj , (k,v)) => obj.put(k , v)
obj
}
}

/*转map/
def convertMap(tuples:(String , String)*): java.util.HashMap[String , String] ={
tuples.foldLeft(new util.HashMapString , String){
case (map , (k,v)) => map.put(k,v)
map
}
}

/*转properties/
def convertProp(tuples:(String , String)*):Properties = {
tuples.foldLeft(new Properties()){
case (prop , (k,v)) => prop.setProperty(k,v)
prop
}
}
}

import java.util.Properties
import javafx.scene.chart.NumberAxis.DefaultFormatter

import com.cartravel.common.MailUtil
import com.cartravel.loggings.Logging
import com.cartravel.utils.{DataStruct, GlobalConfigUtils}
import org.apache.spark._
import org.apache.spark.scheduler.{SparkListener, SparkListenerTaskEnd}
import org.json4s.DefaultFormats
import org.json4s.jackson.Json
import redis.clients.jedis.Jedis

/**

  • Created by angel
    */
    class SparkAppListener(conf:SparkConf) extends SparkListener with Logging{
    //获取redis的配置
    val defaultRedisConfig = “jedisConfig.properties”
    //redis的机器
    val jedis = new Jedis(“cdh1”)

override def onTaskEnd(taskEnd: SparkListenerTaskEnd): Unit = {
/**
* 1、taskMetrics 监控框架的性能分析
* 2、shuffle
* 3、task运行(input output的信息)
* 4、taskInfo
* */
//插入到那个库
jedis.select(2)
//获取当前时间
val currentTimestamp = System.currentTimeMillis()
//获取metrics
val metrics = taskEnd.taskMetrics

val taskMetricsMap = scala.collection.mutable.HashMap(
  "executorDeserializeTime" -> metrics.executorDeserializeTime ,//executor的反序列化时间
  "executorDeserializeCpuTime" -> metrics.executorDeserializeCpuTime ,//executor的反序列化的 cpu时间
  "executorRunTime" -> metrics.executorRunTime ,//executoor的运行时间
  "resultSize" -> metrics.resultSize , //结果集大小
  "jvmGCTime" -> metrics.jvmGCTime ,  //jvm GC时间
  "resultSerializationTime" -> metrics.resultSerializationTime , //result的序列化时间
  "memoryBytesSpilled" -> metrics.memoryBytesSpilled , //内存益写
  "diskBytesSpilled" -> metrics.diskBytesSpilled , //益写到磁盘是多少
  "peakExecutionMemory" -> metrics.peakExecutionMemory//executor的最大内存
)
//实现一个key
val taskMetricsKey = s"taskMetrics_${currentTimestamp}"
//直接使用map报错,所以使用json进行处理
jedis.set(taskMetricsKey , Json(DefaultFormats).write(taskMetricsMap))
//指定key的生病周期
jedis.expire(taskMetricsKey , 3600)


//####################shuffle监控#######
//shuffle 读写监控
val shuffleReadMetrics = metrics.shuffleReadMetrics
val shuffleWriteMetrics = metrics.shuffleWriteMetrics

val shuffleMap = scala.collection.mutable.HashMap(
  "remoteBlocksFetched" -> shuffleReadMetrics.remoteBlocksFetched ,//shuffle远程拉取数据块
  "localBlocksFetched" -> shuffleReadMetrics.localBlocksFetched ,
  "remoteBytesRead" -> shuffleReadMetrics.remoteBytesRead , //shuffle远程读取的字节数
  "localBytesRead" -> shuffleReadMetrics.localBytesRead ,
  "fetchWaitTime" -> shuffleReadMetrics.fetchWaitTime ,
  "recordsRead" -> shuffleReadMetrics.recordsRead , //shuffle读取的记录总数
  "bytesWritten" -> shuffleWriteMetrics.bytesWritten , //shuffle写的总大小
  "recordsWritte" -> shuffleWriteMetrics.recordsWritten , //shuffle写的总记录数
  "writeTime" -> shuffleWriteMetrics.writeTime
)

val shuffleKey = s"shuffleKey${currentTimestamp}"
jedis.set(shuffleKey , Json(DefaultFormats).write(shuffleMap))
jedis.expire(shuffleKey , 3600)


//####################input   output   写入和写出的字节数#######
val inputMetrics = metrics.inputMetrics
val outputMetrics = metrics.outputMetrics
val input_output = scala.collection.mutable.HashMap(
  "bytesRead" ->  inputMetrics.bytesRead ,//读取的大小
  "recordsRead" -> inputMetrics.recordsRead , //总记录数
  "bytesWritten" -> outputMetrics.bytesWritten ,//写的大小
  "recordsWritten" -> outputMetrics.recordsWritten//写的总大小
)
val input_outputKey = s"input_outputKey${currentTimestamp}"
jedis.set(input_outputKey , Json(DefaultFormats).write(input_output))
jedis.expire(input_outputKey , 3600)


//####################taskInfo#######
val taskInfo = taskEnd.taskInfo

val taskInfoMap = scala.collection.mutable.HashMap(
  "taskId" -> taskInfo.taskId ,
  "host" -> taskInfo.host ,
  "speculative" -> taskInfo.speculative , //推测执行
  "failed" -> taskInfo.failed ,//失败的
  "killed" -> taskInfo.killed ,//是否被杀死
  "running" -> taskInfo.running//是否在运行
)


val taskInfoKey = s"taskInfo${currentTimestamp}"
jedis.set(taskInfoKey , Json(DefaultFormats).write(taskInfoMap))
jedis.expire(taskInfoKey , 3600)

//如果taskInfo失败 则应该去报警
//####################邮件告警#######
if(taskInfo != null &&  taskEnd.stageAttemptId != -1){
  val reason: TaskEndReason = taskEnd.reason
  val errmsg = reason match{
    case kill : TaskKilledException => Some(kill.getMessage)
    case e: TaskFailedReason => Some(e.toErrorString)
    case e: ExceptionFailure => Some(e.toErrorString)
    case e:Exception => Some(e.getMessage)
    case _ => None
  }

  if(errmsg.nonEmpty){
    if(conf.getBoolean("enableSendEmailOnTaskFail" , false)){
      val args = Array(GlobalConfigUtils.getProp("mail.host") , s"spark监控任务:${reason}" , errmsg.get)
      val prop: Properties = DataStruct.convertProp(
        ("mail.host", GlobalConfigUtils.getProp("mail.host")),
        ("mail.transport.protocol", GlobalConfigUtils.getProp("mail.transport.protocol")),
        ("mail.smtp.auth", GlobalConfigUtils.getProp("mail.smtp.auth"))
      )
      
      MailUtil.sendMail(prop , args)
    }
  }

}

}
}

resource下的fairscheduler.xml


FAIR
10
10


FAIR
4
3


FAIR
1
3


FAIR
1
3

Spark引擎
import com.cartravel.bean._
import com.cartravel.utils.GlobalConfigUtils
import org.apache.spark.SparkConf
import org.apache.spark.sql.SparkSession

/**

  • Created by angel
    */
    object SparkEngine {
    def getSparkConf():SparkConf = {

    val sparkConf: SparkConf = new SparkConf()
    .set(“spark.worker.timeout” , GlobalConfigUtils.getProp(“spark.worker.timeout”))
    .set(“spark.cores.max” , GlobalConfigUtils.getProp(“spark.cores.max”))
    .set(“spark.rpc.askTimeout” , GlobalConfigUtils.getProp(“spark.rpc.askTimeout”))
    .set(“spark.task.maxFailures” , GlobalConfigUtils.getProp(“spark.task.maxFailures”))
    .set(“spark.driver.allowMutilpleContext” , GlobalConfigUtils.getProp(“spark.driver.allowMutilpleContext”))
    .set(“spark.serializer”, “org.apache.spark.serializer.KryoSerializer”)
    .set(“spark.sql.adaptive.enabled” , “true”)
    .set(“spark.streaming.kafka.maxRatePerPartition” , GlobalConfigUtils.getProp(“spark.streaming.kafka.maxRatePerPartition”))
    .set(“spark.streaming.backpressure.enabled” , GlobalConfigUtils.getProp(“spark.streaming.backpressure.enabled”))
    .set(“spark.streaming.backpressure.initialRate” , GlobalConfigUtils.getProp(“spark.streaming.backpressure.initialRate”))
    .set(“spark.streaming.backpressure.pid.minRate”,“10”)
    .set(“enableSendEmailOnTaskFail”, “true”)
    .set(“spark.buffer.pageSize” , “16m”)
    // .set(“spark.streaming.concurrentJobs” , “5”)
    .set(“spark.driver.host”, “localhost”)
    .setMaster(“local[*]”)
    .setAppName(“query”)
    sparkConf.set(“spark.speculation”, “true”)
    sparkConf.set(“spark.speculation.interval”, “300”)
    sparkConf.set(“spark.speculation.quantile”,“0.9”)
    sparkConf.set(“spark.streaming.backpressure.initialRate” , “500”)
    sparkConf.set(“spark.streaming.backpressure.enabled” , “true”)
    sparkConf.set(“spark.streaming.kafka.maxRatePerPartition” , “5000”)
    sparkConf.registerKryoClasses(
    Array(
    classOf[OrderInfo],
    classOf[Opt_alliance_business],
    classOf[DriverInfo],
    classOf[RegisterUsers] ,
    classOf[Reservation]
    )
    )
    sparkConf
    }
    def getSparkSession(sparkConf:SparkConf):SparkSession = {
    val sparkSession: SparkSession = SparkSession.builder()
    .config(sparkConf)
    //调度模式
    .config(“spark.scheduler.mode”, “FAIR”)
    .config(“spark.executor.memoryOverhead”, “512”)//堆外内存
    //邮件告警
    .config(“enableSendEmailOnTaskFail”, “true”)
    .config(“spark.extraListeners”, “com.cartravel.spark.SparkAppListener”)//TODO 离线
    .enableHiveSupport() //开启支持hive
    .getOrCreate()
    sparkSession.sparkContext.setLocalProperty(“spark.scheduler.pool”, “n1”)
    sparkSession
    }
    }

jedisConfig.properties的配置文件
#jedisCluster连接配置

#redisCluster实例地址
servers = cdh1:6379
#连接redisCluster实例超时时间
connectionTimeout = 300000
#读写redisCluster实例超时时间
soTimeout = 300000
#连接redisCluster实例重试次数
maxAttempts = 6

#jedis连接池配置
#连接池最大连接数
maxTotal = 200
#获取连接池连接最大等待时间(毫秒)
maxWaitMillis = 15000
#最大空闲连接数
maxIdle = 50
#最小空闲连接数
minIdle = 10
#对拿到的connection进行validateObject校验
testOnBorrow = false
#从连接池获取不到连接则阻塞
blockWhenExhausted = true
#连接对象后进先出
lifo = true
#归还连接到池时测试连接
testOnReturn = false
#测试连接池空闲的连接
testWhileIdle = true
#测试连接池空闲连接的时间间隔,testWhileIdle=true时生效
timeBetweenEvictionRunsMillis = 30000
#监控数据-键标识
cluster.key.monitor.dataProcess = MONITOR_DP
#监控数据有效期-单位秒
cluster.exptime.monitor = 86400

import com.typesafe.config.ConfigFactory

/**

  • Created by angel
    */
    //获取参数的一个工具
    class GlobalConfigUtils {

private def conf = ConfigFactory.load()
def heartColumnFamily = “MM”
val getProp = (argv:String) => conf.getString(argv)
}

object GlobalConfigUtils extends GlobalConfigUtils

resource下的application.conf的配置
hdfs.host=“hdfs://node01:8020/hfile/”
mail.smtp.auth=“true”
mail.host=“smtp.163.com”
mail.smtp.port=“587”
mail.user="####@163.com"
mail.transport.protocol=“smtp”
#设置的秘钥
mail.password=“qwe123”

import java.util
import java.util.Properties

import org.codehaus.jettison.json.JSONObject

/**

  • Created by angel

*/
object DataStruct {

/*转JSON/
def convertJson(tuples:(String , Any)*):JSONObject ={
tuples.foldLeft(new JSONObject()){
case (obj , (k,v)) => obj.put(k , v)
obj
}
}

/*转map/
def convertMap(tuples:(String , String)*): java.util.HashMap[String , String] ={
tuples.foldLeft(new util.HashMapString , String){
case (map , (k,v)) => map.put(k,v)
map
}
}

/*转properties/
def convertProp(tuples:(String , String)*):Properties = {
tuples.foldLeft(new Properties()){
case (prop , (k,v)) => prop.setProperty(k,v)
prop
}
}
}

package com.cartravel.loggings

import org.slf4j.LoggerFactory

/**

  • Created by angel
    */

trait Logging {
lazy val logger = LoggerFactory.getLogger(this.getClass)

def trace(message: => Any): Unit = {
if (logger.isTraceEnabled) {
logger.trace(message.toString)
}
}

def debug(message: => Any): Unit = {
if (logger.isDebugEnabled) {
logger.debug(message.toString)
}
}

def info(message: => Any): Unit = {
if (logger.isInfoEnabled) {
logger.info(message.toString)
}
}

def warn(message: => Any): Unit = {
logger.warn(message.toString)
}

def warn(message: => Any, t: Throwable): Unit = {
logger.warn(message.toString, t)
}

def error(message: => Any, t: Throwable): Unit = {
logger.error(message.toString, t)
}

def error(message: => Any): Unit = {
logger.error(message.toString)
}
}

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值