一直忙于工作,在平淡中时间慢慢流逝,想尝试着写点什么,但不知道从何下手, 看到网上有很多文章写的很不错,很羡慕能把自己的想法写出来然
后分享给大家的那些技术达人,把书本上的知识从理解到应用实际工作中,不断的学习、沉淀才能不断的进步,努力成为你想要成为的那个人。
从毕业到现在一直从事Java后台开发工作,阴差阳错的接触到计算广告这个占互联网大部分收入的行业,平时的工作主要是负责后台业务的开发以及对
广告效果数据(广告的曝光、点击、下载、活跃用户等)、性能数据(SDK埋点数据)进行实时统计与报表展示。广告效果数据是用Spark
Streaming进行准实时统计的,性能数据是利用Hadoop进行离线计算统计的(计算广告涉及的知识面较为广泛有兴趣的同学可以拜读一下刘鹏老师的
计算广告学)。因为Spark 集群资源较为紧张导致Spark Streaming准时任务会出现计算延时,主备异常切换的时候导致Spark Streaming出现重启失
败等,如果不能及时感知到这些因素,那么将会给用户带来不好的体验,给公司带来不必要的损失。为了能自动监控到这些变化,并能及时感知进行
相应的处理,在工作之余利用python写了一个任务监控脚本。该脚本根据任务名称监控任务是否正常运行,以及是否出现计算延时,如果不正常的时
候自动发送邮件进行通知。哈哈、第一次写博客废话较多,下面就直接上脚本:
#!/usr/bin/env python
#-*- coding:utf-8 -*-
import re
import datetime
import urllib2
import traceback
from bs4 import BeautifulSoup
from email.mime.text import MIMEText
import smtplib
from email.header import Header
mail_to_list=["xx@xx.com"] #邮件收件人,多个用逗号隔开
mail_host="192.31.15.117" #邮件服务器
mail_user="xx@xx.com" #邮箱账户名(建议用公司内部邮箱,以免其他邮箱泄露服务器机器信息)
#线上环境spark页面
spark_url_master_1 = "http://192.168.141.145:8090/" #spark集群主服务地址
spark_url_master_2 = "http://192.168.141.144:8090/" #spark集群备服务地址
task_names = ["AD_SSP_STAT_OLAP","AD_SDK_DISTRIBUTE_STAT_OLAP"] # 任务名称,多个任务用逗号分隔
time_delayed = 60*30
#发送邮件
def send_mail(content):
text = ''+content
message = MIMEText(text,'html','utf-8')
message['From'] = Header(mail_user,'utf-8')
message['To'] = Header(";".join(mail_to_list),'utf-8')
message['Subject'] = Header("Spark Streaming 统计监控",'utf-8')
try:
server = smtplib.SMTP()
server.connect(mail_host)
server.sendmail(mail_user,mail_to_list,message.as_string())
server.quit()
print '发送成功'
except Exception,e:
print "Error:无法发送邮件",str(e)
#根据任务名称获取任务跳转地址href
def getHref(url,task_name):
html = ''
href = ''
try:
html = urllib2.urlopen(url)
except Exception , e:
print "打开url出错",str(e),str(url)
try:
bsObj = BeautifulSoup(html.read())
href = bsObj.findAll("a",{"href":re.compile("^http:.*")},text=task_name)[0].attrs["href"]
except Exception ,e :
print "解析标签出错",str(e)
return href
#获取任务运行地址任务运行时间状态
def getTaskStatus(url):
url = url +"/streaming/"
html = ''
time = ''
try:
html = urllib2.urlopen(url)
except Exception , e:
print "打开url出错",str(e),str(url)
try:
bsObj = BeautifulSoup(html.read())
time = bsObj.findAll("table",{"id":"completed-batches-table"})[0].find("tbody").findAll("tr")[0].findAll("td")[0].findAll("a")[0].get_text()
except Exception ,e :
print "解析标签出错",str(e)
return time
#指定的时间与当前时间差
def get_time_diff(t_str):
starttime = datetime.datetime.now()
endtime = datetime.datetime.strptime(t_str, '%Y/%m/%d %H:%M:%S')
return dateDiffInSeconds(starttime,endtime)时间相差的秒数
def dateDiffInSeconds(date1, date2):
timedelta = abs(date2 - date1)
return timedelta.days*24*3600 + timedelta.seconds
#检测是否延时过长,超过了指定的阀值
def checkDelayed(time,url,task_name):
#延时一个小时则发送报警邮件
if time != '':
delayed = get_time_diff(time.strip())
if(delayed>time_delayed ):
url = url+"/streaming/"
content = "任务延时:"+str(delayed)+str("秒,任务url:")+str(url)
send_mail(content)
else:
print "任务:"+str(task_name)+"检测正常"
else:
passtaks url
#根据任务名称获取任务地址
def getTaskUrl(task_name):
url = ''
if getHref(spark_url_master_1,task_name) != '':
url = getHref(spark_url_master_1,task_name)
else:
url = getHref(spark_url_master_2,task_name)
return url
#执行主方法
if __name__ == '__main__':
for task_name in task_names:
taskUrl = getTaskUrl(task_name)
if taskUrl == '':
content = "spark master任务中没有找到运行的任务:"+str("master 地址1:")+spark_url_master_1+str(" , master 地址2:")+spark_url_master_2
send_mail(content)
else:
runTime = getTaskStatus(taskUrl)
checkDelayed(runTime,taskUrl,task_name)
“`
上面是完整的脚本,只要在Linux中加个定时任务就可以进行监控了,这里面用了python提供的爬虫库BeautifulSoup,BeautifulSoup提供了find、
findAll等方法可以和正则表达式进行结合使用,让我们方便的对html文档中的标签进行查找定位获取,之所以用任务名称进行查找任务运行地址,是应
为,spark 集群会进行主备切换,如果写hard code,当主备切换的时候,地址发生了变化,脚本会找不到任务,或者任务重新启动的时候,任务运行
的节点地址也会随机变化的,这样我们就不得不每次启动一次就修改一次监控脚本很繁琐,所以使用任务名称进行查找任务运行地址,我们只要通过配置
spark 集群的访问地址,然后通过爬虫自动查找任务运行的节点地址,找到任务地址进行后做相应的延时等监控处理就可以了,这大大增加了脚本的灵活
性,当然脚本也有很多的不足之处,例如:我们把spark 集群主备地址、任务名称、收件人都hard code代码里,这些度可以进行相应的改进,如通过
web页面进行配置上面的hard code,并通过任务名称进行分组,不同的任务名称发送给不同的收件人,这样就能各负其职呢。
当能力不能匹配你的野心的时候,那就安静下来进行学习