hadoop權威指南學習(一) - 天氣預報MapReduce程序的開發和部署


看過Tom White寫的Hadoop權威指南(大象書)的朋友一定得從第一個天氣預報的Map Reduce程序所吸引,

殊不知,Tom White大牛雖然在書中寫了程序和講解了原理,但是他以為你們都會部署了,這里輕描淡寫給

帶過了,這樣就給菜鳥們留了課題,其實在跑書中的程序的時候,如果沒經驗,還是會踩坑的。

這里筆者就把踩過的坑說一下,以防后來人浪費時間了。

1. 首先,你得下載書中的ncdc氣象原始數據,這個可以從書中的官網下載。

作者比較做人家,只給了2年的歷史數據,無妨,2年也可以運行。

下載下來你會看到1901.gz,1902.gz

 

2. 然后我們可以開始我們的編碼之旅了

新建一個maven項目,然后按照書中的例子,編寫如下3個類(這里Mapper, Reducer, Job的原理我就不多解釋了,自己去看大牛的書去)

MaxTemperatureMapper.java

package org.genesis.hadoop.temperature;

import org.apache.hadoop.io.IntWritable;
import org.apache.hadoop.io.LongWritable;
import org.apache.hadoop.io.Text;
import org.apache.hadoop.mapreduce.Mapper;

import java.io.IOException;

public class MaxTemperatureMapper
  extends Mapper<LongWritable, Text, Text, IntWritable> {

  private static final int MISSING = 9999;
  
  @Override
  public void map(LongWritable key, Text value, Context context)
      throws IOException, InterruptedException {
    
    String line = value.toString();
    String year = line.substring(15, 19);
    int airTemperature;
    if (line.charAt(87) == '+') { // parseInt doesn't like leading plus signs
      airTemperature = Integer.parseInt(line.substring(88, 92));
    } else {
      airTemperature = Integer.parseInt(line.substring(87, 92));
    }
    String quality = line.substring(92, 93);
    if (airTemperature != MISSING && quality.matches("[01459]")) {
      context.write(new Text(year), new IntWritable(airTemperature));
    }
  }
}

MaxTemperatureReducer.java

package org.genesis.hadoop.temperature;

import org.apache.hadoop.io.IntWritable;
import org.apache.hadoop.io.Text;
import org.apache.hadoop.mapreduce.Reducer;

import java.io.IOException;

public class MaxTemperatureReducer
  extends Reducer<Text, IntWritable, Text, IntWritable> {
  
  @Override
  public void reduce(Text key, Iterable<IntWritable> values,
      Context context)
      throws IOException, InterruptedException {
    
    int maxValue = Integer.MIN_VALUE;
    for (IntWritable value : values) {
      maxValue = Math.max(maxValue, value.get());
    }
    context.write(key, new IntWritable(maxValue));
  }
}

MaxTemperature.java

package org.genesis.hadoop.temperature;

import org.apache.hadoop.fs.Path;
import org.apache.hadoop.io.IntWritable;
import org.apache.hadoop.io.Text;
import org.apache.hadoop.mapreduce.Job;
import org.apache.hadoop.mapreduce.lib.input.FileInputFormat;
import org.apache.hadoop.mapreduce.lib.output.FileOutputFormat;

public class MaxTemperature {

  public static void main(String[] args) throws Exception {
    if (args.length != 2) {
      System.err.println("Usage: MaxTemperature <input path> <output path>");
      System.exit(-1);
    }
    
    Job job = new Job();
    job.setJarByClass(MaxTemperature.class);
    job.setJobName("Max temperature");

    FileInputFormat.addInputPath(job, new Path(args[0]));
    FileOutputFormat.setOutputPath(job, new Path(args[1]));
    
    job.setMapperClass(MaxTemperatureMapper.class);
    job.setReducerClass(MaxTemperatureReducer.class);

    job.setOutputKeyClass(Text.class);
    job.setOutputValueClass(IntWritable.class);
    
    System.exit(job.waitForCompletion(true) ? 0 : 1);
  }
}

 然后把我們的Java程序打包,你認為自己是一個Java熟手,不是嗎,熟練的命令或者IDE都可以(mvn clean install)

Ok, 包打完了,得到如下jar包: xxx.jar

好了,你可能會試着用書中或者網上的命令(前提是你已經配置好$hadoop_home) 

hadoop jar xxx.jar 你的主類名 你的本地gz文件存放的目錄 你本地另外一個輸出目錄

然而,很不幸,你的程序跑不了,理由很簡單,根本就找不到你的gz文件的目錄。

喔,查了下網上的資料,發現我似乎應該把本地文件拷貝到HDFS,趕快查資料,下一步。。。

 

3. 將本地數據拷貝到HDFS(前提是你已經安裝了hadoop並且把服務給啟動了起來)

3-1) 我們先在hdfs根目錄下建個data目錄

hadoop fs -mkdir /data

 

3-2) 把我們的gz數據拷貝到剛剛新建的目錄

hadoop fs -copyFromLocal /Users/KG/Documents/MyWork/Hadoop/data/ncdc/*.gz /data

 

3-3)把我們的jar包拷貝到一個地方,然后進入命令行,進入哪個目錄

cd /Users/KG/Documents/MyTest/Jar

 

3-4) 使用hadoop jar運行命令

但是,這里你會報錯: 找不到主類名

解決方案:你需要給自己的pom配置shade插件

我的pom.xml

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>org.genesis</groupId>
    <artifactId>MaxTemperature</artifactId>
    <version>1.0-SNAPSHOT</version>

    <dependencies>
        <dependency>
            <groupId>org.apache.hadoop</groupId>
            <artifactId>hadoop-core</artifactId>
            <version>1.2.1</version>
        </dependency>
        <dependency>
            <groupId>org.apache.hadoop</groupId>
            <artifactId>hadoop-common</artifactId>
            <version>2.7.2</version>
        </dependency>
    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-shade-plugin</artifactId>
                <version>2.4.1</version>
                <executions>
                    <execution>
                        <phase>package</phase>
                        <goals><goal>shade</goal></goals>
                        <configuration>
                            <transformers>
                                <transformer implementation="org.apache.maven.plugins.shade.resource.ManifestResourceTransformer">
                                    <mainClass>org.genesis.hadoop.temperature.MaxTemperature</mainClass>
                                </transformer>
                            </transformers>
                        </configuration>
                    </execution>
                </executions>
            </plugin>
        </plugins>

    </build>
</project>

3-5)再次運行完整命令,如下:

hadoop jar original-MaxTemperature-1.0-SNAPSHOT.jar org.genesis.hadoop.temperature.MaxTemperature /data /data/output

如果你看到如下輸出,那么你成功了

 

 

4. 驗證分析結果

使用如下命令:

hadoop fs -cat /data/output/*

輸出結果如下:

1901 317
1902 244

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM