在之前的第一篇文章中,大致介绍了一点关于提高并发的参数,这次做一个详细的总结
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
needChannelNumberByByte : needChannelNumberByRecord;
2.3-如果配置了job.setting.speed.byte或者也配置job.setting.speed.record,
则此时可以退出返回上面获取到的needChannelNumber
if (this.needChannelNumber
return;
}
2.4-如果没有配置则获取job配置的job.setting.speed.channel
用这个值直接等于needChannelNumber,然后返回
到此needChannelNumber获取完毕
接下来就是具体的任务切分了,切分的方式不固定,但是会返回切分后的taskNumberList 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 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 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 configurations) {
this.taskGroupContainerExecutorService = Executors
.newFixedThreadPool(configurations.size());
for (Configuration taskGroupConfiguration : configurations) {
TaskGroupContainerRunner taskGroupContainerRunner = newTaskGroupContainerRunner(taskGroupConfiguration);
this.taskGroupContainerExecutorService.execute(taskGroupContainerRunner);
}
this.taskGroupContainerExecutorService.shutdown();
}
到此这几个不明确的参数,已经慢慢开始了解,接下来就是在实战中去应用了。