趙貴兵
摘要:Kettle是一款功能強大且最流行的ETL工具,該文通過Kettle在工程實踐中的一個應(yīng)用場景,描述了Kettle應(yīng)用方法和技巧,希望為其他應(yīng)用提供參考。
關(guān)鍵詞:Kettle;ETL;流程軟件
中圖分類號:TP311 文獻(xiàn)標(biāo)識碼:A
文章編號:1009-3044(2019)09-0095-02
Pentaho公司的Data Integration產(chǎn)品,又名Kettle,是一款使用元數(shù)據(jù)驅(qū)動的功能強大的ETL工具,可以在Windows、Unix上運行。Kettle本身提供了強大的圖形界面設(shè)計器和豐富的組件,可以大大縮短數(shù)據(jù)抽取項目的開發(fā)周期,并且容易維護(hù)。Kettle設(shè)計器界面友好,提供了工作流設(shè)計模式,能滿足各種場景的實現(xiàn),更詳細(xì)的說明和下載請參考Pentaho官網(wǎng):community.pentaho.com。
下面詳細(xì)說明作者在實踐中應(yīng)用Kettle時遇到的問題和解決方法,希望能為大家的實踐應(yīng)用提供參考。
1 應(yīng)用案例說明
在該應(yīng)用中,需要準(zhǔn)實時的將大量碎片文件中的行記錄保存到數(shù)據(jù)庫,并將部分記錄分發(fā)給下游模塊。文件中的行記錄在入庫前需要進(jìn)行規(guī)整、轉(zhuǎn)換、過濾、匹配、合并記錄等復(fù)雜操作。下圖是對一批文件的處理流程:
以下對該流程圖中的重要組件進(jìn)行說明:
1)“從結(jié)果獲取記錄”組件從父流程接收最多500個文件全路徑,然后由“列出字段”組件解析出每個文件的行和列的值,解析出的每一行記錄都保存有該行所在的文件名。如果該流程每次只接收一個文件,那么在需要處理大量碎片文件的情況下,根本無法滿足性能要求,因為流程的加載和啟動占了一次流程執(zhí)行的絕大多數(shù)時間。
2)“Movefile Step”組件是一個自定義組件,該組件的功能是判斷記錄中傳入的文件名如果發(fā)生變更,就將變更前的文件備份并刪除。Kettle自帶組件中沒有此功能的組件,考慮到需要在很多流程中使用,所以利用了Kettle的插件機(jī)制,定義了該組件。
3)“記錄輸入格式錯誤”->“字段選擇”->“Movefile Step”,“記錄hit失敗”->“字段選擇”->“Movefile Step”,“記錄入庫錯誤”->“字段選擇”->“Movefile Step”,“空操作”->“字段選擇”->“Movefile Step”,以上這些流程確保了所有記錄都會經(jīng)過“Movefile Step”組件,從而保證當(dāng)一個文件的所有行被處理后,這個文件一定會執(zhí)行被備份和刪除操作。
4)“字段轉(zhuǎn)換”是一個JS組件,被使用對字段值進(jìn)行規(guī)整,增加需要的擴(kuò)展字段。JS組件在測試中達(dá)到4000記錄/秒的處理效率,能滿足該應(yīng)用場景的使用需求。在該應(yīng)用中,有很多個業(yè)務(wù)流程,它們是并行執(zhí)行的,這樣不同業(yè)務(wù)的碎片文件能夠被并行處理。“Java Code”組件能提供更高的處理效率,但是編寫的代碼更復(fù)雜,在可以滿足處理效率的前提下,“JavaScript Code”是更好的選擇。
5)“關(guān)聯(lián)外部資源”是一個“Java Code”組件,雖然該組件編寫復(fù)雜,調(diào)試?yán)щy,但在這里使用它可以使流程繪制更簡潔,因為這里的業(yè)務(wù)邏輯太復(fù)雜,使用Java語言更容易描述清楚。如果只是使用Kettle的自帶組件,可能會繪出一條異常復(fù)雜的流程圖。關(guān)于如何為“Java Code”組件編寫代碼將在后文中描述。
6)“關(guān)聯(lián)外部資源查詢”是一個“Java Code”組件,它將Kettle流中的字段值和內(nèi)存中緩存的字典進(jìn)行匹配,如果匹配成功,則將字典中對應(yīng)的值填入Kettle流。在該應(yīng)用中有多個內(nèi)存字典,它們通過Job定時從數(shù)據(jù)庫中加載到Kettle應(yīng)用程序內(nèi)存中,通過Java讀寫并發(fā)鎖避免讀寫沖突。
7)“判斷插入還是更新”是一個“Java Code”組件,它用于前后記錄的匹配。在該應(yīng)用中,有“開始”記錄,有“結(jié)束”記錄,還有其他記錄,“開始”和“結(jié)束”記錄根據(jù)某些字段值可以判定為一對記錄,需要做合并。“開始”記錄會被記錄在內(nèi)存中,當(dāng)“結(jié)束”記錄出現(xiàn)時,首先在內(nèi)存中查找對應(yīng)的“開始”記錄,如果未找到則去數(shù)據(jù)庫中查找。記錄在內(nèi)存中的“開始”記錄,如果被“結(jié)束”記錄匹配上則被清除,或者超過時限也會被清除,這些被從內(nèi)存中清除的“開始”記錄在數(shù)據(jù)庫中仍然可以查找到,不會丟失。
8)“插入或更新數(shù)據(jù)庫”是一個“Java Code”組件,它將一條輸入記錄拆分并插入多個數(shù)據(jù)庫表,并保證多個表的事務(wù)一致性,它同時還將入庫的記錄通過自定義的Socket服務(wù)發(fā)生給Socket客戶端。自定義的Socket服務(wù)在應(yīng)用初始化時創(chuàng)建并接收客戶端的連接。
在該應(yīng)用中,所有“Java Code”組件中使用的數(shù)據(jù)庫連接都是從c3p0連接池獲取的,這樣可以更好的管理和監(jiān)控數(shù)據(jù)庫連接。
上圖的流程是一個實際應(yīng)用中復(fù)雜ETL流程,它包含了許多典型的操作,如內(nèi)存匹配、入庫、通過Socket分發(fā)、備份并刪除文件等。作者通過巧妙的使用Kettle中的各種組件,將復(fù)雜的操作過程簡單化,在Kettle流程圖中清晰的表達(dá)了出來,同時也彰顯了Kettle的強大。
2 應(yīng)用技巧
1)Kettle自帶的“Java Code”組件是一個功能強大的腳本組件,為Kettle功能擴(kuò)展提供了強力支持。如果直接在“Java Code”組件中編寫Java代碼,不但困難,而且容易出錯。如果代碼邏輯復(fù)雜,那么直接在Kettle界面上編寫幾乎不可行。一種方法是首先在IDE中編碼,然后將代碼同步到“Java Code”組件中。具體操作如下:
1)在IDE中新建一個Java工程,將Kettle安裝目錄下lib目錄中的所有jar引入該工程。
新建一個Java類,該類繼承Kettle的TransformClassBase類。
當(dāng)在IDE中編寫完成后,將Java類中“import”部分和“processRow”方法的代碼拷貝到“Java Code”組件即可,如果除“processRow”外,還在該類中新建了其他方法,也要將這些方法一并拷貝到“Java Code”組件中。
2)“Java Code”組件中的Java代碼和它引用的其他代碼中不能使用Java模板類功能,如不能使用“java.util.List
3)從Kettle中配置的數(shù)據(jù)庫中獲取c3p0連接池所需的數(shù)據(jù)庫信息,代碼如下:
TransMeta transMeta = getTransMeta();
DatabaseMeta dm = transMeta.findDatabase(getVariable(“dbname”, “defaultName”));
String host = dm.getHostname();
String port = dm.getDatabasePortNumberString();
String db = dm.getDatabaseName();
String username = dm.getUsername();
String password = dm.getPassword();
4)Kettle插件編寫和插件安裝,請參考該文檔:https://help.pentaho.com/Documentation/6.0/0R0/0V0。
5)配置log4j日志,將log4j日志配置文件如“l(fā)og4j.xml”放在Kettle安裝目錄的classes目錄下,重啟Kettle即生效。
6)添加第三方j(luò)ar包到Kettle中,最直接的方法是將jar包放在Kettle安裝目錄下的lib目錄中,重啟Kettle即可。
參考文獻(xiàn):
[1] Pentaho Kettle源代碼.[EB/OL].https://github.com/pentaho/pentaho-kettle .
[2] Kettle安裝目錄/docs/English/welcome/index.html Kettle安裝包包含的Kettle文檔[EB].
【通聯(lián)編輯:代影】