首先说jobtype跟azkaban的webserver端无关,因为webserver节点只负责项目作业管理(上传和分发),并不关心你上传的是哪种类型的作业。负责具体执行的executor会解析job文件。还记得在配置.job作业文件的时候,使用type关键字指定作业类型吗?
executor有一个作业类型管理器,在其构造方法中可以看到,既可以加载默认的作业类型,也能从插件中加载新的作业类型,事实上作业类型也是可以定制的。默认作业类型包括以下几种:
jobToClass.put("command", ProcessJob.class);
jobToClass.put("javaprocess", JavaProcessJob.class); jobToClass.put("noop", NoopJob.class); jobToClass.put("python", PythonJob.class); jobToClass.put("ruby", RubyJob.class); jobToClass.put("script", ScriptJob.class);
jobToClass.put("command", ProcessJob.class);//shell 命令 type=command ;command=echo ok
jobToClass.put("javaprocess", JavaProcessJob.class);//java 命令行 type=javaprocess; java.class=Hello ,指定入口类
jobToClass.put("noop", NoopJob.class);//不可用暂时
jobToClass.put("python", PythonJob.class);//python 命令行 type=python ;python=python ;script=test.py
jobToClass.put("ruby", RubyJob.class);//ruby 命令行 type=ruby ;ruby=ruby ;script=ruby脚本
jobToClass.put("script", ScriptJob.class);//任意可执行脚本 type=script ;executable=sh ,python,ruby ;script=任意可执行脚本
以上作业类型配置非常简单,实质都是linux的命令行程序。
下面重点说明一下插件作业类型
1、java类型和hadoopJava类型。
这两种插件类型在配置上和解析原理上并无大的区别,跟普通的调用java命令行执行的javaprocess类型的作业,有两个显著的不同。
javaprocess这种作业,实质是用java命令行执行普通的java程序,所谓普通的java程序就是有main方法的java类,执行的时候是启动子进程(新的虚拟机来执行程序)。而插件中java和hadoopJava作业,统一要求从run方法执行,而不是main,是通过得到用户程序类的构造方法,使用用户配置参数作为构造方法的实参,构造出实例然后运行run方法的方法。另一个不同是javaprocess作业在运行的过程中,执行取消操作就是杀死进程,一个场景是用这种方法提交了一个作业,单单杀死提交作业的脚本是无法干掉那个作业的,而这种缺憾在java类型和hadoopJava类型作业中得到解决,即取消正在运行的azkaban作业时先运行用户自定义的方法,例如杀死提交脚本之前,我想杀死所有我提交的作业,那么我就可以在cancel方法中实现这部分功能,azkaban的executor会先调用我的cancel方法,然后再kill掉这个job。
hadoopJava跟java的区别在于,hadoopJava增加了更多访问hadoop的属性,方便用户更方便地访问hadoop集群,因为访问hadoop都需要添加配置文件,需要用户认证等,另外提交hadoop作业也需要进行相应的配置。
2、hive类型
hive作业例子:
type=hive
user.to.proxy=azkaban
azk.hive.action=execute.query
hive.query.01=drop table words;
hive.query.02=create table words (freq int, word string) row format delimited fields terminated by '\t' stored as textfile;
hive.query.03=describe words;
hive.query.04=load data local inpath "res/input" into table words;
hive.query.05=select * from words limit 10;
hive.query.06=select freq, count(1) as f2 from words group by freq sort by f2 desc limit 10;
例子:如何提交一个worldCount作业
通过Azkaban提交一个mr作业,这里是指提交java写的mr作业(通过Streaming也可以提交,方法比较简单,就是将提交命令行叫个command执行就行了)。
作业类型可以选择java类型或者hadoopJava类型,需要注意的几个关键点和步骤是:
1、作业怎么写
jobtype\src\azkaban\jobtype\examples\java目录下给了WordCount的例子,这样的作业类需要继承自AbstractHadoopJob类,作业输入输出文件路径通过构造函数初始化,因此输入输出路径需要再配置文件中表明(.properties文件),然后与普通mr作业类不同,azkaban的hadoop作业要求启动入口为run方法,因此只要把原来的main换成run就行了,另外,在fun方法的最后调用父类的run方法去提交作业。
WordCount.java
2、job文件怎么写
前面提到,既然是提交hadoop作业,那么这里选择的作业类型最好是hadoopJava,之后需要用job.class指定作业的类,其次要把作业提交用到的jar包全部加到环境变量里,用户提交的zip包就是工程独立的工作空间
用户可以在里边建立任意的目录层级关系,可以放任何想要放的东西,但是最好别太大,因为毕竟这些东西需要切分然后插到mysql里,但是可以放一些目录让整个项目文件关系更清晰。例如建立一个工程自己的lib目录,把你写的mr作业用到的所有jar包放在里边。所以classpath=./lib/*,${hadoop.home}/lib/*的意思是把工程目录里边的lib目录里的所有文件(jar)全部加到工程的classpath,classpath目录之间用逗号分隔,这里在properties文件中配置了hadoop_home,所以把hadoop依赖的jar包也全部加进来。
type=hadoopJava
job.class=azkaban.jobtype.examples.java.WordCount
classpath=./lib/*,${hadoop.home}/lib/*
main.args=${param.inData} ${param.outData}
force.output.overwrite=true
input.path=${param.inData}
output.path=${param.outData}
dependencies=upload
#wordCount.job
type=hadoopJava
job.class=azkaban.jobtype.examples.java.WordCount
classpath=./lib/*,${hadoop.home}/lib/*
main.args=${param.inData} ${param.outData}
/main.args指定的是要传给mr作业类构造方法的参数,个数要跟其构造方法匹配,使用空格做间隔,这里传入的是作业的输入输出路径。/
force.output.overwrite=true
input.path=${param.inData}
output.path=${param.outData}
dependencies=upload //wordCount.job依赖另一个upload.job
下面看一下upload.job
#upload.job
type=script
executable=sh
script=src/upload.sh
也很简单,使用了通用的脚本类型的作业,调用src目录里的上传脚本,功能是将一篇英文文章上传到hdfs指定的路径。
3、工程项目的配置文件怎么写
user.to.proxy=hadoop //这里使用代理用户hadoop,因为如果不指定代理用户,那么提交作业的用户会默认采用azkaban系统注册用户去提交,就会失败,但是这里似乎有个问题,实验过程中,只要指定了hadoop代理,就能以hadoop用户提交作业,这样的话是不是所有人都可以用hadoop账户提交?(待续)
HDFSRoot=/tmp
hadoop.home=/data1/azkaban/hadoop //azkaban系统启动账户下部署一个hadoop的客户端(hadoop包)
param.inDataLocal=res/rpfarewell //要计数的英文文章
param.inData=hdfs://YZSJHL19-42.opi.com${HDFSRoot}/${user.to.proxy}/wordcountjavain //输入路径
param.outData=hdfs://YZSJHL19-42.opi.com${HDFSRoot}/${user.to.proxy}/wordcountjavaout才 //输出路径
在配置输入输出路径的时候最好加上“hdfs://域名”,否则会识别为本地路径造成作业失败。
到这里基本上一个工程就配置好了,可以提交运行了,特别需要注意的是,classpath只加了hadoop_home/lib目录下的所有jar包,而像hadoop-core-1.0.3.jar这样的东西基本上直接放在了hadoop_home/下,所以需要单独拷贝一个这样的jar包到自己的工程目录,或者将其放进hadoop的lib目录。
原创,转载请注明出处 http://blog.csdn.net/tracymkgld/article/details/17966283