Oozie
Oozie的简介
是一个轻量的架构。一个基于工作流引擎的开源框架,由Cloudera公司贡献给Apache,提供对Hadoop MapReduce、Pig Jobs的任务调度与协调。Oozie需要部署到Java Servlet容器中运行。主要用于定时调度任务,多任务可以按照执行的逻辑顺序调度。
Oozie和Azkaban的技术选型和对比
调度工具性能对比:Apache Oozie,其配置工作流的过程是编写大量的XML配置,而且代码复杂度比较高,不易于二次开发。Ooize相比Azkaban是一个重量级的任务调度系统,功能全面,但配置使用也更复杂。如果可以不在意某些功能的缺失,轻量级调度器azkaban是很不错的候选对象。
Oozie和Azkaban的区别:
两者在功能方面大致相同,只是Oozie底层在提交Hadoop Spark作业是通过org.apache.hadoop的封装好的接口进行提交,而Azkaban可以直接操作shell语句。在安全性上可能Oozie会比较好。
工作流定义:Oozie是通过xml定义的而Azkaban为properties来定义。
部署过程:Oozie的部署相对困难些,同时它是从Yarn上拉任务日志。Azkaban中如果有任务出现失败,只要进程有效执行,那么任务就算执行成功,这是BUG,但是Oozie能有效的检测任务的成功与失败。
操作工作流:Azkaban使用Web操作。Oozie支持Web,RestApi,Java API操作。
权限控制:Oozie基本无权限控制,Azkaban有较完善的权限控制,供用户对工作流读写执行操作。Oozie的action主要运行在hadoop中而Azkaban的actions运行在Azkaban的服务器中。
记录workflow的状态:Azkaban将正在执行的workflow状态保存在内存中,Oozie将其保存在Mysql中。
出现失败的情况:Azkaban会丢失所有的工作流,但是Oozie可以在继续失败的工作流运行
特性 | Oozie | Azkaban |
工作流描述语言 | XML (xPDL based) | text file with key/value pairs |
依赖机制 | explicit | explicit |
是否要web容器 | Yes | Yes |
进度跟踪 | web page | web page |
Hadoop job调度支持 | yes | yes |
运行模式 | daemon | daemon |
Pig支持 | yes | yes |
事件通知 | no | no |
需要安装 | yes | yes |
支持的hadoop版本 | 0.20+ | currently unknown |
重试支持 | workflownode evel | yes |
运行任意命令 | yes | yes |
Amazon EMR支持 | no | currently unknown |
Oozie 模块功能介绍
Oozie的模块
1) Workflow:顺序执行流程节点,支持fork(分支多个节点),join(合并多个节点为一个)
2) Coordinator:定时触发workflow
3) Bundle Job:绑定多个Coordinator
Oozie 常用节点
1) 控制流节点(Control Flow Nodes):控制流节点一般都是定义在工作流开始或者结束的位置,比如start,end,kill等。以及提供工作流的执行路径机制,如decision,fork,join等。
2) 动作节点(Action Nodes):负责执行具体动作的节点,比如:拷贝文件,执行某个Shell脚本等等。
Oozie 模块的实际的案例
部署hadoop
修改hadoop中的core-site.xml的配置
1
2
3
4
5
6
7
8
9
10
11<!-- Oozie Server的Hostname --> <property> <name>hadoop.proxyuser.shanghaiuniver.hosts</name> <value>*</value> </property> <!-- 允许被Oozie代理的用户组 --> <property> <name>hadoop.proxyuser.shanghaiuniver.groups</name> <value>*</value> </property>
修改marped-site.xml配置文件
1
2
3
4
5
6
7
8
9
10
11
12<!-- 配置 MapReduce JobHistory Server 地址 ,默认端口10020 --> <property> <name>mapreduce.jobhistory.address</name> <value>hadoop102:10020</value> </property> <!-- 配置 MapReduce JobHistory Server web ui 地址, 默认端口19888 --> <property> <name>mapreduce.jobhistory.webapp.address</name> <value>hadoop102:19888</value> </property>
修改是yarn-site.xml
1
2
3
4
5
6<!-- 任务历史服务 --> <property> <name>yarn.log.server.url</name> <value>http://hadoop102:19888/jobhistory/logs/</value> </property>
部署Oozie
下载好Oozie的安装文件 然后在Oozie的根目录下解压 oozie-hadooplibs-4.0.0-cdh5.3.6.tar.gz 在Oozie的目录下创建libext目录。将hadooplibs里面的架包拷贝到libext的目录下。拷贝Mysql驱动包到libext目录下。将ext-2.2.zip拷贝到libext/目录下,然后在在修改Oozie的配置文件
oozie-site.xml
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20属性:oozie.service.JPAService.jdbc.driver 属性值:com.mysql.jdbc.Driver 解释:JDBC的驱动 属性:oozie.service.JPAService.jdbc.url 属性值:jdbc:mysql://hadoop102:3306/oozie 解释:oozie所需的数据库地址 属性:oozie.service.JPAService.jdbc.username 属性值:root 解释:数据库用户名 属性:oozie.service.JPAService.jdbc.password 属性值:000000 解释:数据库密码 属性:oozie.service.HadoopAccessorService.hadoop.configurations 属性值:*=/opt/module/cdh/hadoop-2.5.0-cdh5.3.6/etc/hadoop 解释:让Oozie引用Hadoop的配置文件
在Mysql中的创建Oozie的数据库
1
2
3进入Mysql并创建oozie数据库: $ mysql -uroot -p000000 mysql> create database oozie;
初始化Oozie
1
2
3
4
5
6
7
8
91) 上传Oozie目录下的yarn.tar.gz文件到HDFS: 提示:yarn.tar.gz文件会自行解压 [xjl@hadoop102 oozie-4.0.0-cdh5.3.6]$ bin/oozie-setup.sh sharelib create -fs hdfs://hadoop102:8020 -locallib oozie-sharelib-4.0.0-cdh5.3.6-yarn.tar.gz 执行成功之后,去50070检查对应目录有没有文件生成。 2) 创建oozie.sql文件 [xjl@hadoop102 oozie-4.0.0-cdh5.3.6]$ bin/ooziedb.sh create -sqlfile oozie.sql -run 3) 打包项目,生成war包 [xjl@hadoop102 oozie-4.0.0-cdh5.3.6]$ bin/oozie-setup.sh prepare-war
Oozie的启动与关闭
1
2
3
4
5启动命令如下: [xjl@hadoop102 oozie-4.0.0-cdh5.3.6]$ bin/oozied.sh start 关闭命令如下: [xjl@hadoop102 oozie-4.0.0-cdh5.3.6]$ bin/oozied.sh stop
Oozie的使用
Oozie调度shell脚本
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
701)解压官方案例模板 [xjl@hadoop102 oozie-4.0.0-cdh5.3.6]$ tar -zxvf oozie-examples.tar.gz 2)创建工作目录 [xjl@hadoop102 oozie-4.0.0-cdh5.3.6]$ mkdir oozie-apps/ 3)拷贝任务模板到oozie-apps/目录 [xjl@hadoop102 oozie-4.0.0-cdh5.3.6]$ cp -r examples/apps/shell/ oozie-apps 4)编写脚本p1.sh [xjl@hadoop102 oozie-4.0.0-cdh5.3.6]$ vi oozie-apps/shell/p1.sh 内容如下: #!/bin/bash /sbin/ifconfig > /opt/module/p1.log 5)修改job.properties和workflow.xml文件 job.properties #HDFS地址 nameNode=hdfs://hadoop102:8020 #ResourceManager地址 jobTracker=hadoop103:8032 #队列名称 queueName=default examplesRoot=oozie-apps oozie.wf.application.path=${nameNode}/user/${user.name}/${examplesRoot}/shell EXEC=p1.sh workflow.xml <workflow-app xmlns="uri:oozie:workflow:0.4" name="shell-wf"> <start to="shell-node"/> <action name="shell-node"> <shell xmlns="uri:oozie:shell-action:0.2"> <job-tracker>${jobTracker}</job-tracker> <name-node>${nameNode}</name-node> <configuration> <property> <name>mapred.job.queue.name</name> <value>${queueName}</value> </property> </configuration> <exec>${EXEC}</exec> <!-- <argument>my_output=Hello Oozie</argument> --> <file>/user/atguigu/oozie-apps/shell/${EXEC}#${EXEC}</file> <capture-output/> </shell> <ok to="end"/> <error to="fail"/> </action> <decision name="check-output"> <switch> <case to="end"> ${wf:actionData('shell-node')['my_output'] eq 'Hello Oozie'} </case> <default to="fail-output"/> </switch> </decision> <kill name="fail"> <message>Shell action failed, error message[${wf:errorMessage(wf:lastErrorNode())}]</message> </kill> <kill name="fail-output"> <message>Incorrect output, expected [Hello Oozie] but was [${wf:actionData('shell-node')['my_output']}]</message> </kill> <end name="end"/> </workflow-app> 6)上传任务配置 [xjl@hadoop102 oozie-4.0.0-cdh5.3.6]$ /opt/module/cdh/hadoop-2.5.0-cdh5.3.6/bin/hadoop fs -put oozie-apps/ /user/atguigu 7)执行任务 [xjl@hadoop102 oozie-4.0.0-cdh5.3.6]$ bin/oozie job -oozie http://hadoop102:11000/oozie -config oozie-apps/shell/job.properties -run 8)杀死某个任务 [xjl@hadoop102 oozie-4.0.0-cdh5.3.6]$ bin/oozie job -oozie http://hadoop102:11000/oozie -kill 0000004-170425105153692-oozie-z-W
Oozie逻辑调度执行多个Job
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
791) 解压官方案例模板 [xjl@hadoop102 oozie-4.0.0-cdh5.3.6]$ tar -zxf oozie-examples.tar.gz 2) 编写脚本 [xjl@hadoop102 oozie-4.0.0-cdh5.3.6]$ vi oozie-apps/shell/p2.sh 内容如下: #!/bin/bash /bin/date > /opt/module/p2.log 3)修改job.properties和workflow.xml文件 job.properties nameNode=hdfs://hadoop102:8020 jobTracker=hadoop103:8032 queueName=default examplesRoot=oozie-apps oozie.wf.application.path=${nameNode}/user/${user.name}/${examplesRoot}/shell EXEC1=p1.sh EXEC2=p2.sh workflow.xml <workflow-app xmlns="uri:oozie:workflow:0.4" name="shell-wf"> <start to="p1-shell-node"/> <action name="p1-shell-node"> <shell xmlns="uri:oozie:shell-action:0.2"> <job-tracker>${jobTracker}</job-tracker> <name-node>${nameNode}</name-node> <configuration> <property> <name>mapred.job.queue.name</name> <value>${queueName}</value> </property> </configuration> <exec>${EXEC1}</exec> <file>/user/atguigu/oozie-apps/shell/${EXEC1}#${EXEC1}</file> <!-- <argument>my_output=Hello Oozie</argument>--> <capture-output/> </shell> <ok to="p2-shell-node"/> <error to="fail"/> </action> <action name="p2-shell-node"> <shell xmlns="uri:oozie:shell-action:0.2"> <job-tracker>${jobTracker}</job-tracker> <name-node>${nameNode}</name-node> <configuration> <property> <name>mapred.job.queue.name</name> <value>${queueName}</value> </property> </configuration> <exec>${EXEC2}</exec> <file>/user/admin/oozie-apps/shell/${EXEC2}#${EXEC2}</file> <!-- <argument>my_output=Hello Oozie</argument>--> <capture-output/> </shell> <ok to="end"/> <error to="fail"/> </action> <decision name="check-output"> <switch> <case to="end"> ${wf:actionData('shell-node')['my_output'] eq 'Hello Oozie'} </case> <default to="fail-output"/> </switch> </decision> <kill name="fail"> <message>Shell action failed, error message[${wf:errorMessage(wf:lastErrorNode())}]</message> </kill> <kill name="fail-output"> <message>Incorrect output, expected [Hello Oozie] but was [${wf:actionData('shell-node')['my_output']}]</message> </kill> <end name="end"/> </workflow-app> 3) 上传任务配置 $ bin/hadoop fs -rmr /user/atguigu/oozie-apps/ $ bin/hadoop fs -put oozie-apps/map-reduce /user/atguigu/oozie-apps 4) 执行任务 [xjl@hadoop102 oozie-4.0.0-cdh5.3.6]$ bin/oozie job -oozie http://hadoop102:11000/oozie -config oozie-apps/shell/job.properties -run
Oozie调度MapReduce任务
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
971)找到一个可以运行的mapreduce任务的jar包(可以用官方的,也可以是自己写的) 2)拷贝官方模板到oozie-apps [xjl@hadoop102 oozie-4.0.0-cdh5.3.6]$ cp -r /opt/module/cdh/ oozie-4.0.0-cdh5.3.6/examples/apps/map-reduce/ oozie-apps/ 1) 测试一下wordcount在yarn中的运行 [xjl@hadoop102 oozie-4.0.0-cdh5.3.6]$ /opt/module/cdh/hadoop-2.5.0-cdh5.3.6/bin/yarn jar /opt/module/cdh/hadoop-2.5.0-cdh5.3.6/share/hadoop/mapreduce/hadoop-mapreduce-examples-2.5.0-cdh5.3.6.jar wordcount /input/ /output/ 4) 配置map-reduce任务的job.properties以及workflow.xml job.properties nameNode=hdfs://hadoop102:8020 jobTracker=hadoop103:8032 queueName=default examplesRoot=oozie-apps #hdfs://hadoop102:8020/user/admin/oozie-apps/map-reduce/workflow.xml oozie.wf.application.path=${nameNode}/user/${user.name}/${examplesRoot}/map-reduce/workflow.xml outputDir=map-reduce workflow.xml <workflow-app xmlns="uri:oozie:workflow:0.2" name="map-reduce-wf"> <start to="mr-node"/> <action name="mr-node"> <map-reduce> <job-tracker>${jobTracker}</job-tracker> <name-node>${nameNode}</name-node> <prepare> <delete path="${nameNode}/output/"/> </prepare> <configuration> <property> <name>mapred.job.queue.name</name> <value>${queueName}</value> </property> <!-- 配置调度MR任务时,使用新的API --> <property> <name>mapred.mapper.new-api</name> <value>true</value> </property> <property> <name>mapred.reducer.new-api</name> <value>true</value> </property> <!-- 指定Job Key输出类型 --> <property> <name>mapreduce.job.output.key.class</name> <value>org.apache.hadoop.io.Text</value> </property> <!-- 指定Job Value输出类型 --> <property> <name>mapreduce.job.output.value.class</name> <value>org.apache.hadoop.io.IntWritable</value> </property> <!-- 指定输入路径 --> <property> <name>mapred.input.dir</name> <value>/input/</value> </property> <!-- 指定输出路径 --> <property> <name>mapred.output.dir</name> <value>/output/</value> </property> <!-- 指定Map类 --> <property> <name>mapreduce.job.map.class</name> <value>org.apache.hadoop.examples.WordCount$TokenizerMapper</value> </property> <!-- 指定Reduce类 --> <property> <name>mapreduce.job.reduce.class</name> <value>org.apache.hadoop.examples.WordCount$IntSumReducer</value> </property> <property> <name>mapred.map.tasks</name> <value>1</value> </property> </configuration> </map-reduce> <ok to="end"/> <error to="fail"/> </action> <kill name="fail"> <message>Map/Reduce failed, error message[${wf:errorMessage(wf:lastErrorNode())}]</message> </kill> <end name="end"/> </workflow-app> 5)拷贝待执行的jar包到map-reduce的lib目录下 [xjl@hadoop102 oozie-4.0.0-cdh5.3.6]$ cp -a /opt /module/cdh/hadoop-2.5.0-cdh5.3.6/share/hadoop/mapreduce/hadoop-mapreduce-examples-2.5.0-cdh5.3.6.jar oozie-apps/map-reduce/lib 6)上传配置好的app文件夹到HDFS [xjl@hadoop102 oozie-4.0.0-cdh5.3.6]$ /opt/module/cdh/hadoop-2.5.0-cdh5.3.6/bin/hdfs dfs -put oozie-apps/map-reduce/ /user/admin/oozie-apps 7)执行任务 [xjl@hadoop102 oozie-4.0.0-cdh5.3.6]$ bin/oozie job -oozie http://hadoop102:11000/oozie -config oozie-apps/map-reduce/job.properties -run
Oozie定时任务/循环任务
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130分步实现: 1) 配置Linux时区以及时间服务器 2) 检查系统当前时区: # date -R 注意:如果显示的时区不是+0800,删除localtime文件夹后,再关联一个正确时区的链接过去,命令如下: # rm -rf /etc/localtime # ln -s /usr/share/zoneinfo/Asia/Shanghai /etc/localtime 同步时间: # ntpdate pool.ntp.org 修改NTP配置文件: # vi /etc/ntp.conf 去掉下面这行前面的# ,并把网段修改成自己的网段: restrict 192.168.122.0 mask 255.255.255.0 nomodify notrap 注释掉以下几行: #server 0.centos.pool.ntp.org #server 1.centos.pool.ntp.org #server 2.centos.pool.ntp.org 把下面两行前面的#号去掉,如果没有这两行内容,需要手动添加 server 127.127.1.0 # local clock fudge 127.127.1.0 stratum 10 重启NTP服务: # systemctl start ntpd.service, 注意,如果是centOS7以下的版本,使用命令:service ntpd start # systemctl enable ntpd.service, 注意,如果是centOS7以下的版本,使用命令:chkconfig ntpd on 集群其他节点去同步这台时间服务器时间: 首先需要关闭这两台计算机的ntp服务 # systemctl stop ntpd.service, centOS7以下,则:service ntpd stop # systemctl disable ntpd.service, centOS7以下,则:chkconfig ntpd off # systemctl status ntpd,查看ntp服务状态 # pgrep ntpd,查看ntp服务进程id 同步第一台服务器linux01的时间: # ntpdate hadoop102 使用root用户制定计划任务,周期性同步时间: # crontab -e */10 * * * * /usr/sbin/ntpdate hadoop102 重启定时任务: # systemctl restart crond.service, centOS7以下使用:service crond restart, 其他台机器的配置同理。 3) 配置oozie-site.xml文件 属性:oozie.processing.timezone 属性值:GMT+0800 解释:修改时区为东八区区时 注:该属性去oozie-default.xml中找到即可 4) 修改js框架中的关于时间设置的代码 $ vi /opt/module/cdh/oozie-4.0.0-cdh5.3.6/oozie-server/webapps/oozie/oozie-console.js 修改如下: function getTimeZone() { Ext.state.Manager.setProvider(new Ext.state.CookieProvider()); return Ext.state.Manager.get("TimezoneId","GMT+0800"); } 5)重启oozie服务,并重启浏览器(一定要注意清除缓存) [xjl@hadoop102 oozie-4.0.0-cdh5.3.6]$ bin/oozied.sh stop [xjl@hadoop102 oozie-4.0.0-cdh5.3.6]$ bin/oozied.sh start 6)拷贝官方模板配置定时任务 $ cp -r examples/apps/cron/ oozie-apps/ 7)修改模板job.properties和coordinator.xml以及workflow.xml job.properties nameNode=hdfs://hadoop102:8020 jobTracker=hadoop103:8032 queueName=default examplesRoot=oozie-apps oozie.coord.application.path=${nameNode}/user/${user.name}/${examplesRoot}/cron #start:必须设置为未来时间,否则任务失败 start=2017-07-29T17:00+0800 end=2017-07-30T17:00+0800 workflowAppUri=${nameNode}/user/${user.name}/${examplesRoot}/cron EXEC3=p3.sh coordinator.xml <coordinator-app name="cron-coord" frequency="${coord:minutes(5)}" start="${start}" end="${end}" timezone="GMT+0800" xmlns="uri:oozie:coordinator:0.2"> <action> <workflow> <app-path>${workflowAppUri}</app-path> <configuration> <property> <name>jobTracker</name> <value>${jobTracker}</value> </property> <property> <name>nameNode</name> <value>${nameNode}</value> </property> <property> <name>queueName</name> <value>${queueName}</value> </property> </configuration> </workflow> </action> </coordinator-app> workflow.xml <workflow-app xmlns="uri:oozie:workflow:0.5" name="one-op-wf"> <start to="p3-shell-node"/> <action name="p3-shell-node"> <shell xmlns="uri:oozie:shell-action:0.2"> <job-tracker>${jobTracker}</job-tracker> <name-node>${nameNode}</name-node> <configuration> <property> <name>mapred.job.queue.name</name> <value>${queueName}</value> </property> </configuration> <exec>${EXEC3}</exec> <file>/user/atguigu/oozie-apps/cron/${EXEC3}#${EXEC3}</file> <!-- <argument>my_output=Hello Oozie</argument>--> <capture-output/> </shell> <ok to="end"/> <error to="fail"/> </action> <kill name="fail"> <message>Shell action failed, error message[${wf:errorMessage(wf:lastErrorNode())}]</message> </kill> <kill name="fail-output"> <message>Incorrect output, expected [Hello Oozie] but was [${wf:actionData('shell-node')['my_output']}]</message> </kill> <end name="end"/> </workflow-app> 8)上传配置 [xjl@hadoop102 oozie-4.0.0-cdh5.3.6]$ /opt/module/cdh/hadoop-2.5.0-cdh5.3.6/bin/hdfs dfs -put oozie-apps/cron/ /user/admin/oozie-apps 9)启动任务 [xjl@hadoop102 oozie-4.0.0-cdh5.3.6]$ bin/oozie job -oozie http://hadoop102:11000/oozie -config oozie-apps/cron/job.properties -run 注意:Oozie允许的最小执行任务的频率是5分钟
常见问题总结:
1)Mysql权限配置
授权所有主机可以使用root用户操作所有数据库和数据表
1
2
3
4
5mysql> grant all on *.* to root@'%' identified by '000000'; mysql> flush privileges; mysql> exit;
2)workflow.xml配置的时候不要忽略file属性
3)jps查看进程时,注意有没有bootstrap
4)关闭oozie: 如果bin/oozied.sh stop无法关闭,则可以使用kill -9 [pid],之后oozie-server/temp/xxx.pid文件一定要删除。
5)Oozie重新打包时,一定要注意先关闭进程,删除对应文件夹下面的pid文件。(可以参考第4条目)
6)配置文件一定要生效: 起始标签和结束标签无对应则不生效,配置文件的属性写错了,那么则执行默认的属性。
7)libext下边的jar存放于某个文件夹中,导致share/lib创建不成功。
8)调度任务时,找不到指定的脚本,可能是oozie-site.xml里面的Hadoop配置文件没有关联上。
9)修改Hadoop配置文件,需要重启集群。一定要记得scp到其他节点。
10)JobHistoryServer必须开启,集群要重启的。
11)Mysql配置如果没有生效的话,默认使用derby数据库。
12)在本地修改完成的job配置,必须重新上传到HDFS。
13)将HDFS中上传的oozie配置文件下载下来查看是否有错误。
14)Linux用户名和Hadoop的用户名不一致。
最后
以上就是哭泣白开水最近收集整理的关于大数据云计算——Oozie组件Oozie的全部内容,更多相关大数据云计算——Oozie组件Oozie内容请搜索靠谱客的其他文章。
发表评论 取消回复