Azkaban本身具有邮件报警功能,但是邮件报警一般用户不能及时响应处理。虽然用户可以在作业中自行设计、使用短信报警功能,但是仅能对工作流中的一个作业执行内部过程监控,而不能监视工作流整体运行进度。为了使工作流的执行状态更方便快捷地通知到用户,特设计开发Azkaban的短信报警功能。
Azkaban的详细介绍在前几篇,想要添加短信报警功能,必须要对Azkaban的结构有所了解。简单来讲,Azkaban2.2由两部分组成,一个是webserver,一个是executor,前者负责调度和显示、后者负责执行,两者依靠http接口通信。已经掌握Azkaban使用方法的用户都知道,可以在定义job文件或者全局配置文件的时候,通过指定下面三种参数,可以给工作流中的每一个job分别设置
报警邮件接受者列表。
failure.emails | Comma delimited list of emails to notify during a failure. * |
success.emails | Comma delimited list of emails to notify during a success. * |
notify.emails | Comma delimited list of emails to notify during either a success or failure. * |
或者在web页面手工一次运行或者设置调度运行之前通过Notification选项添加,可以将触发条件配置成首次失败或者整个工作流失败的情况,一般来讲,一个工作流首次失败意味着工作流的某个节点失败,对于依赖关系较强的工作流来说是应该立即处理的。
基于以上工作原理,我们希望设计一个与邮件报警配置类似的短信报警配置功能。通过Azkaban的代码可以看出,一个工作流被调度、被执行的大致过程是这样的:
1、用户打包上传自己的项目文件,被webserver解析出dag依赖关系,建立流程图,同时项目文件被插入mysql数据表中,并建立项目、工作流对象。
2、用户点击执行前有时候会配置上图中那些信息,点击执行按钮时,这些前段用户配置信息通过http接口发送到webserver的servlet处理,webserver会将这些信息进行处理,结合从用户job文件、配置文件中设置的信息做好准备交给执行器执行。
3、准备好的工作流会提交给执行器执行,执行器对工作流排队,执行完毕的工作流会有一个执行结果处理的过程,邮件报警也是在那里被执行的。
一种简单地解决方案是,在邮件报警器上直接添加短信报警方法,即发送短信报警必须发送邮件报警,这种方式比较简单,但是不符合面向对象程序设计的思想和原则;幸运地是Azkaban2.2提供了报警接口,邮件报警也实现了这个接口,并且还支持插件方式,不得不说Azkaban2.2程序设计得实在人性,现在我们就开发一个短信报警器插件。
1、插件的开发
首先需要在webserver的conf目录的azkaban.properties文件中指定插件目录,当然我们可以不指定,直接使用默认的目录,即plugins/alerter,跟其他插件一样,需要在里边建一个目录,比如叫sms
sms中需要有conf extlib lib三个目录。
我们在conf目录中创建一个文件叫做plugin.properties,我们添加参数alerter.name=sms,同时配置alerter.external.classpaths和alerter.class,这俩分别是咱们开发的编译好的报警器的classpath和class文件位置
相应的lib文件放置使用到的外部jar包。
这样的插件就会被azkaban识别,称为一个可用的报警器。报警器程序如何开发呢,我们可以参照Emailer,实现Alerter接口,主要实现四种方法即可。这里不再多说,比较简单,短信报警的方式我们还是采用公司的http接口,使用java调用shell脚本实现。
public interface Alerter { void alertOnSuccess(ExecutableFlow exflow) throws Exception; void alertOnError(ExecutableFlow exflow, String ... extraReasons) throws Exception; void alertOnFirstError(ExecutableFlow exflow) throws Exception; void alertOnSla(SlaOption slaOption, String slaMessage) throws Exception;
}
public interface Alerter
2、报警手机的配置
报警手机我们希望能从前段获取,用户可以在执行或者调度前自己在页面配置,暂不提供job文件配置方式,一是需要改动较多源码,二是也没十分必要,调度或者手工执行前配置是比较好的方式。想要实现这个功能,必须要搞清楚前后端数据投递方式,和页面绘制方法。
从java代码的servlet方法看,Azkaban2.2使用了Velocity模板引擎,所谓模板实际上是相对于传统的开发方式来说的,普通的jsp或者servlet开发方式原理都是往页面打印页面标签和一些动态数据,这种方式有个缺点是不易维护,更改起来不方便,但是有个优点是后台运行起来之后,jsp更改不需要重启服务。这里不深入比较两者,只为说明Velocity的工作原理,Velocity的模板文件以.vm结尾,随java代码一起编译,模板中规划好了页面布局,引入了javascript脚本作为与后台的交互,因此添加报警手机界面需要更改vm文件,往后台传递手机号码需要更改js文件。
ok,我们抓一下页面,看看那个面板叫什么名字,execute-flow-panel,对应的模板是azkaban.webapp.servlet.velocity包下的flowexecutionpanel.vm,
Velocity模板整体结构还是html结构,我们按照邮件列表界面模仿添加手机列表,同时设置id,
现在界面有了,下一就应该考虑怎么把咱们输入的手机号传递给后台,比较快的方式是把它关联的js挨个看一下,最后发现在azkaban.flow.execute.view.js里
我们继续看这个js,并且模仿添加手机列表,下图可以看出,我们点执行对应的是handleExecuteFlow方法
这里采用的ajax往后台打数据,看看都传了哪些数据,
我们模仿邮件功能,把手机列表也抓进来投递过去,通过handleExecuteFlow我们看到这个请求是由ExecutorServlet负责处理的。
最终我们可以定位到ajaxExecuteFlow方法,Azkaban使用ExecutionOptions对象将所有的配置信息保存,并且在执行结果报警时从中拿出来进行相应的处理,所以我们在parseFlowOptions方法中,将手机号码解析出来,同时更改一下ExecutionOptions对象,添加相应的成员变量即可,到这里前端的数据就成功被添加到后台了。
前端界面变成了这样子:
使用:
报警格式:
[Azkaban]["azkabanName"][ERROR][ExecutionId:"flow.getExecutionId()"][FlowId:"flow.getFlowId()"]
以[Azkaban]开头,提醒用户这是来自azkaban的短信,第二个字段是为了区分将来有可能出现的不同的azkaban的系统,第三个字段可以是ERROR或者SUCCESS,代表成功或者失败,之后跟上执行id和工作流id,方便用户追查日志,查找失败原因。