TP 2 : MapReduce avec Hadoop
Créer un répertoire dans HDFS
HDFS, appelé input. Pour cela, taper:
hadoop fs –mkdir -p
p input
Nous allons utiliser le fichie
fichier [Link] comme
omme entrée pour le traitement MapReduce.
Ce fichier se trouve déjà sous le répertoire principal de votre machine master.
Charger le fichier purchases dans le répertoire input que vous avez créé:
hadoop fs –put
put [Link] input
Pour afficher le contenu du répertoire input, la commande est:
hadoop fs –ls input
Pour afficher les dernières lignes du fichier purchases:
hadoop fs -tail
tail input/[Link]
Le résultat suivant va donc s'afficher:
Interfaces web pour Hadoop
Hadoop offre plusieurs interfaces web pour pouvoir observer le comportement de ses
différentes composantes. Vous pouvez afficher ces pages en local sur votre machine grâce à l'option
-p de la commande docker run
run.. En effet, cette option permet de publier un port du contenaire
1
sur la machinee hôte. Pour pouvoir publier tous les ports exposés, vous pouvez lancer votre
contenaire en utilisant l'option -P
P.
En regardant le contenu du fichier [Link] fourni dans le projet, vous verrez
que deux ports de la machine maître ont été exposés:
Le port 50070:: qui permet d'afficher les informations de votre namenode.
Le port 8088:: qui permet d'afficher les informations du resource manager de Yarn et
visualiser le comportement des différents jobs.
Une fois votre cluster lancé et prêt à l'emploi, vous pouvez, sur votre navigateur préféré de votre
machine hôte, aller à : [Link]
[Link] Vous obtiendrez le résultat suivant:
Vous pouvez également visualiser l'avancement et les résultats de vos Jobs (Map Reduce ou autre)
en allant à l'adresse: [Link]
2
Map Reduce
Présentation
Un Job Map-Reduce
Reduce se compose principalement de deux types de programmes:
Mappers : permettent d’extraire les données nécessaires sous forme de clef
clef/valeur, pour
pouvoir ensuite les trier selon la clef
Reducers : prennent un ensemble de données triées selon leur clef
clef, et effectuent le
traitement nécessaire sur ces données (somme, moyenne, total...)
Wordcount
Nous allons tester un programme MapReduce grâce à un exemple très simple, le WordCount,
l'équivalent du HelloWorld pour les applications de traitement de données. Le Wordcount permet de
calculer le nombre de mots dans un fichier donné, en décomposant le ca
calcul
lcul en deux étapes:
L'étape de Mapping,, qui permet de découper le texte en mots et de délivrer en sortie un flux
textuel, où chaque ligne contient le mot trouvé, suivi de la valeur 1 (pour dire que le mot a
été trouvé une fois)
L'étape de Reducing,, qui ppermet
ermet de faire la somme des 1 pour chaque mot, pour trouver le
nombre total d'occurrences de ce mot dans le texte.
Commençons par créer un projet Maven dans IntelliJ IDEA. Nous utiliserons dans notre cas JDK
1.8.
Définir les valeurs suivantes pour votre pprojet:
3
GroupId: [Link]
ArtifactId: wordcount
Version: 1
Ouvrir le fichier [Link], et ajouter les dépendances suivantes pour Hadoop, HDFS et Map
Reduce:
<dependencies>
<dependency>
<groupId>[Link]</groupId>
<artifactId>hadoop-common</artifactId>
<version>2.7.2</version>
</dependency>
<!-- [Link]
client-core -->
<dependency>
<groupId>[Link]</groupId>
<artifactId>hadoop-mapreduce-client-core</artifactId>
<version>2.7.2</version>
</dependency>
<!-- [Link] -->
<dependency>
<groupId>[Link]</groupId>
<artifactId>hadoop-hdfs</artifactId>
<version>2.7.2</version>
</dependency>
<dependency>
<groupId>[Link]</groupId>
<artifactId>hadoop-mapreduce-client-common</artifactId>
<version>2.7.2</version>
</dependency>
</dependencies>
Créer un package iset.tp1 sous le répertoire src/main/java
Créer la classe TokenizerMapper, contenant ce code:
package iset.tp1;
import [Link];
import [Link];
import [Link];
4
import [Link];
import [Link];
public class TokenizerMapper
extends Mapper<Object, Text, Text, IntWritable>{
private final static IntWritable one = new IntWritable(1);
private Text word = new Text();
public void map(Object key, Text value, [Link] context
) throws IOException, InterruptedException {
StringTokenizer itr = new StringTokenizer([Link]());
while ([Link]()) {
[Link]([Link]());
[Link](word, one);
}
}
}
Créer la classe IntSumReducer:
package iset.tp1;
import [Link];
import [Link];
import [Link];
import [Link];
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) {
[Link]("value: "+[Link]());
5
sum += [Link]();
}
[Link]("--> Sum = "+sum);
[Link](sum);
[Link](key, result);
}
}
Enfin, créer la classe WordCount:
package iset.tp1;
import [Link];
import [Link];
import [Link];
import [Link];
import [Link];
import [Link];
import [Link];
public class WordCount {
public static void main(String[] args) throws Exception {
Configuration conf = new Configuration();
Job job = [Link](conf, "word count");
[Link]([Link]);
[Link]([Link]);
[Link]([Link]);
[Link]([Link]);
[Link]([Link]);
[Link]([Link]);
[Link](job, new Path(args[0]));
[Link](job, new Path(args[1]));
[Link]([Link](true) ? 0 : 1);
}
}
Tester Map Reduce en local
Dans votre projet sur IntelliJ:
Créer un répertoire input sous le répertoire resources de votre projet.
Créer un fichier de test: [Link] dans lequel vous insèrerez les deux lignes:
6
salut hello salut hi
salut hello hello hi
hello
Créer une configuration de type Application (Run->Edit
>Edit Configurations...
Configurations...->+-
>Application).
Définir comme Main Class
Class: [Link], et comme Program Arguments:
Arguments
src/main/resources/input/[Link] src/main/resources/output
Lancer le programme. Un répertoire output sera créé dans le répertoire resources, contenant
notamment un fichier part
part-r-00000, dont le contenu devrait être lee suivant:
Lancer Map Reduce sur le cluster
Dans votre projet IntelliJ:
Créer une configuration Maven avec la ligne de commande: package install
Lancer la configuration. Un fichier [Link] sera créé dans le répertoire target du
projet.
Copier le fichier
ichier jar créé dans le contenaire master. Pour cela:
Ouvrir le terminal sur le répertoire du projet. Cela peut être fait avec IntelliJ en
ouvrant la vue Terminal située en bas à gauche de la fenêtre principale.
7
Taper la commande suivante:
docker cp target/wordcount
target/[Link] hadoop-master:/root/wordcount
master:/root/[Link]
Revenir au shell du contenaire master, et lancer le job map reduce avec cette
commande :
hadoop jar wordcount
[Link]
[Link] [Link] input output
Le Job sera lancé sur le fichier purchase
[Link] que vous aviez préalablement chargé dans le répertoire
input de HDFS. Une fois le Job terminé, un répertoire output sera créé. Si tout se passe bien, vous
obtiendrez un affichage ressemblant au suivant:
8
En affichant les dernières lignes du fichi
fichier généré output/part-r-00000, avec hadoop fs -tail
output/part-r-00000,, vous obtiendrez l'affichage suivant:
Il vous est possible de monitorer vos Jobs Map Reduce, en allant à la page:
[Link] Vous trouverez votre Job dans la liste des applications comme suit:
9
Il est également possible de voir le comportement des noeuds esclaves, en allant à l'adresse:
[Link] pour slave1, et [Link] pour slave2. Vous
obtiendrez ce qui suit:
Refaire le même exercice mais cette fois en va le programmer en Python
- créer un fichier [Link]
nano [Link]
- écrire le code suivant :
#!/usr/bin/env python
"""[Link]"""
import sys
for line in [Link]:
line=[Link]()
words=[Link]()
for word in words:
print('%s\t%s'%(word,1))
- tapez ctr+o pour enregister et ctr+x pour quitter
- créer un fichier [Link]
nano [Link]
10
- écrire le code suivant :
#!/usr/bin/env python
import sys
prev_word=None
prev_count=0
for line in [Link]:
line=[Link]()
word,count=[Link]('\t')
count=int(count)
if prev_word==word:
prev_count+=count
else:
if prev_word:
print('%s\t%s' %(prev_word,prev_count))
prev_count=count
prev_word=word
if prev_word==word:
print('%s\t%s'%(prev_word,prev_count))
1. executer le code en local
cat [Link] | python [Link]
salut 1
hello 1
salut 1
bienvenue 1
salut 1
salut 1
hello 1
hello 1
salut 1
bienvenue 1
bienvenue 1
hi 1
cat [Link] | python [Link] | sort
bienvenue 1
bienvenue 1
11
bienvenue 1
hello 1
hello 1
hello 1
hi 1
salut 1
salut 1
salut 1
salut 1
salut 1
cat [Link] | python [Link] | sort| python [Link]
bienvenue 3
hello 3
hi 1
salut 5
2. exécuetr le code sur Hadoop
- hadoop jar /usr/local/hadoop/share/hadoop/tools/lib/[Link] -file [Link]
-mapper [Link] -file [Link] -reducer [Link] -input /user/root/input/[Link] -output
/user/root/out7
- hadoop fs -ls /user/root/out7
-rw-r--r-- 2 root supergroup 0 2021-10-27 13:36 /user/root/out7/_SUCCESS
-rw-r--r-- 2 root supergroup 499048 2021-10-27 13:36 /user/root/out7/part-00000
- hadoop fs -ls /user/root/out7/part-00000
- cat part-00000
12