組件
- Reader:Reader為數據采集模塊,負責采集數據源的數據,將數據發送給Framework。
- Writer: Writer為數據寫入模塊,負責不斷向Framework取數據,并將數據寫入到目的端。
- Transformer:在數據同步、傳輸過程中,存在用戶對于數據傳輸進行特殊定制化的需求場景,包括裁剪列、轉換列等工作
-
Job
:Job
是DataX用以描述從一個源頭到一個目的端的同步作業,是DataX數據同步的最小業務單元。 -
Task
:Task
是把Job
拆分得到的最小執行單元。 -
JobContainer
:Job
執行器,負責Job
全局拆分、調度、前置語句和后置語句等工作的工作單元。 -
TaskGroupContainer
:TaskGroup
執行器,負責執行一組Task
的工作單元。 -
TaskGroup
: 描述的是一組Task
集合。在同一個TaskGroupContainer
執行下的Task
集合稱之為TaskGroup
參數
datax.py腳本接收參數
-j:jvm參數
--jobid: 在local與distribute模式下運行的作業唯一id
-m: 運行datax時的-Dmode參數,可選standalone, local, distribute
-p: 運行datax時的額外的附加的運行參數
-r: 查看reader模板,與-w一起使用,${datax.home}/plugin/reader/${該讀插件名稱}/plugin_job_template.json
-w: 查看writer模板,與-r一起使用,${datax.home}/plugin/reader/${該寫插件名稱}/plugin_job_template.json
C:/dev/Python27/python.exe datax.py -p"-Dlast=123 -Dend=456" --jobid=123456 C:/Users/Lenovo/Desktop/datax/jobConf/mysql2mysql.json
#分配了啟動 限制堆大小為1g,不可擴展,發生了 內存溢出錯誤dump路徑為C:\Users\Lenovo\PycharmProjects/log
java -server
-Xms1g -Xmx1g -XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=C:\Users\Lenovo\PycharmProjects/log
-Dloglevel=info -Dfile.encoding=UTF-8
-Dlogback.statusListenerClass=ch.qos.logback.core.status.NopStatusListener
-Djava.security.egd=file:///dev/urandom
-Ddatax.home=C:\Users\Lenovo\PycharmProjects
-Dlogback.configurationFile=C:\Users\Lenovo\PycharmProjects/conf/logback.xml
-classpath C:\Users\Lenovo\PycharmProjects/lib/*
-Dlog.file.name=onf\mysql2mysql_json
-Dlast=123 -Dend=456 com.alibaba.datax.core.Engine
-mode standalone -jobid 123456 -job C:\Users\Lenovo\Desktop\datax\jobConf\mysql2mysql.json
#默認以standalone模式啟動
datax.home=當前運行目錄
logback.configurationFile=${data.home}/conf/logback.xml
classpath=${datax.home}/lib/*
CoreConstant中會提取datax.home這個環境變量供全局使用,拼接成core.json,plugin.json的地址
- 一些環境變量
- mode:standalone, local, distribute 選擇作業運行模式
- jobid:在local與distribute模式下運行的作業唯一id
- job:作業配置文件路徑
- classpath
-
Standalone
: 單進程運行,沒有外部依賴。 -
Local
: 單進程運行,統計信息、錯誤信息匯報到集中存儲。 -
Distrubuted
: 分布式多進程運行,依賴DataX Service
服務。
運行流程
作業配置加載
通過作業配置文件路徑(-job參數)來加載作業配置文件。
CoreConstant通過環境變量獲取core配置文件路徑(datax.home拼接),加載core配置。
通過
job.content[0].reader/writer.name
讀取該作業的插件名,通過job.preHandler.pluginName
/job.postHandler.pluginName
讀取該作業的前置或后置處理插件名。通過CoreConstant獲取以上所有讀取到的插件名的絕對路徑。-
通過路徑來加載插件配置文件內容。插件的配置文件按如下約束。
{ "name": "mysqlwriter", "class": "com.alibaba.datax.plugin.writer.mysqlwriter.MysqlWriter", "description": "", "developer": "" }
在
Configuration.from(String json)
讀取任意配置文件時都會將${xxx}
或$xxx
占位符替換成xxx對應的環境變量。即-Dlast=123
使配置文件中${last}
替換成123
, 該邏輯存在StrUtil.replaceVariable(json)
中-
將core,job,plugin配置合并,生成全局使用的配置
Configuration
。{ "entry":{……}, "common":{……}, "core":{ "container":{ "job":{ "id": ${jobId}, ………………其他配置 } } }, "job":{……}, "plugin":{ "reader":{ "${pluginName}":{ "name": "", "class": "", "description": "", "developer": "" } }, "writer":{ "${pluginName}":{……} } } }
最后做過濾輸出和檢查配置
引擎啟動
- 從common取出需要的轉換格式
yyyy-MM-dd
或編碼UTF-8
,用于String與Date或Bytes的互相轉換 - 將配置
Configuration
傳入LoadUtil
Jar加載器,后面會使用LoadUtil進行插件Jar的動態加載。包括對每個插件的加載隔離機制和加載器緩沖的實現。 - 根據
core.container.model
判斷使用TaskGroupContainer
還是使用JobContainer
,默認使用JobContainer
- PerfTrace初始化,默認不使用PerfTrace,獲取
job.JobInfo
默認無該配置項, - 容器啟動
JobContainer
其中加載操作中的加載插件時:
為避免jar沖突,比如hbase可能有多個版本的讀寫依賴jar包,JobContainer和TaskGroupContainer
就需要脫離當前classLoader去加載這些jar包,執行完成后,又退回到原來classLoader上繼續執行接下來的代碼
每個Jar的執行加載都有單一的類加載器進行隔離加載,JarLoader會緩沖到jarLoaderCenter中
LoadUtil.getJarLoader 就會根據插件類型和名字去jarLoaderCenter中獲取加載器,獲取不到之后才會重新構造一個加載器
preHandle前置處理器:根據
job.preHandler.pluginName
加載已存在的插件,并執行插件的preHandler
方法-
init初始化:
根據
job.content[0].reader/writer.name
插件名來加載reader和writer插件,并保存reader/wirter PluginName
,賦值
Configuration
,賦值Job插件
本身和對端插件
的配置job.content[0].reader/writer.parameter
與對端的插件名子。并且執行他們的init方法。
prepare準備:執行reader/writer的
prepare
方法-
split切分任務:
-
根據
job.setting.speed.byte
,core.transport.channel.speed.byte
和job.setting.speed.record
,core.transport.channel.speed.record
的值計算出并發task數needChannelNumber
,具體算法作業byte限速除于單個channel的byte限速 得到 byte限速下的所需channel 作業record限速除于單個channel的record限速 得到record限速下的所需channel 對比兩個channel數取最小的作為needChannelNumber 若job.setting.speed.byte與job.setting.speed.record設置為空 則直接使用job.setting.speed.channel作為needChannelNumber 若都為空,則拋出異常
-
-
執行reader和writer的
split
方法,獲取經過split
每個Task的reader和writer的配置。執行reader和writer最細粒度的切分,需要注意的是,writer的切分結果要參照reader的切分結果, 達到切分后數目相等,才能滿足1:1的通道模型,所以這里可以將reader和writer的配置整合到一起。 計算出的needChannelNumber/tableNUm * 分裂因子 = 最終需要的Task數量
在split方法中需要根據tables數量,splitPk進行分隔任務,每個任務下的connection都會根據切分結果與column,where來生成一個querySql。
-
獲取作業的
transformer
配置,每個Task的reader和writer配置再加上該transformer
的配置合并。將原本的job.content
替換。即原本只有單個content,經過split后產生多個content,并為其設置遞增的taskId{ "job": { "content": [ { "taskId": 1, "reader": { "parameter": { "querySql": "" } }, "transformer":[], "writer": {} }, { "taskId": 2, "reader": {}, "transformer":[], "writer": {} }, { "taskId": 3, "reader": {}, "transformer":[], "writer": {} } ], "setting": { "speed": { "channel": "" } } } }
-
schedule調度:
parseAndGetResourceMarkAndTaskIdMap
:以reader.parameter.loadBalanceResourceMark
資源名做分組。得出一個 資源名稱 --> taskId(List) 的 map 映射關系。在split階段,會對插件的loadBalanceResourceMark
進行設置,通常是使用jdbc連接的host-
doAssign:根據
parseAndGetResourceMarkAndTaskIdMap
的結果,將需要運行Task按一個特定的規則分配到taskGroup中。每個TaskGroup都將獲得一份Configuration
克隆,設置每個taskConfiguration的content中的core.container.taskGroup.id
。并且修正job.content
,使他的配置文件回到單content狀態a 庫上有表:0, 1, 2 b 庫上有表:3, 4 c 庫上有表:5, 6, 7 如果有 4個 taskGroup 打豎遍歷添加到taskGroup 資源: 0 3 5|1 4 6| 2 7 taskGroup: 0 3 5 1|4 6 2 7 則 doAssign 后的結果為: taskGroup-0: 0, 4, taskGroup-1: 3, 6, taskGroup-2: 5, 2, taskGroup-3: 1, 7
-
adjustChannelNumPerTaskGroup:修正因為無法平均分配的少一個task的taskGroup的
core.container.taskGroup.channel
的更改3個task分配到2個taskGroup中時,會造成一個taskGroup的channel為2,一個taskGroup的channel為1 所以要將少了一個task的taskGroup的channel進行修正優化。
為每個taskGroup修正
core.container.job.mode
為standaloneStandAloneScheduler#registerCommunication:為每個taskGroup注冊Communication(狀態及統計信息交互)
StandAloneScheduler#startAllTaskGroup:為每個taskGroup創建
TaskGroupContainer
并代理到TaskGroupContainerRunner
啟動TaskGroupContainer
。其中動態加載transfomer,數據采集就在這個步驟之內。
post:執行reader和writer的
post
方法postHandle:根據
job.postHandler.pluginName
加載已存在的插件,并執行插件的postHandler
方法invokeHooks:根據
/hook
目錄調用外部hook
TaskGroupContainer
類圖
reader與writer的數據傳輸