datax啟動(dòng)流程

組件

datax采集流程
  • Reader:Reader為數(shù)據(jù)采集模塊,負(fù)責(zé)采集數(shù)據(jù)源的數(shù)據(jù),將數(shù)據(jù)發(fā)送給Framework。
  • Writer: Writer為數(shù)據(jù)寫入模塊,負(fù)責(zé)不斷向Framework取數(shù)據(jù),并將數(shù)據(jù)寫入到目的端。
  • Transformer:在數(shù)據(jù)同步、傳輸過(guò)程中,存在用戶對(duì)于數(shù)據(jù)傳輸進(jìn)行特殊定制化的需求場(chǎng)景,包括裁剪列、轉(zhuǎn)換列等工作
  • Job: Job是DataX用以描述從一個(gè)源頭到一個(gè)目的端的同步作業(yè),是DataX數(shù)據(jù)同步的最小業(yè)務(wù)單元。
  • Task: Task是把Job拆分得到的最小執(zhí)行單元。
  • JobContainer: Job執(zhí)行器,負(fù)責(zé)Job全局拆分、調(diào)度、前置語(yǔ)句和后置語(yǔ)句等工作的工作單元。
  • TaskGroupContainer: TaskGroup執(zhí)行器,負(fù)責(zé)執(zhí)行一組Task的工作單元。
  • TaskGroup: 描述的是一組Task集合。在同一個(gè)TaskGroupContainer執(zhí)行下的Task集合稱之為TaskGroup

參數(shù)

datax.py腳本接收參數(shù)
-j:jvm參數(shù)
--jobid: 在local與distribute模式下運(yùn)行的作業(yè)唯一id
-m: 運(yùn)行datax時(shí)的-Dmode參數(shù),可選standalone, local, distribute 
-p: 運(yùn)行datax時(shí)的額外的附加的運(yùn)行參數(shù)
-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

#分配了啟動(dòng) 限制堆大小為1g,不可擴(kuò)展,發(fā)生了 內(nèi)存溢出錯(cuò)誤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
#默認(rèn)以standalone模式啟動(dòng)
datax.home=當(dāng)前運(yùn)行目錄
logback.configurationFile=${data.home}/conf/logback.xml 
classpath=${datax.home}/lib/*


CoreConstant中會(huì)提取datax.home這個(gè)環(huán)境變量供全局使用,拼接成core.json,plugin.json的地址

  • 一些環(huán)境變量
  • mode:standalone, local, distribute 選擇作業(yè)運(yùn)行模式
  • jobid:在local與distribute模式下運(yùn)行的作業(yè)唯一id
  • job:作業(yè)配置文件路徑
  • classpath
  • Standalone: 單進(jìn)程運(yùn)行,沒(méi)有外部依賴。
  • Local: 單進(jìn)程運(yùn)行,統(tǒng)計(jì)信息、錯(cuò)誤信息匯報(bào)到集中存儲(chǔ)。
  • Distrubuted: 分布式多進(jìn)程運(yùn)行,依賴DataX Service服務(wù)。

運(yùn)行流程

引擎啟動(dòng)后jobContainer啟動(dòng)流程

作業(yè)配置加載

  • 通過(guò)作業(yè)配置文件路徑(-job參數(shù))來(lái)加載作業(yè)配置文件。

  • CoreConstant通過(guò)環(huán)境變量獲取core配置文件路徑(datax.home拼接),加載core配置。

  • 通過(guò)job.content[0].reader/writer.name讀取該作業(yè)的插件名,通過(guò)job.preHandler.pluginName/job.postHandler.pluginName讀取該作業(yè)的前置或后置處理插件名。通過(guò)CoreConstant獲取以上所有讀取到的插件名的絕對(duì)路徑。

  • 通過(guò)路徑來(lái)加載插件配置文件內(nèi)容。插件的配置文件按如下約束。

    {
        "name": "mysqlwriter",
        "class": "com.alibaba.datax.plugin.writer.mysqlwriter.MysqlWriter",
        "description": "",
        "developer": ""
    }
    
  • Configuration.from(String json)讀取任意配置文件時(shí)都會(huì)將${xxx}$xxx占位符替換成xxx對(duì)應(yīng)的環(huán)境變量。即-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}":{……}
            }
      }
    }
    
  • 最后做過(guò)濾輸出和檢查配置

引擎啟動(dòng)

  • 從common取出需要的轉(zhuǎn)換格式yyyy-MM-dd或編碼UTF-8,用于String與Date或Bytes的互相轉(zhuǎn)換
  • 將配置Configuration傳入LoadUtil Jar加載器,后面會(huì)使用LoadUtil進(jìn)行插件Jar的動(dòng)態(tài)加載。包括對(duì)每個(gè)插件的加載隔離機(jī)制和加載器緩沖的實(shí)現(xiàn)。
  • 根據(jù)core.container.model判斷使用TaskGroupContainer還是使用JobContainer,默認(rèn)使用JobContainer
  • PerfTrace初始化,默認(rèn)不使用PerfTrace,獲取job.JobInfo 默認(rèn)無(wú)該配置項(xiàng),
  • 容器啟動(dòng)

JobContainer

其中加載操作中的加載插件時(shí):

為避免jar沖突,比如hbase可能有多個(gè)版本的讀寫依賴jar包,JobContainer和TaskGroupContainer
就需要脫離當(dāng)前classLoader去加載這些jar包,執(zhí)行完成后,又退回到原來(lái)classLoader上繼續(xù)執(zhí)行接下來(lái)的代碼

每個(gè)Jar的執(zhí)行加載都有單一的類加載器進(jìn)行隔離加載,JarLoader會(huì)緩沖到j(luò)arLoaderCenter中

LoadUtil.getJarLoader 就會(huì)根據(jù)插件類型和名字去jarLoaderCenter中獲取加載器,獲取不到之后才會(huì)重新構(gòu)造一個(gè)加載器
類加載器隔離
  • preHandle前置處理器:根據(jù)job.preHandler.pluginName加載已存在的插件,并執(zhí)行插件的preHandler方法

  • init初始化:

    1. 根據(jù)job.content[0].reader/writer.name插件名來(lái)加載reader和writer插件,并保存reader/wirter PluginName,

    2. 賦值Configuration,賦值Job插件本身和對(duì)端插件的配置job.content[0].reader/writer.parameter與對(duì)端的插件名子。并且執(zhí)行他們的init方法。

  • prepare準(zhǔn)備:執(zhí)行reader/writer的prepare方法

  • split切分任務(wù):

    1. 根據(jù)job.setting.speed.bytecore.transport.channel.speed.bytejob.setting.speed.record,core.transport.channel.speed.record的值計(jì)算出并發(fā)task數(shù)needChannelNumber,具體算法

      作業(yè)byte限速除于單個(gè)channel的byte限速 得到 byte限速下的所需channel
      作業(yè)record限速除于單個(gè)channel的record限速 得到record限速下的所需channel
      對(duì)比兩個(gè)channel數(shù)取最小的作為needChannelNumber
      
      若job.setting.speed.byte與job.setting.speed.record設(shè)置為空
      則直接使用job.setting.speed.channel作為needChannelNumber
      若都為空,則拋出異常
      
  1. 執(zhí)行reader和writer的split方法,獲取經(jīng)過(guò)split每個(gè)Task的reader和writer的配置。

    執(zhí)行reader和writer最細(xì)粒度的切分,需要注意的是,writer的切分結(jié)果要參照reader的切分結(jié)果,
    達(dá)到切分后數(shù)目相等,才能滿足1:1的通道模型,所以這里可以將reader和writer的配置整合到一起。
    
    計(jì)算出的needChannelNumber/tableNUm * 分裂因子 = 最終需要的Task數(shù)量
    
切分方式
 在split方法中需要根據(jù)tables數(shù)量,splitPk進(jìn)行分隔任務(wù),每個(gè)任務(wù)下的connection都會(huì)根據(jù)切分結(jié)果與column,where來(lái)生成一個(gè)querySql。
  1. 獲取作業(yè)的transformer配置,每個(gè)Task的reader和writer配置再加上該transformer的配置合并。將原本的job.content替換。即原本只有單個(gè)content,經(jīng)過(guò)split后產(chǎn)生多個(gè)content,并為其設(shè)置遞增的taskId

    {
        "job": {
            "content": [
                {
                    "taskId": 1,
                    "reader": {
                        "parameter": {
                            "querySql": ""
                        }
                    },
                    "transformer":[],
                    "writer": {}
                },
                 {
                    "taskId": 2,
                    "reader": {},
                    "transformer":[],
                    "writer": {}
                },
                {
                    "taskId": 3,
                    "reader": {},
                    "transformer":[],
                    "writer": {}
                }
            ],
            "setting": {
                "speed": {
                    "channel": ""
                }
         }
        }
    }
    
  • schedule調(diào)度:

    1. parseAndGetResourceMarkAndTaskIdMap:以reader.parameter.loadBalanceResourceMark資源名做分組。得出一個(gè) 資源名稱 --> taskId(List) 的 map 映射關(guān)系。在split階段,會(huì)對(duì)插件的loadBalanceResourceMark進(jìn)行設(shè)置,通常是使用jdbc連接的host

    2. doAssign:根據(jù)parseAndGetResourceMarkAndTaskIdMap的結(jié)果,將需要運(yùn)行Task按一個(gè)特定的規(guī)則分配到taskGroup中。每個(gè)TaskGroup都將獲得一份Configuration克隆,設(shè)置每個(gè)taskConfiguration的content中的core.container.taskGroup.id。并且修正job.content,使他的配置文件回到單content狀態(tài)

      a 庫(kù)上有表:0, 1, 2
      b 庫(kù)上有表:3, 4
      c 庫(kù)上有表:5, 6, 7
      
      如果有 4個(gè) taskGroup
      打豎遍歷添加到taskGroup 
      資源: 0 3 5|1 4 6| 2 7
      taskGroup: 0 3 5 1|4 6 2 7
      
      則 doAssign 后的結(jié)果為:
      taskGroup-0: 0,  4,
      taskGroup-1: 3,  6,
      taskGroup-2: 5,  2,
      taskGroup-3: 1,  7
      
  1. adjustChannelNumPerTaskGroup:修正因?yàn)闊o(wú)法平均分配的少一個(gè)task的taskGroup的core.container.taskGroup.channel的更改

    3個(gè)task分配到2個(gè)taskGroup中時(shí),會(huì)造成一個(gè)taskGroup的channel為2,一個(gè)taskGroup的channel為1
    所以要將少了一個(gè)task的taskGroup的channel進(jìn)行修正優(yōu)化。
    
  2. 為每個(gè)taskGroup修正core.container.job.mode為standalone

  3. StandAloneScheduler#registerCommunication:為每個(gè)taskGroup注冊(cè)Communication(狀態(tài)及統(tǒng)計(jì)信息交互)

  4. StandAloneScheduler#startAllTaskGroup:為每個(gè)taskGroup創(chuàng)建TaskGroupContainer并代理到TaskGroupContainerRunner啟動(dòng)TaskGroupContainer。其中動(dòng)態(tài)加載transfomer,數(shù)據(jù)采集就在這個(gè)步驟之內(nèi)。

  • post:執(zhí)行reader和writer的post方法

  • postHandle:根據(jù)job.postHandler.pluginName加載已存在的插件,并執(zhí)行插件的postHandler方法

  • invokeHooks:根據(jù)/hook目錄調(diào)用外部hook

TaskGroupContainer

類圖

reader與writer的數(shù)據(jù)傳輸

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 230,825評(píng)論 6 546
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡,警方通過(guò)查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 99,814評(píng)論 3 429
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái),“玉大人,你說(shuō)我怎么就攤上這事?!?“怎么了?”我有些...
    開(kāi)封第一講書人閱讀 178,980評(píng)論 0 384
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)。 經(jīng)常有香客問(wèn)我,道長(zhǎng),這世上最難降的妖魔是什么? 我笑而不...
    開(kāi)封第一講書人閱讀 64,064評(píng)論 1 319
  • 正文 為了忘掉前任,我火速辦了婚禮,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 72,779評(píng)論 6 414
  • 文/花漫 我一把揭開(kāi)白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上,一...
    開(kāi)封第一講書人閱讀 56,109評(píng)論 1 330
  • 那天,我揣著相機(jī)與錄音,去河邊找鬼。 笑死,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 44,099評(píng)論 3 450
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來(lái)了?” 一聲冷哼從身側(cè)響起,我...
    開(kāi)封第一講書人閱讀 43,287評(píng)論 0 291
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒(méi)想到半個(gè)月后,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 49,799評(píng)論 1 338
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 41,515評(píng)論 3 361
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 43,750評(píng)論 1 375
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 39,221評(píng)論 5 365
  • 正文 年R本政府宣布,位于F島的核電站,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 44,933評(píng)論 3 351
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開(kāi)封第一講書人閱讀 35,327評(píng)論 0 28
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)。三九已至,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開(kāi)封第一講書人閱讀 36,667評(píng)論 1 296
  • 我被黑心中介騙來(lái)泰國(guó)打工, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 52,492評(píng)論 3 400
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 48,703評(píng)論 2 380

推薦閱讀更多精彩內(nèi)容

  • 開(kāi)篇 ?最早接觸DataX是在前阿里同事在現(xiàn)在的公司引入的時(shí)候提到的,一直想抽空好好看看這部分代碼,因?yàn)镈ataX...
    晴天哥_王志閱讀 42,211評(píng)論 16 45
  • 概覽 DataX 是一個(gè)異構(gòu)數(shù)據(jù)源離線同步工具,致力于實(shí)現(xiàn)包括關(guān)系型數(shù)據(jù)庫(kù)(MySQL、Oracle等)、HDFS...
    tracy_668閱讀 709評(píng)論 0 1
  • Datax的執(zhí)行過(guò)程 要想進(jìn)行調(diào)優(yōu),一般先要了解執(zhí)行過(guò)程,執(zhí)行過(guò)程如下: 過(guò)程詳細(xì)說(shuō)明如下: DataX完成單個(gè)數(shù)...
    tracy_668閱讀 5,120評(píng)論 0 2
  • CommonRdbms主要泛指一些常用的傳統(tǒng)數(shù)據(jù)庫(kù)如Mysql、Oracle等,本文以Mysql到Mysql的導(dǎo)入...
    GJMZ閱讀 1,862評(píng)論 0 0
  • 一、DataX3.0概述 DataX 是一個(gè)異構(gòu)數(shù)據(jù)源離線同步工具,致力于實(shí)現(xiàn)包括關(guān)系型數(shù)據(jù)庫(kù)(MySQL、Ora...
    勤奮的超跑閱讀 11,630評(píng)論 1 12