天天看點

《深入了解Hadoop(原書第2版)》——3.5Hadoop作業中的第三方函數庫

本節書摘來自華章計算機《深入了解hadoop(原書第2版)》一書中的第3章,第3.5節,作者 [美]薩米爾·瓦德卡(sameer wadkar),馬杜·西德林埃(madhu siddalingaiah),傑森·文納(jason venner),譯 于博,馮傲風,更多章節内容可以通路雲栖社群“華章計算機”公衆号檢視。

到目前為止,在mapper和reducer類中隻使用了标準java函數庫和hadoop函數庫。這些标準函數庫包括了hadoop發行版中的類庫和标準java類庫(比如string.class)。

可是,僅僅使用這些标準函數庫不能夠開發複雜的hadoop作業程式,有時我們需要第三方庫的支援。如前所述,mapper和reducer類中使用的這些庫需要被發送并配置到叢集中運作mapper和reducer執行個體的所有節點。

首先,你要編寫一個跟介紹過的代碼不同的使用第三方庫的程式。代碼清單3-4中是一個使用了第三方庫的word count程式。這個例子是故意如此編寫的,以便更好地示範說明。

假設你有一個包含一系列單詞的檔案,其中有些單詞由unicode字元和數字(0~9)組成。其他都是由unicode字元組成。由數字和字母組成的單詞常常用在合同檔案中,合同檔案中各種各樣的标示符就是由數字和字母組成的。簡便起見,像“-“和“$”這樣的字元是不允許出現在單詞中的。

假設我們隻關心由字母和數字組成的單詞。為了判斷單詞中是否隻包含有字母和數字,我們需要用到commons-lang函數庫中的stringutils.class。使用下面的邏輯來調用相應的方法以做出正确的判斷:

《深入了解Hadoop(原書第2版)》——3.5Hadoop作業中的第三方函數庫

代碼清單3-4中展示了全部源代碼。

《深入了解Hadoop(原書第2版)》——3.5Hadoop作業中的第三方函數庫
《深入了解Hadoop(原書第2版)》——3.5Hadoop作業中的第三方函數庫
《深入了解Hadoop(原書第2版)》——3.5Hadoop作業中的第三方函數庫

稍後讨論代碼清單3-4。首先,你要了解為了使用第三方函數庫,pom檔案所作出的修改。代碼清單3-5展示了pom檔案中的有關部分。

《深入了解Hadoop(原書第2版)》——3.5Hadoop作業中的第三方函數庫

在這個pom檔案中,添加了commons-lang 2.3版本的函數庫。注意添加hadoop-client函數庫時使用的标簽中的内容為provided。到目前為止,标簽中提供的配置項會使程式在編譯之後生成兩個獨立的jar檔案。

prohadoop-0.0.1-snapshot.jar僅包含org.apress包及其子包中的使用者自定義的類。

prohadoop-0.0.1-snapshot-jar-with-dependencies.jar中不僅僅包含了使用者自己編寫的類,還包含了commons-lang-2.3.jar檔案中的類。由于pom檔案中,添加hadoop- client函數庫依賴時配置的scope值為provided,是以生成的jar檔案中不包括這個函數依賴庫。這個配置項的含義是,在程式編譯時使用這個函數庫,但是不把它打包到最終的jar檔案中。

為什麼hadoop-client及其他的依賴函數庫不包含在prohadoop-0.0.1-snapshot-jar-with-dependencies.jar檔案中呢?我們知道,maven不但解析聲明的函數庫,還會解析該函數庫(帶有正确版本号)所依賴的其他函數庫。如果hadoop-client函數庫及其他依賴的函數庫也被打包,會導緻jar檔案的臃腫不堪。hadoop-client函數庫已經配置在了叢集中的各個節點上,是以hadoop-client中的類都不需要打包到作業程式的jar檔案中。這是一個非常重要的優化。由于程式打包排除掉了hadoop-client函數庫,整合依賴之後的jar檔案體積大大減小(比如200kb與20mb)。回想一下,這個jar檔案需要從用戶端節點傳輸到遠端節點。jar檔案的大小會影響到作業程式的啟動耗時,因為隻有當該檔案傳輸完畢,作業才能夠啟動運作。試着去掉标簽,并重新編譯。

我們來講解前文中代碼清單3-4中的程式。需要注意的是有一個附加的函數庫包含在程式之中。這個函數庫是commons-lang-2.3.jar,遠端的mapper 和reducer類會使用這個函數庫。wordcountnewapiv2.class擴充并實作了新的類,運作這個程式需要把它依賴的函數庫jar檔案分發到執行該程式的計算節點。

使用下面的指令來執行該程式:

《深入了解Hadoop(原書第2版)》——3.5Hadoop作業中的第三方函數庫

上面的指令、參數及其環境變量配置的解釋如下:

hadoop_classpath中的配置確定了位于$hadoop_home/bin檔案夾中的hadoop指令能夠通路依賴jar檔案,這個依賴jar檔案是啟動mapreduce作業的用戶端程式要使用的。在本示例中,這個變量不是必須的,因為示例中的mapreduce 作業的用戶端程式沒有使用任何第三方函數庫。

$libjars變量是一個逗号分隔的函數庫檔案路徑清單,這些函數庫檔案是叢集中資料節點執行mapper和reducer類的時候要使用的。需要注意的是這個清單的分隔符不同于在hadoop_classpath變量指定函數庫的時候用到的分隔符。

作業程式jar檔案和$libjars變量中設定的jar檔案會被發送到叢集上所有執行該map/reduce任務的節點上。這是一個移動代碼到資料附近的例子(第1章中介紹的)。這些jar檔案會被配置到遠端節點的classpath變量中。main()函數中的toolrunner類負責這個工作。

和 中配置的路徑指向hdfs上的相關位置。

運作作業程式的時候要確定reducers運作過程中不會抛出由于沒有找到包含stringutils.class的函數庫jar檔案而導緻的classnotfoundexception異常。

有另一種不需要配置–libjars選項的方法來運作這個作業,其指令如下:

《深入了解Hadoop(原書第2版)》——3.5Hadoop作業中的第三方函數庫

注意兩種方法的關鍵差別。如果依賴的函數庫已經被打包進了作業程式的jar檔案中,我們就不需要-libjars這個選項了。每當作業執行的時候,作業程式jar檔案就會被發送到遠端節點上進行配置。實際上,新舊api寫成的作業程式都可以使用這樣的方法,而且在不使用代碼清單3-4中介紹的toolrunner類的情況下也可以使用這個方法。使用這個方法唯一的缺點就是當依賴函數庫數量很大的時候,這種情況在實際情況中會經常碰到,把所有的依賴函數庫都打包到jar檔案中,會導緻jar檔案變得很大,這樣的話,在程式建構/測試周期内會增加程式的編譯時間。如果你的測試環境與開發環境不在同一個叢集環境中(比如你有另外一個配置在雲中的測試叢集),當你需要經常修改你的作業程式代碼的時候,而包含所有依賴函數庫的jar檔案體積又比較大,經常移動這樣的檔案是比較耗費時間的。但請記住,這是執行作業程式的最通用的方法。

在這本書的後續講解過程中,程式作業的開發均基于mapreduce架構的新api,并使用toolrunner類來執行它。

最後,我們來讨論一下代碼清單3-4中的内容,它與代碼清單3-2和代碼清單3-3之間有什麼不同呢?其主要不同在于它們使用不同的指令行來執行作業程式;以及為了確定在遠端節點上執行的map和reduce任務可以通路第三方函數庫,在作業程式開發中使用了不同的方法來編寫類:

代碼清單3-4更多地使用genericoptionsparser.class類來擷取程式運作的參數,比如輸入檔案路徑和輸出檔案路徑。使用方法如下所示:

《深入了解Hadoop(原書第2版)》——3.5Hadoop作業中的第三方函數庫

在送出執行hadoop作業的指令行中,删除了-libjars和$libjars_path參數,僅僅傳回程式所必需的參數。

在代碼清單3-4中最重要的一個方面是,在main()方法中調用toolrunner.run()時所使用的configuration執行個體必須與run()方法中用來配置作業的configuration執行個體是同一個執行個體。為了確定這一點,run()方法中一般都會使用getconf()方法來擷取configuration執行個體,getconf()是在configurable接口中定義的,并在該接口的繼承類configured類中實作的。如果使用的不是同一個configuration執行個體,作業就會配置錯誤,遠端節點上運作的mapper 和 reducer 任務也無法通路第三方jar檔案。

toolrunner.run()方法負責解析-libjars參數。它将解析這個參數的任務委托給genericoptionsparser.class執行。把-libjars參數的值添加到configuration對象,用這樣的方法來配置遠端任務。

代碼清單3-2和代碼清單3-3沒有方法來傳輸第三方函數庫。如果你想在代碼清單3-2和代碼清單3-3的程式中使用第三方函數庫,需要打包到應用程式jar檔案中。這個打包後的檔案就是使用maven建構生成的prohadoop-0.0.1-snapshot-jar-with-dependencies。(建構這個jar檔案的過程和目的,我們已經在前面介紹過了。)

表3-3中列出了代碼清單3-4中mapreduce程式的各個元件。

《深入了解Hadoop(原書第2版)》——3.5Hadoop作業中的第三方函數庫