sqoop 抽取源码流程分析( 二 ) 导入工具代码结构分析
来源:互联网 发布:知乎 正楷 字帖推荐 编辑:程序博客网 时间:2024/06/06 10:51
1.导入工具的起点importTool.java
抽取就是从这个地方开始的,重点是其中的run() 方法
@Override /** {@inheritDoc} */ public int run(SqoopOptions options) { ......... codeGenerator.setManager(manager); try { if (options.doHiveImport()) { hiveImport = new HiveImport(options, manager, options.getConf(), false); } // Import a single table (or query) the user specified. importTable(options, options.getTableName(), hiveImport);
这个manager 的作用就是管理下面各种数据库的访问,比如你是要访问mysql 呢,还是oracle 呢。
这个代码重点是在manager 这个地方,这个是什么时候初始化的呢
protected ConnManager manager;
1.1 诞生之地
这个就是链接管理,那么这个东东的初始化在哪里呢?通过尾随其回家的路,终于嘿嘿。。。
public abstract class BaseSqoopTool extends com.cloudera.sqoop.tool.SqoopTool {
这就是manager 的老巢了。
进去看看
*/ protected boolean init(SqoopOptions sqoopOpts) { // Get the connection to the database. try { JobData data = new JobData(sqoopOpts, this); this.manager = new ConnFactory(sqoopOpts.getConf()).getManager(data); return true; } catch (Exception e) { LOG.error("Got error creating database manager: " + StringUtils.stringifyException(e)); if (System.getProperty(Sqoop.SQOOP_RETHROW_PROPERTY) != null) { throw new RuntimeException(e); } } return false; }
这就是他的出生之地了
this.manager = new ConnFactory(sqoopOpts.getConf()).getManager(data);
1.2 工厂
public class ConnFactory {
在这个类里面,可以看到默认有两个工厂实现类
当然,也可以通过配置文件指定自定义的工厂实现类,相关代码也在这个类中可以找到
public static final String[] DEFAULT_FACTORY_CLASS_NAMES_ARR = {OraOopManagerFactory.class.getName(), DefaultManagerFactory.class.getName(), }; ...... private List<ManagerFactory> factories; // 存储实例化的工厂对象
除了这两个默认的工厂,还可以利用配置文件来进行扩展,一般是在conf 目录下,利用manager.d 目录提供的配置文件来
控制你要提供的工厂,具体的请结合ConnFactory的代码来看
ConnFactory 的对外接口
public ConnManager getManager(JobData data) throws IOException {
根据配置信息来构造出一个连接器供抽取使用。
下面分别对这两个默认工厂的实现进行介绍
1.2.1 缺省工厂DefaultManagerFactory
public class DefaultManagerFactory extends com.cloudera.sqoop.manager.ManagerFactory { ......... public ConnManager accept(JobData data) { SqoopOptions options = data.getSqoopOptions(); String scheme = extractScheme(options); if (null == scheme) { // We don't know if this is a mysql://, hsql://, etc. // Can't do anything with this. LOG.warn("Null scheme associated with connect string."); return null; } LOG.debug("Trying with scheme: " + scheme); if (scheme.equals("jdbc:mysql:")) { if (options.isDirect()) { return new DirectMySQLManager(options); } else { return new MySQLManager(options); } } else if (scheme.equals("jdbc:postgresql:")) { if (options.isDirect()) { return new DirectPostgresqlManager(options); } else { return new PostgresqlManager(options); } } else if (scheme.startsWith("jdbc:hsqldb:")) { return new HsqldbManager(options); } else if (scheme.startsWith("jdbc:oracle:")) { return new OracleManager(options); } else if (scheme.startsWith("jdbc:sqlserver:")) { return new SQLServerManager(options); } else if (scheme.startsWith("jdbc:jtds:sqlserver:")) { return new SQLServerManager( "net.sourceforge.jtds.jdbc.Driver", options); } else if (scheme.startsWith("jdbc:db2:")) { return new Db2Manager(options); } else if (scheme.startsWith("jdbc:netezza:")) { if (options.isDirect()) { return new DirectNetezzaManager(options); } else { return new NetezzaManager(options); } } else if (scheme.startsWith("jdbc:cubrid:")) { return new CubridManager(options); } else { return null; } }protected String extractScheme(SqoopOptions options) {.............. } return connectStr.substring(0, schemeStopIdx); }}
String scheme = extractScheme(options);
取得连接的参数,然后判断是属于那种类型的数据库链接,是mysql 还是oracle.
OracleManager.java 或 MySQLManager.java 等
然后制造出不同数据库的manager. 到这里,工厂的使命就完成了
1.2.2 ORA 工厂 OraOopManagerFactory
TBD
2. 再回 importTool
还是在run 方法里面
importTable(options, options.getTableName(), hiveImport);
再看其实现里面有这么一段
if (null != tableName) { manager.importTable(context); } else { manager.importQuery(context); }
这里的importTable 或者 importQuery 就是由工厂制造出来具体的类来实现了,比如OracleManager.java 或 MySQLManager.java
3. 进入抽取阶段
3.1 具体实现的继承关系
public abstract class SqlManager extends com.cloudera.sqoop.manager.ConnManager {public abstract class SqlManager extends org.apache.sqoop.manager.SqlManager {public class GenericJdbcManager extends com.cloudera.sqoop.manager.SqlManager {public class GenericJdbcManager extends org.apache.sqoop.manager.GenericJdbcManager {
GenericJdbcManager下面有多种数据库进行的子类化
public abstract class CatalogQueryManager extends com.cloudera.sqoop.manager.GenericJdbcManager {
其他的如OracleManager , MySqlManager 应该去代码里面实现。
这是多少层继承关系啊
好了,那么importQuery() 的实现是在SqlManager 这个类里面
3.2 importQuery的实现
public void importQuery(com.cloudera.sqoop.manager.ImportJobContext context) throws IOException, ImportException { ImportJobBase importer;...... if (!opts.isBulkLoadEnabled()){ importer = new HBaseImportJob(opts, context); } else { importer = new HBaseBulkImportJob(opts, context); } } else if (opts.getAccumuloTable() != null) { // Import to Accumulo. ...... importer = new AccumuloImportJob(opts, context); } else { // Import to HDFS. importer = new DataDrivenImportJob(opts, context.getInputFormat(),context); } importer.runImport(null, jarFile, splitCol, opts.getConf());
这里可以看出,导出主要是有三种存储类型,HBASE 、Accumulo 和 HDFS
那么hive 当然是算导入到hdfs 了,所以重点还是在 DataDrivenImportJob上面
4. 抽取到hdfs
4.1 继承关系
public class DataDrivenImportJob extends org.apache.sqoop.mapreduce.DataDrivenImportJob {public class DataDrivenImportJob extends ImportJobBase {public class ImportJobBase extends org.apache.sqoop.mapreduce.ImportJobBase {public class ImportJobBase extends JobBase {
ImportJobBase 提供了 runImport 方法的实现
public void runImport(String tableName, String ormJarFile, String splitByCol, Configuration conf) throws IOException, ImportException { ................... if (null != tableName) { LOG.info("Beginning import of " + tableName); } else { LOG.info("Beginning query import."); } .................... 上传mapred 包 loadJars(conf, ormJarFile, tableClassName);创建mapred job Job job = createJob(conf); try { // Set the external jar to use for the job. job.getConfiguration().set("mapred.jar", ormJarFile); if (options.getMapreduceJobName() != null) { job.setJobName(options.getMapreduceJobName()); } propagateOptionsToJob(job); // 设置输入格式 configureInputFormat(job, tableName, tableClassName, splitByCol); // 设置输出格式 configureOutputFormat(job, tableName, tableClassName); configureMapper(job, tableName, tableClassName); configureNumTasks(job); cacheJars(job, getContext().getConnManager()); jobSetup(job); setJob(job);// 运行mapreduce job. boolean success = runJob(job); if (!success) { throw new ImportException("Import job failed!"); } completeImport(job);................
- sqoop 抽取源码流程分析( 二 ) 导入工具代码结构分析
- sqoop 抽取源码流程分析( 三 ) 代码生成工具分析
- sqoop 抽取源码流程分析(一) 主流程分析以及各种插件
- MySQL源码分析——代码结构与基本流程
- ffmpeg源码分析与应用示例(二)——代码抽取的意义
- 导入sqoop代码到eclipse报错问题分析
- libevent源码分析--代码结构
- FreeRTOS源码分析-代码结构
- Uboot 源码分析----代码整体结构分析
- Uboot 源码分析----代码整体结构分析
- rtpengine源码结构分析及交互流程
- 代码流程分析二:Settings-蓝牙分析-switch开关分析
- vlc源码分析(二) 播放流程
- vlc源码分析(二) 播放流程
- amoeba源码分析(二)-amoeba模块以及源码结构分析
- sqoop导入数据地图-reduce job分析
- Tor源码分析二 -- 目录结构
- WebRTC源码分析二:音频模块结构
- 第二周【项目3 - 体验复杂度】
- 使用Workbench创建数据库和表
- LeetCode Implement Queue using Stacks
- C++Primer第五版 3.3.2节练习
- LeetCode 1 Two Sum
- sqoop 抽取源码流程分析( 二 ) 导入工具代码结构分析
- linux iscsi 配置过程详解--包括自动挂载文件系统
- 第2周项目2程序的多文件组织
- android Studio优化
- 去哪网2015面试题:[编程题] 首个重复字符
- 不给人设定角色
- swift详解之二十七------------自定义UINavigationController的push和pop动画
- SQL查询每个分组的前N条记录
- sqoop 抽取源码流程分析( 三 ) 代码生成工具分析