在之前的第一篇文章中,大致介绍了一点关于提高并发的参数,这次做一个详细的总结
1-先熟悉一下精简的配置文件core.json
"transport": { "channel": { "class": "com.alibaba.datax.core.transport.channel.memory.MemoryChannel", "speed": { "byte": 5242880, "record": 30 }, ... } ... }, "container": { ... "taskGroup": { "channel": 5 }, ... } job.json "setting": { "speed": { "channel":15, "byte" : 10485760, "record":300 } } ...
2-还是找到代码com.alibaba.datax.core.job.JobContainer中的start()启动任务流程的方法中
首先会定义 private int needChannelNumber;代表需要的channel个数
然后会对任务进行切分this.totalStage = this.split();获取这个needChannelNumber
注意这个方法 this.adjustChannelNumber();是获取needChannelNumber的方法
我们来看看他做了什么?还是先总结一下具体的流程
2.1-获取job配置的 job.setting.speed.byte 如果配置了这个参数且有效的话,接着获取全局配置 core.transport.channel.speed.byte 然后计算根据byte计算出需要的channelNumber needChannelNumberByByte = (int) (globalLimitedByteSpeed / channelLimitedByteSpeed);//job_speed/core_speed 2.2-接着获取job配置的job.setting.speed.record 如果配置了这个参数且有效的话,接着获取全局配置 core.transport.channel.speed.record 然后根据record计算出需要的channelNumber needChannelNumberByRecord = (int) (globalLimitedRecordSpeed / channelLimitedRecordSpeed); 然后比较needChannelNumberByByte和needChannelNumberByRecord 取较小值为最终的needChannelNumber this.needChannelNumber = needChannelNumberByByte < needChannelNumberByRecord ? needChannelNumberByByte : needChannelNumberByRecord; 2.3-如果配置了job.setting.speed.byte或者也配置job.setting.speed.record, 则此时可以退出返回上面获取到的needChannelNumber if (this.needChannelNumber < Integer.MAX_VALUE) { return; } 2.4-如果没有配置则获取job配置的job.setting.speed.channel 用这个值直接等于needChannelNumber,然后返回 到此needChannelNumber获取完毕
接下来就是具体的任务切分了,切分的方式不固定,但是会返回切分后的taskNumber
List<Configuration> readerTaskConfigs = this .doReaderSplit(this.needChannelNumber); int taskNumber = readerTaskConfigs.size();
3-进入schedule()方法
3.1-会重新定义needChannelNumber,根据切分任务数和上面计算出来的needChannelNumber
this.needChannelNumber = Math.min(this.needChannelNumber, taskNumber);//此处获取最小值变为needChannelNumber
3.2接下来进行任务配置,仔细看注释
/** * 通过获取配置信息得到每个taskGroup需要运行哪些tasks任务 * 总任务书/配置的任务组数目 获取需要定义几个taskGroupConfigs */ List<Configuration> taskGroupConfigs = JobAssignUtil.assignFairly(this.configuration, this.needChannelNumber, channelsPerTaskGroup);
此时会用到另一个配置参数:
core.container.taskGroup.channel,它的具体作用之前已经讲解过,再来看一遍
进入到assignFairly方法中,计算taskGroupNumber
int taskGroupNumber = (int) Math.ceil(1.0 * channelNumber / channelsPerTaskGroup);
获取到获取需要定义几个taskGroupConfigs
List<Configuration> taskGroupConfig = doAssign(resourceMarkAndTaskIdMap, configuration, taskGroupNumber);
3.3接下来就进入到 scheduler.schedule(taskGroupConfigs);方法中,进行具体的调度了
startAllTaskGroup(configurations);
此时就可以看到之前一系列操作带来的影响:
(1)根据taskGroupConfigs创建一个固定大小的线程池
(2)然后提交每一个 taskGroupConfig(包括多个 task 每个task 包含reader -->channel-->writer)
public void startAllTaskGroup(List<Configuration> configurations) { this.taskGroupContainerExecutorService = Executors .newFixedThreadPool(configurations.size()); for (Configuration taskGroupConfiguration : configurations) { TaskGroupContainerRunner taskGroupContainerRunner = newTaskGroupContainerRunner(taskGroupConfiguration); this.taskGroupContainerExecutorService.execute(taskGroupContainerRunner); } this.taskGroupContainerExecutorService.shutdown(); }
到此这几个不明确的参数,已经慢慢开始了解,接下来就是在实战中去应用了。
共同学习,写下你的评论
评论加载中...
作者其他优质文章