datax啟動流程

組件

datax采集流程
  • 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服務。

運行流程

引擎啟動后jobContainer啟動流程

作業配置加載

  • 通過作業配置文件路徑(-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初始化:

    1. 根據job.content[0].reader/writer.name插件名來加載reader和writer插件,并保存reader/wirter PluginName

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

  • prepare準備:執行reader/writer的prepare方法

  • split切分任務:

    1. 根據job.setting.speed.bytecore.transport.channel.speed.bytejob.setting.speed.recordcore.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
      若都為空,則拋出異常
      
  1. 執行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。
  1. 獲取作業的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調度:

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

    2. 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
      
  1. adjustChannelNumPerTaskGroup:修正因為無法平均分配的少一個task的taskGroup的core.container.taskGroup.channel的更改

    3個task分配到2個taskGroup中時,會造成一個taskGroup的channel為2,一個taskGroup的channel為1
    所以要將少了一個task的taskGroup的channel進行修正優化。
    
  2. 為每個taskGroup修正core.container.job.mode為standalone

  3. StandAloneScheduler#registerCommunication:為每個taskGroup注冊Communication(狀態及統計信息交互)

  4. StandAloneScheduler#startAllTaskGroup:為每個taskGroup創建TaskGroupContainer并代理到TaskGroupContainerRunner啟動TaskGroupContainer。其中動態加載transfomer,數據采集就在這個步驟之內。

  • post:執行reader和writer的post方法

  • postHandle:根據job.postHandler.pluginName加載已存在的插件,并執行插件的postHandler方法

  • invokeHooks:根據/hook目錄調用外部hook

TaskGroupContainer

類圖

reader與writer的數據傳輸

?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 229,117評論 6 537
  • 序言:濱河連續發生了三起死亡事件,死亡現場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發現死者居然都...
    沈念sama閱讀 98,860評論 3 423
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 177,128評論 0 381
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 63,291評論 1 315
  • 正文 為了忘掉前任,我火速辦了婚禮,結果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 72,025評論 6 410
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發上,一...
    開封第一講書人閱讀 55,421評論 1 324
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當著我的面吹牛,可吹牛的內容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,477評論 3 444
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 42,642評論 0 289
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當地人在樹林里發現了一具尸體,經...
    沈念sama閱讀 49,177評論 1 335
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 40,970評論 3 356
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發現自己被綠了。 大學時的朋友給我發了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 43,157評論 1 371
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,717評論 5 362
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質發生泄漏。R本人自食惡果不足惜,卻給世界環境...
    茶點故事閱讀 44,410評論 3 347
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 34,821評論 0 28
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 36,053評論 1 289
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 51,896評論 3 395
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 48,157評論 2 375

推薦閱讀更多精彩內容

  • 開篇 ?最早接觸DataX是在前阿里同事在現在的公司引入的時候提到的,一直想抽空好好看看這部分代碼,因為DataX...
    晴天哥_王志閱讀 42,177評論 16 45
  • 概覽 DataX 是一個異構數據源離線同步工具,致力于實現包括關系型數據庫(MySQL、Oracle等)、HDFS...
    tracy_668閱讀 709評論 0 1
  • Datax的執行過程 要想進行調優,一般先要了解執行過程,執行過程如下: 過程詳細說明如下: DataX完成單個數...
    tracy_668閱讀 5,115評論 0 2
  • CommonRdbms主要泛指一些常用的傳統數據庫如Mysql、Oracle等,本文以Mysql到Mysql的導入...
    GJMZ閱讀 1,853評論 0 0
  • 一、DataX3.0概述 DataX 是一個異構數據源離線同步工具,致力于實現包括關系型數據庫(MySQL、Ora...
    勤奮的超跑閱讀 11,618評論 1 12