1. 程式人生 > >MapReduce程式打成jar包在遠端伺服器執行

MapReduce程式打成jar包在遠端伺服器執行

一:背景

有時候,我們不想再程式中顯示的指定輸入路徑和輸出路徑,因為那樣不太靈活,不利於擴充套件,Hadoop提供了將程式打成jar包發到叢集上通過命令列引數指定輸入輸出路徑的方式執行程式。

二:技術實現

(1):主類繼承Configured類還要實現Tool介面。

(2):將我們以前寫的設定各種引數的程式碼寫在run()方法中(實現介面必須要實現run方法)。

(3):還有一句很關鍵的程式碼就是:job.setJarByClass(XXX.class);即以Jar包的形式執行。

我們以單詞計數為例,有以下兩種方法!!!

方法一:繼承Configured類和實現Tool介面

public class WordCount extends Configured implements Tool {

	// 定義輸入路徑
	private String INPUT_PATH = "";
	// 定義輸出路徑
	private String OUT_PATH = "";

	public static void main(String[] args) {

		try {
			ToolRunner.run(new WordCount(), args);
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

	static class MyMapper extends Mapper<LongWritable, Text, Text, LongWritable> {

		@Override
		protected void map(LongWritable key, Text value, Mapper<LongWritable, Text, Text, LongWritable>.Context context) throws IOException,
				InterruptedException {

			// 注:value是hadoop的Text型別,呼叫toString可以轉換成java的型別。
			String[] splited = value.toString().split("\t");

			// 迭代
			for (String word : splited) {
				context.write(new Text(word), new LongWritable(1L));
			}
		}
	}

	static class MyReduce extends Reducer<Text, LongWritable, Text, LongWritable> {

		@Override
		protected void reduce(Text k2, Iterable<LongWritable> v2s, Reducer<Text, LongWritable, Text, LongWritable>.Context context) throws IOException,
				InterruptedException {

			long sum = 0L;
			// 迭代計算單詞在檔案中出現的總記錄數
			for (LongWritable v2 : v2s) {
				sum += v2.get();
			}

			// 寫到上下文中
			context.write(k2, new LongWritable(sum));
		}
	}

	public int run(String[] args) throws Exception {

		// 給路徑賦值
		INPUT_PATH = args[0];
		OUT_PATH = args[1];

		try {
			// 建立配置資訊
			Configuration conf = new Configuration();
			// 新增配置檔案(我們可以在程式設計的時候動態配置資訊,而不需要手動去改變叢集)

			//conf.addResource("classpath://hadoop/core-site.xml");
			//conf.addResource("classpath://hadoop/hdfs-site.xml");
			//conf.addResource("classpath://hadoop/mapred-site.xml");

			// 如果輸出目錄存在,我們就進行刪除
			FileSystem fileSystem = FileSystem.get(new URI(INPUT_PATH), conf);
			if (fileSystem.exists(new Path(OUT_PATH))) {
				fileSystem.delete(new Path(OUT_PATH), true);
			}

			// 建立任務
			Job job = new Job(conf, WordCount.class.getSimpleName());
			// 通過命令列傳參的形式必須走這一步(打包執行必須執行的關鍵)
			job.setJarByClass(WordCount.class);

			// 1.1 設定輸入目錄
			FileInputFormat.setInputPaths(job, INPUT_PATH);
			// 指定對輸入資料進行格式化處理的類(這個可以省略,預設值即可)
			job.setInputFormatClass(TextInputFormat.class);

			// 1.2 指定自定義的Mapper類
			job.setMapperClass(MyMapper.class);
			// 指定map輸出的<K,V>型別(如果<K3,V3>的型別和<K2,V2>的型別一致,那麼可以省略)
			// job.setMapOutputKeyClass(Text.class);
			// job.setMapOutputValueClass(LongWritable.class);

			// 1.3 分割槽(可以省略,預設即可)
			job.setPartitionerClass(HashPartitioner.class);
			job.setNumReduceTasks(1);// 預設的分割槽是1個,所以任務也就是1個

			// 1.4排序、分組

			// 1.5 歸約

			// 2.1 對多個map任務的輸出,按照不同的分割槽,通過網路copy到不同reduce節點。

			// 2.2 指定自定義的reduce類
			job.setReducerClass(MyReduce.class);
			// 指定<K,V>的型別
			job.setOutputKeyClass(Text.class);
			job.setOutputValueClass(LongWritable.class);

			// 2.3 指定輸出的路徑
			FileOutputFormat.setOutputPath(job, new Path(OUT_PATH));
			// 指定輸出的格式化類(這個可以省略,使用預設值即可)
			job.setOutputFormatClass(TextOutputFormat.class);

			// 把作業提交給JobTracker完成
			job.waitForCompletion(true);

		} catch (Exception e) {
			e.printStackTrace();
		}

		return 0;
	}
}

上傳到遠端伺服器,通過如下命令執行:

我們可以先用jar -tf XXX.jar檢視jar中的結構,如下


然後用hadoop jar命令執行,如果我們是直接把整個專案打成一個jar包(因為很多時候我們會將類寫在多個檔案中,所以要打包整個專案),我們就要加上包名.主類名。如:

hadoop jar WordCount.jar com.lixue.run.cmd.WordCount  /hello  /out 

由於我們這個例子是直接將主類進行了打包,所以我們可以直接執行jar包就可以了,如下:

hadoop jar WordCount.jar hdfs://liaozhongmin5:9000/hello hdfs://liaozhongmin5:9000/out
命令格式為:hadoop jar XXX.jar 輸入路徑 輸出路徑(前面的hdfs://liaozhongmin5:9000可以省略)

方法二:也可以不繼承Configured和實現Tool介面,程式碼如下:

public class WordCountTest {
	
	//定義輸入路徑
	private static String IN_PATH = "";
	//定義輸出路徑
	private static String OUT_PATH = "";

	public static void main(String[] args) {

		try {
			// 建立配置資訊
			Configuration conf = new Configuration();
			//獲取命令列的引數
			String[] otherArgs = new GenericOptionsParser(conf, args).getRemainingArgs();
			//當引數違法時,中斷程式
			if (otherArgs.length != 2){
				System.err.println("Usage:wordcount<in> <out>");
				System.exit(1);
			}
			
			//給路徑賦值
			IN_PATH = otherArgs[0];
			OUT_PATH = otherArgs[1];
			// 建立檔案系統
			FileSystem fileSystem = FileSystem.get(new URI(OUT_PATH), conf);
			// 如果輸出目錄存在,我們就刪除
			if (fileSystem.exists(new Path(new URI(OUT_PATH)))) {
				fileSystem.delete(new Path(new URI(OUT_PATH)), true);
			}

			// 建立任務
			Job job = new Job(conf, WordCountTest.class.getName());
			//打成jar包執行,這句話是關鍵
			job.setJarByClass(WordCountTest.class);
			//1.1	設定輸入目錄和設定輸入資料格式化的類
			FileInputFormat.setInputPaths(job, IN_PATH);
			job.setInputFormatClass(TextInputFormat.class);

			//1.2	設定自定義Mapper類和設定map函式輸出資料的key和value的型別
			job.setMapperClass(MyMapper.class);
			job.setMapOutputKeyClass(Text.class);
			job.setMapOutputValueClass(LongWritable.class);

			//1.3	設定分割槽和reduce數量(reduce的數量,和分割槽的數量對應,因為分割槽為一個,所以reduce的數量也是一個)
			job.setPartitionerClass(HashPartitioner.class);
			job.setNumReduceTasks(1);

			//1.4	排序
			//1.5	歸約
			//2.1	Shuffle把資料從Map端拷貝到Reduce端。
			//2.2	指定Reducer類和輸出key和value的型別
			job.setReducerClass(MyReducer.class);
			job.setOutputKeyClass(Text.class);
			job.setOutputValueClass(LongWritable.class);

			//2.3	指定輸出的路徑和設定輸出的格式化類
			FileOutputFormat.setOutputPath(job, new Path(OUT_PATH));
			job.setOutputFormatClass(TextOutputFormat.class);


			// 提交作業 退出
			System.exit(job.waitForCompletion(true) ? 0 : 1);
		
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

	public static class MyMapper extends Mapper<LongWritable, Text, Text, LongWritable> {

		// 定義一個LongWritable物件作為map輸出的value型別
		LongWritable oneTime = new LongWritable(1);
		// 定義一個Text物件作為map輸出的key型別
		Text word = new Text();

		protected void map(LongWritable key, Text value, Mapper<LongWritable, Text, Text, LongWritable>.Context context) throws IOException,
				InterruptedException {

			// 對每一行記錄採用製表符(\t)進行分割
			String[] splits = value.toString().split("\t");

			// 遍歷字串陣列輸出每一個單詞
			for (String str : splits) {

				// 設定word
				word.set(str);
				// 把結果寫出去
				context.write(word, oneTime);
			}
		}
	}

	public static class MyReducer extends Reducer<Text, LongWritable, Text, LongWritable> {

		// 定義LongWritable物件最為Reduce輸出的value型別
		LongWritable result = new LongWritable();

		protected void reduce(Text key, Iterable<LongWritable> values, Reducer<Text, LongWritable, Text, LongWritable>.Context context) throws IOException,
				InterruptedException {

			int sum = 0;

			// 遍歷集合,計算每個單詞出現的和
			for (LongWritable s : values) {

				sum += s.get();
			}
			// 設定result
			result.set(sum);
			// 把結果寫出去
			context.write(key, result);
		}
	}
}
注:這種方式比較簡單,執行的方式還是一樣!

程式執行的日誌如下:


1.MapReduce任務的計算量即消耗CPU的時間=CPU time spent (ms)=1400

2.程式執行所消耗的實體記憶體=Physical memory (bytes) snapshot=184586240

3.程式執行所消耗的虛擬記憶體=Virtual memory (bytes) snapshot=756031488

4.JVM當前堆的大小=Total committed heap usage (bytes)=177016832

5.IO消耗=HDFS_BYTES_READ+HDFS_BYTES_WRITTEN*副本數+FILE_BYTES_READ+FILE_BYTES_WRITTEN=115+19*1+65+105096

6.網路流量消耗情況=HDFS_BYTES_READ+HDFS_BYTES_WRITTEN*副本數+Reduce shuffle bytes=115+19*1 + 65


相關推薦

MapReduce程式jar遠端伺服器執行

一:背景 有時候,我們不想再程式中顯示的指定輸入路徑和輸出路徑,因為那樣不太靈活,不利於擴充套件,Hadoop提供了將程式打成jar包發到叢集上通過命令列引數指定輸入輸出路徑的方式執行程式。 二:技術實現 (1):主類繼承Configured類還要實現Tool介面。 (2

java GUI程式jar涉及讀取工程資源無效問題解決

我們常常在程式碼中讀取一些資原始檔(比如圖片,音樂,文字等等)。在單獨執行的時候這些簡單的處理當然不會有問題。但是,如果我們把程式碼打成一個jar包以後,即使將資原始檔一併打包,這些東西也找不出來了。看看下面的程式碼: //原始碼1: package edu.hxraid; import

中在eclipse下如何將程式jar

匯出1. 建立java project2. 工程屬性java build path->Libraries中加入android.jar3. package explorer中右鍵點選工程,export java->jar file.使用1. 建立android p

如何將spring boot工程JAR伺服器執行

只需在專案的pom.xml中加入下面外掛 <build>     <plugins>         <plugin>             <groupId>org.springframework.boot</gro

程式jar後,如何使用log4j.properties檔案和因為外部jar

在eclipse中建的java project專案,打成jar檔案以後執行。發現各種錯誤。包括在ant達成jar檔案,當引入外部包,和外部檔案比如說log4j.properties檔案,老師報找不到異常。 下面自己的解決辦法, MANIFEST.mf 檔案內容:Manife

Ueditor 整合SpringBoot jar放到伺服器出現的問題

打成jar百度的富文字就會出現這個問題本地環境不會,上了測試機就會,是讀取不到後臺配置資訊造成的controller.jsp這個檔案讀取不到專案的真實路徑,遇到同樣問題的人可以打下log看下所以這種情況我們只能在後臺去寫控制器去實現,因為打成jar包後他的路徑跟war包是不一

把一個java程式jar

我介紹兩種打jar包的方法給大家,分別是cmd命令和Myeclipse工具。 cmd命令打jar包: 老規矩,先開啟黑視窗。如下: 打"jar",然後回車,就能看見JDK給我們提供打jar的一些字母的含意。下面還提供了一個示例。 在打jar之前,必須

程式jar路徑不對、找不到配置檔案的解決

我們常常在程式碼中讀取一些資原始檔(比如圖片,音樂,文字等等)。在單獨執行的時候這些簡單的處理當然不會有問題。但是,如果我們把程式碼打成一個jar包以後,即使將資原始檔一併打包,這些東西也找不出來了。看看下面的程式碼: //原始碼1: package

把Maven專案連同其依賴jar一同jar,並執行入口類

需求: 在我本地的電腦上存在一個maven工程,在pom檔案中依賴了一些第三方jar包。現在需要把工程打成jar包,然後放到linux伺服器中執行。 因此i,現在就需要在打jar包的同時既要指定執行

javaweb專案jar用命令執行

直接打包專案成jar,執行報找不到依賴的那個外部jar包,所有我直接打包的單個檔案,然後把這個檔案需要依賴的jar包,用WinRAR開啟,把裡面的整個檔案複製到自己的jar包中。然後執行就可以了。不要忘

地表最強idea Web專案war伺服器執行

點選之後開啟專案資料夾 選擇WebRoot目錄 OK 選擇war包目錄 點選建立資料夾 建立WEB-INF WEB

springbootJar後部署至Linux伺服器

下面主要記錄一下springboot打包成jar包在Linux服務上部署的步驟: 1、通過WinSCP,將相應的Jar檔案,複製到Linux指定目錄下,如/home/ 2、開啟ssh,進入/home目錄下,執行如下命令,進行專案的啟動,此方式為後臺啟動,即使關閉當前視窗,專案還是在執行的,會生成nohu

SpringBoot jar 釋出到伺服器

SpringBoot打成的jar包釋出到伺服器上 步驟 1. pom.xml檔案中必須包含: <packaging>jar</packaging> <build>     <plugins>  

SpongBoot專案jar並部署到伺服器上的方法

開啟命令提示符,切換到專案所在目錄,如我的專案名稱為Borrow就寫 然後在後邊加上maven命令maven package回車,如果顯示build success則打包成功 打好的jar包在專案資料夾的target資料夾下 如果想跳過打包測試階段,則在pom檔案中的<plugi

spring boot jar,部署到公司Linux系統的伺服器

FileZilla使用詳情 主機號:47.88.171.117 使用者名稱:root 密碼:[email protected]@7281001 埠:22 遠端站點:/develop/myjar 將其中檔案miner-currency-0.0.1-SNA

springboot專案jar執行程式讀取jarclasses中的檔案

使用:this.getClass().getResourceAsStream("/你的檔名稱");如果如果你在靜態類中想使用此語句是不可能的,不要問我為什麼。若要使用,可以在呼叫靜態類的時候先通過此語句來獲得 該檔案的 InputStream 物件,傳到靜態類中,這樣就可以在

java專案jar並上傳伺服器執行

java專案打包教程 首先我們寫好的java專案中至少有一個main方法,不管你有幾個main方法,打包時都只有一個入口。現在我用我寫好的程式打包並上傳伺服器執行。需要用到的工具有Intellij I

關於在eclipse下的mapreduce工程打包jar的問題(包含第三方jar

成功 sha mas 但是 關於 hadoop集群 日誌 方法 mapreduce 這個問題也是在開發項目中經常遇到的一個問題,網上提供了很多方法,但是我發現很多並不適用,這裏推薦兩種方法,一種肯定沒問題,就是比較麻煩,另一種是適用FatJar來打包,但是我沒成功,原因估計

項目jar

pid attach zookeepe -s gin aps ble lns 發布 distributionManagement 為發布到本地參考的地址 repository 設置從本地maven庫拉取jar包 <project xmlns:xsi="http:

java 如何把自己寫的淚jar,如何放入classpath讓其他人可以使用

-c ima 技術 test 路徑 log spa images mage 定位到要打包的上一層路徑,執行jar -cvf test.jar *.*(輸入需要打包的內容,此為所有內容) 在你要打包的文件夾同級目錄下回生成該文件夾名字的jar包了 其他人使用時