Prérequis

Outils nécessaires pour la compilation

La liste suivante présente les outils à installer pour compiler la distribution Hadoop sur une machine utilisant Windows 7 :

Compilation des sources Hadoop

Télécharger les sources Hadoop 2.6.0 : http://hadoop.apache.org/releases.html

Décompresser le contenu de l’archive dans un répertoire ayant un chemin très court (par exemple C:\hdc) pour éviter les problèmes liées à la taille des chemins dans Windows.

Exécuter, en tant qu’administrateur, le Windows SDK 7.1 Command Prompt.

Se placer dans le répertoire C:\hdc\hadoop-2.6.0-src\.

Définir les variables suivantes

set Platform=x64
set ZLIB_HOME=C:\zlib-1.2.8

Executer la commande suivante pour compiler Hadoop

mvn package -Pdist,native-win -Dmaven.javadoc.skip=true -DskipTests -Dtar

La compilation peut durer quelques minutes…

Si l’exécution se termine avec succès, la distribution Hadoop est disponible dans le répertoire C:\hdc\hadoop-2.6.0-src\hadoop-dist\target\hadoop-2.6.0.

Développement du projet MapReduce

Pour illustrer notre démonstration, nous avons développé un exemple classique de job MapReduce : un compteur de mot.

Voici le pom de notre projet

<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>com.leuville.hadoop</groupId>
  <artifactId>hadoop-mr</artifactId>
  <version>1.0.0-SNAPSHOT</version>

  <dependencies>
    <dependency>
      <groupId>org.apache.hadoop</groupId>
      <artifactId>hadoop-client</artifactId>
      <version>2.6.0</version>
    </dependency>
  </dependencies>
</project>

Le code source de notre classe Mapper :

package com.leuville.hadoop.mr.wordcount;

import java.io.IOException;
import java.util.StringTokenizer;

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

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

  private final static IntWritable one = new IntWritable(1);

  private Text word = new Text();

  public void map(LongWritable key, Text value, Context context) throws IOException, InterruptedException {
    System.out.println(key + " --> " + value);
    StringTokenizer itr = new StringTokenizer(value.toString());
    while (itr.hasMoreTokens()) {
      word.set(itr.nextToken());
      context.write(word, one);
    }
  }
}

Le code source de notre classe Reducer :

package com.leuville.hadoop.mr.wordcount;

import java.io.IOException;

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

public class IntSumReducer extends Reducer<Text,IntWritable,Text,IntWritable> {
  
  private IntWritable result = new IntWritable();

  public void reduce(Text key, Iterable<IntWritable> values, Context context) 
      throws IOException, InterruptedException {
    int sum = 0;
    for (IntWritable val : values) {
      sum += val.get();
    }
    result.set(sum);
    context.write(key, result);
  }
}

Et enfin le code source de notre classe Driver contenant la méthode main

package com.leuville.hadoop.mr.wordcount;

import org.apache.hadoop.conf.Configured;
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;
import org.apache.hadoop.util.Tool;
import org.apache.hadoop.util.ToolRunner;

public class WordCountDriver extends Configured implements Tool{

  @Override
  public int run(String[] args) throws Exception {
    Job job = Job.getInstance(getConf(), "WordCount");
    job.setJarByClass(getClass());
    
    FileInputFormat.addInputPath(job, new Path(args[0]));
    FileOutputFormat.setOutputPath(job, new Path(args[1]));
    
    job.setMapperClass(TokenizerMapper.class);
    job.setReducerClass(IntSumReducer.class);
    
    job.setOutputKeyClass(Text.class);
    job.setOutputValueClass(IntWritable.class);
    
    return job.waitForCompletion(true) ? 0 : 1;
    
  }
  
  public static void main(String[] args) throws Exception{
    int code = ToolRunner.run(new WordCountDriver(), args);
    System.exit(code);
  }

}

Exécution du projet dans Eclipse

Avant de configurer et d’exécuter le programme, créer un répertoire input à la racine du projet Eclipse et créer un fichier test.txt contenant le texte à analyser par le programme.

Aller dans Run > Run Configuration… et ajouter une nouvelle Java Application

Configurer les paramètres du programme pour indiquer le répertoire où se situe les fichiers en entrée (ici input) et le répertoire de sortie (ici output)

Les paramètres -fs file:/// et -jt local indique respectivement à Hadoop d’utiliser le système de fichier local et une exécution local du moteur MapReduce.

image

Ajouter les 2 variables d’environnements suivantes :

image

Executer maintenant le programme et, après avoir rafraichi le projet Eclipse, un répertoire output doit apparaître contenant 2 fichiers (_SUCCESS et part-r-00000) comme le montre l’image suivante

image