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)
}
}