背景:
spark本身没有设置timeout的配置,加上数据开发团队大数据sql基础薄弱,很容易写出数据倾斜倾斜等消耗资源巨大的sql,而后其它任务全部卡死,考虑写脚本kill超时的任务,考虑到了如下3个方案
1、spark-shell --kill,该方法只支持 Spark standalone or Mesos with cluster deploy mode only,而大多数公司的场景是spark on yarn,该方法pass。
2、spark源码中有个canceljob的接口,同样该方法不支持spark on yarn。
3、通过spark ui界面获取超时的任务,直接获取该界面对应job的kill链接,并curl url即可kill job,链接获取如下,curl http://ip or hostname:port/proxy/application_1587906428557_0119/jobs/job/kill/?id=21068,即可kill该job
环境:
centos7,python2.7
代码:
#!/usr/bin/python
#coding:utf-8
from lxml import etree
import os
import re
import io
os.system('curl http://ip or hostname:port/cluster/apps/RUNNING >yarn.html')
for line in open('yarn.html','r').readlines():
if "spark" in line:
#提取spark用户任务的spark ui链接,该服务为长服务,只有1个appid,该服务在spark中可以运行多个sparkjob
print(line)
sparkUrl=re.findall('http://ip or hostname:port/proxy/application_?\d+_?\d+', line)[0]
print(sparkUrl)
#获取spark ui html
cmd='curl '+sparkUrl+'>sparkUi.html'
os.system(cmd)
html=io.open('sparkUi.html',encoding='UTF-8').read()
page=etree.HTML(html)
#判断有无正在运行的任务,spark ui界面有kill按钮就表示该任务在运行
def ifActive():
hrefs = page.xpath(u"/html/body/div[2]/div[4]/div/table/tbody/tr/td[2]/a[1]")
for href in hrefs:
print(href.text)
return "kill" in href.text
#没有正在运行的任务即退出运行
if(ifActive()):
print("There are running job,next")
else:
print("There are not running job,exit")
exit(0)
runTimes = page.xpath(u"/html/body/div[2]/div[4]/div/table/tbody/tr/td[4]")
i=0
for runTime in runTimes:
i=i+1
#先筛选运行时长有’h‘的job
if("h" in runTime.text):
print("There are more than one hour job")
herf_url="/html/body/div[2]/div[4]/div/table/tbody/tr["+str(i)+"]/td[2]/a[1]/@href"
killJobUrl="curl -s http://ip or hostname:port"+str(page.xpath(herf_url)[0])
print(killJobUrl)
#再筛选运行时长大于6的job
if(float(re.findall(u'^\d+\.?\d+', runTime.text)[0]) >=6):
#kill运行时长大于6小时的job
os.system(killJobUrl)
print("cancel successfull")
else:
print("There are not more than one hour task,next job")
代码解读:
先从yarn的界面获取正在运行appid对应的spark ui链接,在spark ui界面获取正在运行的任务,判断运行时长,超过6小时就kill该任务。
脚本启动:
使用linux crontab调度,每小时调度一次,确保部署脚本的服务器要和部署spark ui服务的主机环境要通。