datax源码解析

本文详细解析了DataX的执行流程,从入口类开始,包括配置封装、JobContainer和TaskGroupContainer容器的启动,重点介绍了TaskExecutor类在任务调度和执行中的作用。DataX通过PluginLoader加载插件,初始化Job和Task,根据配置进行任务切分,最后利用TaskExecutor执行读写操作,实现数据同步。
摘要由CSDN通过智能技术生成
具体流程代码
step1: 入口

知识点:

  • 首先入口在com.alibaba.datax.core.Engine类,命令行参数有-job-jobid-mode
            options.addOption("job", true, "Job config.");
            options.addOption("jobid", true, "Job unique id.");
            options.addOption("mode", true, "Job runtime mode.");

在这里插入图片描述

step2: 封装配置
  • entry()先获取命令行参数-mode, -jobid, -job
  • 解析系统配置的json和用户自己编辑的json文件配置,然后统一封装成Configuration类,传给Engine.start()使用。

在这里插入图片描述

  • 读取核心配置文件core.json以及对应读写的plugin.json
       configuration.merge(
                // 读取核心core.json
        ConfigParser.parseCoreConfig(CoreConstant.DATAX_CONF_PATH),
                false);
        // todo config优化,只捕获需要的plugin
        String readerPluginName = configuration.getString(
                CoreConstant.DATAX_JOB_CONTENT_READER_NAME);
        String writerPluginName = configuration.getString(
                CoreConstant.DATAX_JOB_CONTENT_WRITER_NAME);

  • 这里获取的参数jobid,如果用户没有明确的指定,则datax.py会指定jobid默认值为-1

在这里插入图片描述

Enginestart()主要完成:

  1. 首先往配置类中绑定一些信息,比如ColumnCast等转换信息。
  2. 初始化PluginLoader(插件加载器), 用来获取插件配置
  3. 创建JobContainer,并且启动,JobContainer是一次数据同步job的运行容器.
public void start(Configuration allConf) {
   

    // 绑定column转换信息 包括json中的字符信息
    ColumnCast.bind(allConf);

    /**
     * 初始化PluginLoader,可以获取各种插件配置
     */
    LoadUtil.bind(allConf);

    // DATAX_CORE_CONTAINER_MODEL: core.container.model
    boolean isJob = !("taskGroup".equalsIgnoreCase(allConf
            .getString(CoreConstant.DATAX_CORE_CONTAINER_MODEL)));
    //JobContainer会在schedule后再行进行设置和调整值
    int channelNumber =0;
    // 抽象容器类 有两种实现 JobContainer和TaskGroupContainer
    AbstractContainer container;
    long instanceId;
    int taskGroupId = -1;
    if (isJob) {
   
        allConf.set(CoreConstant.DATAX_CORE_CONTAINER_JOB_MODE, RUNTIME_MODE);
        container = new JobContainer(allConf);
        instanceId = allConf.getLong(
                CoreConstant.DATAX_CORE_CONTAINER_JOB_ID, 0);

    } else {
   
        // 基本用不到
        container = new TaskGroupContainer(allConf);
        instanceId = allConf.getLong(
                CoreConstant.DATAX_CORE_CONTAINER_JOB_ID);
        taskGroupId = allConf.getInt(
                CoreConstant.DATAX_CORE_CONTAINER_TASKGROUP_ID);
        channelNumber = allConf.getInt(
                CoreConstant.DATAX_CORE_CONTAINER_TASKGROUP_CHANNEL);
    }

    //缺省打开perfTrace
    boolean traceEnable = allConf.getBool(CoreConstant.DATAX_CORE_CONTAINER_TRACE_ENABLE, true);
    boolean perfReportEnable = allConf.getBool(CoreConstant.DATAX_CORE_REPORT_DATAX_PERFLOG, true);

    //standalone模式的 datax shell任务不进行汇报
    if(instanceId == -1){
   
        perfReportEnable = false;
    }

    // todo 不太明白这里要做什么
    int priority = 0;
    try {
   
        priority = Integer.parseInt(System.getenv("SKYNET_PRIORITY"));
    }catch (NumberFormatException e){
   
        LOG.warn("prioriy set to 0, because NumberFormatException, the value is: "+System.getProperty("PROIORY"));
    }

    // 总配置文件中提取出跟一个job有关的配置
    Configuration jobInfoConfig = allConf.getConfiguration(CoreConstant.DATAX_JOB_JOBINFO);
    //初始化PerfTrace
    PerfTrace perfTrace = PerfTrace.getInstance(isJob, instanceId, taskGroupId, priority, traceEnable);
    perfTrace.setJobInfo(jobInfoConfig,perfReportEnable,channelNumber);
    container.start();

}
step3: 初始化并启动JobContainer容器
  • 根据配置初始化不同的容器(JobContainerTaskGroupContainer)并启动,一般都使用Job容器,check job model first,位置com.alibaba.datax.core.JobContainer#start
  • job实例运行在jobContainer容器中,它是所有任务的master,负责初始化、拆分、调度、运行、回收、监控和汇报,但它并不做实际的数据同步操作。
  • JobContainer主要负责的工作全部在start()中,包括initpreparesplitscheduler
  • init()负责ReaderWriter插件的初始化和热加载。
  • prepare()方法做Read、Write前置准备(如Presql等)
  • split()方法根据配置的并发参数(channelbytesRecord必须配置其一,优先级bytes>=Record>channel),对job进行切分,返回多个task的配置列表。
  • scheduler()是真正的调度任务与运行,task的调度方式按照轮询式。
    @Override
    public void start() {
   
        LOG.info("DataX jobContainer starts job.");
        boolean hasException = false;
        boolean isDryRun = false;
        try {
   
            // 计时开始
            this.startTimeStamp = System.currentTimeMillis();
            // 预检查
            isDryRun = configuration.getBool(CoreConstant.DATAX_JOB_SETTING_DRYRUN, false);
            if(isDryRun) {
   
                ///...省略,几乎用不到
            } else {
   
                //clone一份配置,因为要做修改
                userConf = configuration.clone();
                //前置处理
                this.preHandle();
                //初始化read和write插件
                this.init();
                //进行插件的前置操作,有些插件不需要
                this.prepare();
                //切分任务,为并发做准备 主要adjustChannelNumber 
                this.totalStage = this.split();
                //任务调度,启动任务 轮询式
                this.schedule();
                //和preparea对应,插件的后置操作
                this.post(
  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值