重点介绍oozie调度中 MapReduce 、Spark、Hive workflow的构建以及构建过程中遇到的问题
oozie调度mapreduce任务,其实是针对mapreduce任务的map和reduce阶段分别起了一个map和reduce的任务,
去分别调度map和reduce阶段,而不会去从mapreduce任务的main 函数执行,因此需要将main函数中设置的所有配置都要设置在 workflow中的configuration中。
mapred.reducer.new-api //让oozie支持Hadoop新的MapReduce api
true
mapred.mapper.new-api //让oozie支持Hadoop新的MapReduce api
true
mapreduce.job.queuename //设置任务队列的队列名
${queue_name}
mapreduce.job.reduces //设置MapReduce任务的 reduce个数
50
//设置任务的数据输入路径,对应 FileInputFormat.setInputPaths(job, new Path(args[0]));
name 的值对应 Hadoop中配置参数 public static final String INPUT_DIR =
"mapreduce.input.fileinputformat.inputdir"; (通过代码跟进setInputPaths()可以找到这个参数)
mapreduce.input.fileinputformat.inputdir
${input_data_l2}
//设置任务的数据输出路径,对应 FileOutputFormat.setOutputPath(job, new Path(args[1]));
name 的值对应 Hadoop中配置参数 public static final String OUTDIR = "mapreduce.output.fileoutputformat.outputdir"; (通过代码跟进setOutputPath()可以找到这个参数)
mapreduce.output.fileoutputformat.outputdir
${output_data_l2}
//设置任务中 map的类型以及page名,形式:page名$map类名,对应 job.setMapperClass(JsonAvroConverterMapper.class);
mapreduce.job.map.class
com.milky.pkl.mijia.mapreduce.JsonAvroConverter$JsonAvroConverterMapper
//设置任务中 reduce的类型以及page名,形式:page名$reduce类名,对应 job.setReducerClass(JsonAvroConverterReducer.class);
mapreduce.job.reduce.class
com.milky.pkl.mijia.mapreduce.JsonAvroConverter$JsonAvroConverterReducer
//设置任务中 输入数据的数据格式类型,对应:job.setInputFormatClass(TextInputFormat.class);
name的值 对应Hadoop中配置参数 public static final String INPUT_FORMAT_CLASS_ATTR = "mapreduce.job.inputformat.class"; (通过代码跟进setInputFormatClass()可以找到这个参数)
key的值对应 TextInputFormat 所在的包名,在当前类 中的 import中可以找到
mapreduce.job.inputformat.class
org.apache.hadoop.mapreduce.lib.input.TextInputFormat
//设置任务中 输入数据的数据格式类型,对应:job.setOutputFormatClass(AvroKeyOutputFormat.class);
name的值 对应Hadoop中配置参数 public static final String OUTPUT_FORMAT_CLASS_ATTR = "mapreduce.job.outputformat.class"; (通过代码跟进setOutputFormatClass()可以找到这个参数)
key的值对应 AvroKeyOutputFormat 所在的包名,在当前类 中的 import中可以找到
mapreduce.job.outputformat.class
org.apache.avro.mapreduce.AvroKeyOutputFormat
//设置任务中 map阶段输出数据 key的类型的class,对应 job.setMapOutputKeyClass(AvroKeyOutputFormat.class);
name的值 对应Hadoop中配置参数 public static final String MAP_OUTPUT_KEY_CLASS = "mapreduce.map.output.key.class";(通过代码跟进setMapOutputKeyClass()可以找到这个参数)
key的值对应 public static class JsonAvroConverterMapper
extends Mapper/*输出key的类型*/, NullWritable/*输出value的类型*/> {} 中 AvroKey 所在的包名,在当前类 中的 import中可以找到
mapreduce.map.output.key.class
org.apache.avro.mapred.AvroKey
// 设置任务中 map阶段输出数据value类型的class,类同 上述 ,不再多说
mapreduce.map.output.value.class
org.apache.hadoop.io.NullWritable
/* 普通的mapreduce任务设置以上内容已可满足,若是main函数中还有其他的job任务的配置,根据上述的方法继续配置*/
/*下面是 avrojob中的额外配置,main函数中有两行:
第一行: AvroJob.setOutputKeySchema(job, MijiaResult.getClassSchema());
其中setOutputKeySchema函数实现为:
public static void setOutputKeySchema(Job job, Schema schema) {
job.setOutputKeyClass(AvroKey.class);
job.getConfiguration().set(CONF_OUTPUT_KEY_SCHEMA, schema.toString());
}
第二行: AvroJob.setMapOutputKeySchema(job, MijiaResult.getClassSchema());
其中setMapOutputKeySchema函数的实现为:
public static void setMapOutputKeySchema(Job job, Schema schema) {
job.setMapOutputKeyClass(AvroKey.class);
job.setGroupingComparatorClass(AvroKeyComparator.class);
job.setSortComparatorClass(AvroKeyComparator.class);
AvroSerialization.setKeyWriterSchema(job.getConfiguration(), schema);
AvroSerialization.setKeyReaderSchema(job.getConfiguration(), schema);
AvroSerialization.addToConfiguration(job.getConfiguration());
}
这需要根据上面两个函数的实现继续配置!!!
*/
mapreduce.job.output.key.class
org.apache.avro.mapred.AvroKey
avro.schema.output.key
${schema}
mapreduce.job.output.group.comparator.class
org.apache.avro.hadoop.io.AvroKeyComparator
mapreduce.job.output.key.comparator.class
org.apache.avro.hadoop.io.AvroKeyComparator
avro.serialization.key.writer.schema
${schema}
avro.serialization.key.reader.schema
${schema}
io.serializations
org.apache.hadoop.io.serializer.WritableSerialization, org.apache.hadoop.io.serializer.avro.AvroSpecificSerialization, org.apache.hadoop.io.serializer.avro.AvroReflectSerialization,org.apache.avro.hadoop.io.AvroSerialization
(2)遇到的问题:
avro-mapred.jar 包与hive中有些jar冲突问题,避免avro-mapred.jar 与hive的一些jar放到一起
oozie调度spark任务,只会启动一个map任务,来执行spark任务,
(1)oozie4.2.0 只支持sparkaction0.1,最新版本是支持sparkaction0.2
(2)workflow 设置action时,要标明sparkaction的版本,例如:
(3)即使有spark任务没提交到spark上运行,有可能产生oozie调度的成功
(4)基本路径不能忽略hdfs://op2:8020/,不设置将默认在本地找(默认的事file://)
(5) sparkhistory中找不到oozie调spark的任务记录;需要在spark-opts标签中显示的设置,例如:
--conf spark.yarn.historyServer.address=http://172.23.7.11:18080 --conf spark.eventLog.dir=hdfs://op2/user/spark/log --conf spark.eventLog.enabled=true
(6)运行方式: master为 yarn-cluster,mode 不用设置或将其设置成cluster;yarn-client的模式会出现永久区 OOM,原因不详
(7)配置设置: 将runtime时需要的 file:// 协议的文件,用 spark的--files参数将所需要的文件带到各个节点上
(8) 队列设置: mapreduce.job.queuename 只设置了oozie起 的一个map的队列,而spark任务的队列需要在spark-opts 中的 --queue 设置队列的名字,若不设置 spark任务会在 root.default队列上执行
(9) 像 --driver-java-option 这样的参数传递多个参数时,多个参数之前不能用空格,需要 用转义过的制表符的(注意是xml的转义)
workflow的例子:
${job_tracker}
${name_node}
mapreduce.job.queuename
${queue_name}
yarn-cluster
mijia.spark.M6
com.milky.pkl.mijia.Mijia
${oozie_app_path}workflow/lib/mijia.jar
${spark_opts}
--input
${pkl_mijia_datas_input}
--output
${output_data_l1}
--output-format
avro
--config-path
${configs_path}
Job failed, error message[${wf:errorMessage(wf:lastErrorNode())}]
(1) 参数传递方式
_0_date=${_0_date}其中param标签传递的参数 最终为转化为 --hivevar 的这种传参方式,若是hive脚本中 有hiveconf
传参方式,请将脚本中的hiveconf 全部换成hivevar传参,因为是 oozie调度hive ,oozie向hive脚本传递参数只能是 hivevar方式
(2)设置hive配置
若是不加载hive-site.xml,会报出异常。
workflow的例子:
${job_tracker}
${hive_name_node}
${oozie_app_path}/workflow/conf/hive-site.xml
mapreduce.job.queuename
${queue_name}
date1=${date1}
date2=${date1}
Job failed, error message[${wf:errorMessage(wf:lastErrorNode())}]
(1) workflow目录下的lib文件夹下的所有 jar包是默认全部加载,即使你在workflow中指定其他目录下的 jar包,
lib下的所有jar包也有加载,在出现jar包冲突时需要考虑这一点。
(2)一个workflow中出现多个 action,且configuration中的配置有很多相同的配置的时候,建议将多个action中的配置写在global标签中