大数据之Oozie——源码分析(一)程序入口
时间:2022-04-22
本文章向大家介绍大数据之Oozie——源码分析(一)程序入口,主要内容包括oozie工程结构、寻找源码入口、sqoop作业的提交、后续问题、参考、基本概念、基础应用、原理机制和需要注意的事项等,并结合实例形式分析了其使用技巧,希望通过本文能帮助到大家理解应用这部分内容。
工作中发现在oozie中使用sqoop与在shell中直接调度sqoop性能上有很大的差异。为了更深入的探索其中的缘由,开始了oozie的源码分析之路。今天第一天阅读源码,由于没有编译成功,不能运行测试用例,直接使用sublime肉眼阅读,还是挺费劲的。
虽然流程还不是顺畅,但是大体上的内容还算是了解了。
我这里使用的是oozie4.2的版本,之前稍微看过4.3版本的,源码上还是有一定的差异的。
看上面的图,大致理解oozie的过程是:
- oozie cli提交任务
- oozie server创建一个对应任务的client
- client去提交相应的任务
oozie工程结构
最重要的就是三个:
- 1 client 这是任务提交的入口
- 2 core 这是oozie的核心(在3中好像拆分成了core和server)
- 3 distro 这里保存了启动脚本
寻找源码入口
- 一种方式是直接以文件夹搜索main方法。
- 另一种是看它的启动脚本。
在启动脚本中oozie.cmd,有这样一句:
%JAVA_BIN% %JAVA_PROPERTIES% -cp %OOZIECPPATH% org.apache.oozie.cli.OozieCLI %OOZIE_PROPERTIES%
可见,入口在org.apache.oozie.cli.OozieCLI
这个类中,那就从它开始吧。
sqoop作业的提交
首先是OozieCLI的入口main方法:
public static void main(String[] args) {
//oozie方法的入口
if (!System.getProperties().containsKey(AuthOozieClient.USE_AUTH_TOKEN_CACHE_SYS_PROP)) {
System.setProperty(AuthOozieClient.USE_AUTH_TOKEN_CACHE_SYS_PROP, "true");
}
System.exit(new OozieCLI().run(args));
}
前面是一些认证的东西,可以忽略,直接进入run方法:
public synchronized int run(String[] args) {
//保证clent仅启动一次
if (used) {
throw new IllegalStateException("CLI instance already used");
}
used = true;
//创建参数解析器
final CLIParser parser = getCLIParser();
try {
final CLIParser.Command command = parser.parse(args);
String doAsUser = command.getCommandLine().getOptionValue(DO_AS_OPTION);
if (doAsUser != null) {
OozieClient.doAs(doAsUser, new Callable<Void>() {
@Override
public Void call() throws Exception {
processCommand(parser, command);
return null;
}
});
}
else {
processCommand(parser, command);
}
return 0;
}
...
}
主要的内容是在这个processCommand里面,processCommand会根据命令调用相应的命令方法:
public void processCommand(CLIParser parser, CLIParser.Command command) throws Exception {
if (command.getName().equals(HELP_CMD)) {
parser.showHelp(command.getCommandLine());
}
else if (command.getName().equals(JOB_CMD)) {
jobCommand(command.getCommandLine());
}
else if (command.getName().equals(JOBS_CMD)) {
jobsCommand(command.getCommandLine());
}
else if (command.getName().equals(ADMIN_CMD)) {
adminCommand(command.getCommandLine());
}
else if (command.getName().equals(VERSION_CMD)) {
versionCommand();
}
else if (command.getName().equals(VALIDATE_CMD)) {
validateCommand(command.getCommandLine());
}
else if (command.getName().equals(SLA_CMD)) {
slaCommand(command.getCommandLine());
}
else if (command.getName().equals(PIG_CMD)) {
scriptLanguageCommand(command.getCommandLine(), PIG_CMD);
}
else if (command.getName().equals(HIVE_CMD)) {
scriptLanguageCommand(command.getCommandLine(), HIVE_CMD);
}
else if (command.getName().equals(SQOOP_CMD)) {
sqoopCommand(command.getCommandLine());//我关注的sqoop在这里
}
else if (command.getName().equals(INFO_CMD)) {
infoCommand(command.getCommandLine());
}
else if (command.getName().equals(MR_CMD)){
mrCommand(command.getCommandLine());
}
}
在sqoopCommand方法里面,sqoop任务被提交:
private void sqoopCommand(CommandLine commandLine) throws IOException, OozieCLIException {
List<String> args = commandLine.getArgList();
if (args.size() > 0) {
// checking if args starts with -X (because CLIParser cannot check this)
if (!args.get(0).equals("-X")) {
throw new OozieCLIException("Unrecognized option: " + args.get(0) + " Expecting -X");
}
args.remove(0);
}
if (!commandLine.hasOption(SQOOP_COMMAND_OPTION)) {
throw new OozieCLIException("Need to specify -command");
}
if (!commandLine.hasOption(CONFIG_OPTION)) {
throw new OozieCLIException("Need to specify -config <configfile>");
}
try {
XOozieClient wc = createXOozieClient(commandLine);
Properties conf = getConfiguration(wc, commandLine);
String[] command = commandLine.getOptionValues(SQOOP_COMMAND_OPTION);
System.out.println(JOB_ID_PREFIX + wc.submitSqoop(conf, command, args.toArray(new String[args.size()])));
}
catch (OozieClientException ex) {
throw new OozieCLIException(ex.toString(), ex);
}
}
最重要的内容就在这几行:
XOozieClient wc = createXOozieClient(commandLine);
Properties conf = getConfiguration(wc, commandLine);
String[] command = commandLine.getOptionValues(SQOOP_COMMAND_OPTION);
System.out.println(JOB_ID_PREFIX + wc.submitSqoop(conf, command, args.toArray(new String[args.size()])));
其中wc.submitSqoop提交了sqoop的任务。
后续问题
- 1 任务提交到了哪里?
- 2 在提交任务的时候都做了很么?
- 3 如何在mapreduce开启一个新的sqoop的?
- 4 为什么在yarn中可以同时看到两个应用,一个oozie,一个是sqoop
参考
- 【数据科学】数据科学中的 Spark 入门
- 【自然框架】QuickPager分页控件的单独的源码 V2.0.4.2。
- 用 iPhoneX 的 FaceID 刷脸解锁真的靠谱吗?
- 【自然框架】用CMS的栏目举例,聊一聊从“一层”到“三层”的变化
- java如何自定义鼠标指针
- 面向对象最重要的是“抽象”,三层最重要的也是“抽象”,没有抽象就不是真正的面向对象、三层。
- 唯一不变的就是一直在变”--“数据”的华丽“变身术”
- 借用 疯狂秀才 的页面,修改了一下自然框架后台管理的页面。
- PDF.NET(PWMIS数据开发框架)之SQL-MAP目标和规范
- PDF.NET数据开发框架 之SQL-MAP使用存储过程
- 用接口实现事件的一种方法,只是玩玩。
- 国内研究人员首次Wifi重大漏洞利用实现 | Krack攻击测试套件打包
- 想成为优秀程序员必知的要点
- Attribute(特性),怎么用才更好?
- JavaScript 教程
- JavaScript 编辑工具
- JavaScript 与HTML
- JavaScript 与Java
- JavaScript 数据结构
- JavaScript 基本数据类型
- JavaScript 特殊数据类型
- JavaScript 运算符
- JavaScript typeof 运算符
- JavaScript 表达式
- JavaScript 类型转换
- JavaScript 基本语法
- JavaScript 注释
- Javascript 基本处理流程
- Javascript 选择结构
- Javascript if 语句
- Javascript if 语句的嵌套
- Javascript switch 语句
- Javascript 循环结构
- Javascript 循环结构实例
- Javascript 跳转语句
- Javascript 控制语句总结
- Javascript 函数介绍
- Javascript 函数的定义
- Javascript 函数调用
- Javascript 几种特殊的函数
- JavaScript 内置函数简介
- Javascript eval() 函数
- Javascript isFinite() 函数
- Javascript isNaN() 函数
- parseInt() 与 parseFloat()
- escape() 与 unescape()
- Javascript 字符串介绍
- Javascript length属性
- javascript 字符串函数
- Javascript 日期对象简介
- Javascript 日期对象用途
- Date 对象属性和方法
- Javascript 数组是什么
- Javascript 创建数组
- Javascript 数组赋值与取值
- Javascript 数组属性和方法
- Android自定义View实现圆环带数字百分比进度条
- Python按照list dict key进行排序过程解析
- Java并发编程的艺术(一)
- Python3.7 读取音频根据文件名生成脚本的代码
- python如何判断IP地址合法性
- 从*Application.java解读SpringBoot
- django实现后台显示媒体文件
- 服务发现与消费--Eureka与Ribbon的联手出击
- 自我加戏,在自闭的边缘尝试高可用的Eureka
- 视频直播系统源码,图片叠加
- SpringCloud初体验--Hello Eureka
- Android自定义View实现水平带数字百分比进度条
- AndResGuard编译速度优化
- Android自定义带拼音音调Textview
- Android仿音乐播放器带进度的播放暂停按钮