Hadoop作业提交分析(三)
http://www.cnblogs.com/spork/archive/2010/04/12/1710294.html
通過前面兩篇文章的分析,對Hadoop的作業提交流程基本明了了,下面我們就可以開始編寫代碼模擬這個流程。
第一步要做的是添加Hadoop的依賴庫和配置文件到classpath。最常用的方法就是用一個容器先把各個要添加到classpath的文件或文件夾存儲起來,后面再作為類加載器的URL搜索路徑。
/*** Add a directory or file to classpath.
*
* @param component
*/
public static void addClasspath(String component) {
if ((component != null) && (component.length() > 0)) {
try {
File f = new File(component);
if (f.exists()) {
URL key = f.getCanonicalFile().toURL();
if (!classPath.contains(key)) {
classPath.add(key);
}
}
} catch (IOException e) {
}
}
}
上面的classPath變量就是我們聲明用來裝載classpath組件的容器。
private static ArrayList<URL> classPath = new ArrayList<URL>();由于需要添加一些文件夾下的所有Jar包,所以我們還要實現一個遍歷添加某文件夾下文件的方法。
/*** Add all jars in directory to classpath, sub-directory is excluded.
*
* @param dirPath
*/
public static void addJarsInDir(String dirPath) {
File dir = new File(dirPath);
if (!dir.exists()) {
return;
}
File[] files = dir.listFiles();
if (files == null) {
return;
}
for (int i = 0; i < files.length; i++) {
if (files[i].isDirectory()) {
continue;
} else {
addClasspath(files[i].getAbsolutePath());
}
}
}
簡單起見,這個方法沒有使用Filter,對文件夾下的文件是通吃,也忽略掉了子文件夾,只處理根文件夾。
好了,有了基礎方法,下面就是照著bin/hadoop中腳本所做的,把相應classpath添加進去。
/*** Add default classpath listed in bin/hadoop bash.
*
* @param hadoopHome
*/
public static void addDefaultClasspath(String hadoopHome) {
// Classpath initially contains conf dir.
addClasspath(hadoopHome + "/conf");
// For developers, add Hadoop classes to classpath.
addClasspath(hadoopHome + "/build/classes");
if (new File(hadoopHome + "/build/webapps").exists()) {
addClasspath(hadoopHome + "/build");
}
addClasspath(hadoopHome + "/build/test/classes");
addClasspath(hadoopHome + "/build/tools");
// For releases, add core hadoop jar & webapps to classpath.
if (new File(hadoopHome + "/webapps").exists()) {
addClasspath(hadoopHome);
}
addJarsInDir(hadoopHome);
addJarsInDir(hadoopHome + "/build");
// Add libs to classpath.
addJarsInDir(hadoopHome + "/lib");
addJarsInDir(hadoopHome + "/lib/jsp-2.1");
addJarsInDir(hadoopHome + "/build/ivy/lib/Hadoop/common");
}
至此,該添加classpath的都已添加好了(未包括第三方庫,第三方庫可用Conf中的tmpjars屬性添加。),下去就是調用RunJar類了。本文為了方便,把RunJar中的兩個方法提取了出來,去掉了一些可不要的Hadoop庫依賴,然后整合到了類EJob里。主要改變是把原來解壓Jar包的“hadoop.tmp.dir”文件夾改為"java.io.tmpdir",并提取出了fullyDelete方法。
利用這個類來提交Hadoop作業很簡單,下面是一個示例:
args = new String[4];args[0] = "E:\\Research\\Hadoop\\hadoop-0.20.1+152\\hadoop-0.20.1+152-examples.jar";
args[1] = "pi";
args[2] = "2";
args[3] = "100";
// 傳入Hadoop Home的地址,自動添加相應classpath。
EJob.addDefaultClasspath("E:\\Research\\Hadoop\\hadoop-0.20.1+152");
EJob.runJar(args);
上面這個示例調用了Hadoop官方例子Jar包里的pi計算例子,傳遞參數時同bin/hadoop jar *.jar mainclass args命令類似,但是忽略掉了bin/hadoop jar這個命令,因為我們現在不需要這個腳本來提交作業了。新建一個Project,添加一個class,在main里粘上上面的代碼,然后Run as Java Application。注意看你的Console,你會發現你已經成功把作業提交到Hadoop上去了。
有圖有真相,粘一下我的運行示例(在Win上開Eclipse,Hadoop Cluster在Linux,配置文件同Cluster的一樣)。
下面是在Cloudera Desktop看到的Job信息(它的時間是UTC的)。
用上述方法,我們可以做一個類似Cloudera Desktop的Web應用,接受用戶提交的Jar,并在Action處理中提交到Hadoop中去運行,然后把結果返回給用戶。
由于篇幅原因,加上前面介紹過RunJar類,所本文沒有粘關于RunJar類的代碼,不過你放心,本文提供例子工程下載。你可以在此基礎上優化它,添加更多功能。由于大部分是Hadoop的代碼,So,該代碼基于Apache License。
-->>點我下載<<--
到此,以Java方式提交Hadoop作業介紹完畢。但,是否還可以再進一步呢?現在還只能提交打包好的MR程序,尚不能像Hadoop Eclipse Plugin那樣能直接對包含Mapper和Reducer的類Run on Hadoop。為什么直接對這些類Run as Java Application提交的作業是在Local運行的呢?這其中又包含有什么秘密呢?我們將在下面的文章中更深入的剖析Hadoop的作業提交代碼,去到最底層,慢慢揭開它的黑面紗。
To be continued...
/Files/xuxm2007/jobutil.rar
轉載于:https://www.cnblogs.com/xuxm2007/archive/2011/09/08/2170498.html
與50位技術專家面對面20年技術見證,附贈技術全景圖總結
以上是生活随笔為你收集整理的Hadoop作业提交分析(三)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 使用MEF构建可扩展的Silverlig
- 下一篇: ProgressBar 类