TP1 : Mise en place d’un traitement en lots : Hadoop, MapReduce et YARN
Objectifs du TP : Au terme de ce TP, vous serez capable de :
- Configurer un cluster avec un Name Node et des Data Nodes
- Réaliser un programme de Map Reduce sur un fichier avec Hadoop
Manipulation 1 : Mise en place de l’environnement
Dans cette première manipulation, vous allez préparer l’environnement sur vos machines virtuelles.
Pour ce faire, créez tout d’abord un répertoire lab1 où vous allez créer votre fichier docker-compose.yml
dont le contenu est le suivant:
version: "3.3"
networks:
net:
driver: bridge
ipam:
config:
- subnet: 172.22.0.0/24
services:
namenode:
image: bde2020/hadoop-namenode:2.0.0-hadoop3.2.1-java8
container_name: namenode
restart: always
ports:
- 9870:9870
- 9000:9000
volumes:
- hadoop_namenode:/hadoop/dfs/name
environment:
- CLUSTER_NAME=test
env_file:
- ./hadoop.env
networks:
- net
datanode:
image: bde2020/hadoop-datanode:2.0.0-hadoop3.2.1-java8
container_name: datanode
restart: always
volumes:
- hadoop_datanode:/hadoop/dfs/data
environment:
SERVICE_PRECONDITION: "namenode:9870"
env_file:
- ./hadoop.env
networks:
- net
resourcemanager:
image: bde2020/hadoop-resourcemanager:2.0.0-hadoop3.2.1-java8
container_name: resourcemanager
restart: always
environment:
SERVICE_PRECONDITION: "namenode:9000 namenode:9870 datanode:9864"
env_file:
- ./hadoop.env
ports:
- "8088:8088"
networks:
- net
nodemanager1:
image: bde2020/hadoop-nodemanager:2.0.0-hadoop3.2.1-java8
container_name: nodemanager
restart: always
environment:
SERVICE_PRECONDITION: "namenode:9000 namenode:9870 datanode:9864 resourcemanager:8088"
env_file:
- ./hadoop.env
networks:
- net
historyserver:
image: bde2020/hadoop-historyserver:2.0.0-hadoop3.2.1-java8
container_name: historyserver
restart: always
volumes:
- hadoop_historyserver:/hadoop/yarn/timeline
environment:
SERVICE_PRECONDITION: "namenode:9000 namenode:9870 datanode:9864 resourcemanager:8088"
env_file:
- ./hadoop.env
networks:
- net
volumes:
hadoop_namenode:
hadoop_datanode:
hadoop_historyserver:
et créez également le fichier de configuration hadoop.env dont le contenu est le suivant:
# CORE
CORE_CONF_fs_defaultFS=hdfs://namenode:9000
CORE_CONF_hadoop_http_staticuser_user=root
CORE_CONF_hadoop_proxyuser_hue_hosts=*
CORE_CONF_hadoop_proxyuser_hue_groups=*
CORE_CONF_io_compression_codecs=org.apache.hadoop.io.compress.SnappyCodec
# HDFS
HDFS_CONF_dfs_webhdfs_enabled=true
HDFS_CONF_dfs_permissions_enabled=false
HDFS_CONF_dfs_namenode_datanode_registration_ip___hostname___check=false
# YARN
YARN_CONF_yarn_log___aggregation___enable=true
YARN_CONF_yarn_log_server_url=http://historyserver:8188/applicationhistory/logs/
YARN_CONF_yarn_resourcemanager_recovery_enabled=true
YARN_CONF_yarn_resourcemanager_store_class=org.apache.hadoop.yarn.server.resourcemanager.recovery.FileSystemRMStateStore
YARN_CONF_yarn_resourcemanager_scheduler_class=org.apache.hadoop.yarn.server.resourcemanager.scheduler.capacity.CapacityScheduler
YARN_CONF_yarn_scheduler_capacity_root_default_maximum___allocation___mb=8192
YARN_CONF_yarn_scheduler_capacity_root_default_maximum___allocation___vcores=4
YARN_CONF_yarn_resourcemanager_fs_state___store_uri=/rmstate
YARN_CONF_yarn_resourcemanager_system___metrics___publisher_enabled=true
YARN_CONF_yarn_resourcemanager_hostname=resourcemanager
YARN_CONF_yarn_resourcemanager_address=resourcemanager:8032
YARN_CONF_yarn_resourcemanager_scheduler_address=resourcemanager:8030
YARN_CONF_yarn_resourcemanager_resource__tracker_address=resourcemanager:8031
YARN_CONF_yarn_timeline___service_enabled=true
YARN_CONF_yarn_timeline___service_generic___application___history_enabled=true
YARN_CONF_yarn_timeline___service_hostname=historyserver
YARN_CONF_yarn_nodemanager_resource_memory___mb=16384
YARN_CONF_yarn_nodemanager_resource_cpu___vcores=8
YARN_CONF_yarn_nodemanager_disk___health___checker_max___disk___utilization___per___disk___percentage=98.5
YARN_CONF_yarn_nodemanager_remote___app___log___dir=/app-logs
YARN_CONF_yarn_nodemanager_aux___services=mapreduce_shuffle
# MAPREDUCE
MAPRED_CONF_mapreduce_framework_name=yarn
MAPRED_CONF_mapred_child_java_opts=-Xmx4096m
MAPRED_CONF_mapreduce_map_memory_mb=4096
MAPRED_CONF_mapreduce_reduce_memory_mb=8192
MAPRED_CONF_mapreduce_map_java_opts=-Xmx3072m
MAPRED_CONF_mapreduce_reduce_java_opts=-Xmx6144m
# Important : Hadoop home pour MapReduce
MAPRED_CONF_yarn_app_mapreduce_am_env=HADOOP_MAPRED_HOME=/opt/hadoop-3.2.1
MAPRED_CONF_mapreduce_map_env=HADOOP_MAPRED_HOME=/opt/hadoop-3.2.1
MAPRED_CONF_mapreduce_reduce_env=HADOOP_MAPRED_HOME=/opt/hadoop-3.2.1
Lancez le réseau de containers en lançant la commande suivante:
docker-compose up -d
Vous devez avoir cet affichage montrant que votre réseau de contenainers a été bien créé:
En accédant les liens suivants, vous pouvez visualiser l’état de votre namenode et de YARN:
- http://localhost:9870 qui permet d’afficher les informations de votre namenode.
- http://localhost:8088 qui permet d’afficher les informations du resource manager de Yarn et visualiser le comportement des différents jobs.
Maintenant, dans le même répertoire, téléchargez le fichier purchases.txt, disponible sur ce lien
. Nous allons maintenant le mettre dans le container namenode dans un répertoire à nommer input.
Pour ce faire, exécutez la commande suivante :
sudo docker exec -it namenode hadoop fs -mkdir -p input
Ensuite, déplacez le fichier purchases.txt vers le répertoire input.
sudo docker cp purchases.txt namenode:/purchases.txt
sudo docker exec -it namenode hadoop fs -put purchases.txt input
Vérifiez l’existence de ce fichier dans votre HDFS:
sudo docker exec -it namenode hadoop fs -ls input
Lancez la commande tail suivante pour avoir l’affichage des dernières lignes du fichier purchases.txt :
sudo docker exec -it namenode hadoop fs -tail input/purchases.txt
Avant de passer à la deuxième partie, vous devez vous assurer que vous avez bien jdk sur votre machine en tapant:
java -version
Si vous n’avez pas de jdk installé sur vos machines, vous pouvez l’installer en lançant la commande suivante:
sudo apt get update
sudo apt install default-jdk -y
Ensuite, mettez à jour votre variable d’environnement PATH en obtenant tout d’abord le chemin vers le dossier bin:
sudo update-alternatives --config java
Ensuite, vous affectez le chemin correct à la variable JAVA_HOME:
export JAVA_HOME=/usr/lib/jvm/java-11-openjdk-amd64/bin/java
Finalement, la variable PATH doit contenir le chemin:
export PATH=$JAVA_HOME/bin:$PATH
Manipulation 2
Dans cette manipulation, nous réalisons un job Map-Reduce. Un Job Map-Reduce se compose principalement de deux types de programmes :
- Mappers : permettent d’extraire les données nécessaires sous forme de clef/valeur, pour pouvoir ensuite les trier selon la clef
- Reducers : prennent un ensemble de données triées selon leur clef, et effectuent le traitement nécessaire sur ces données (somme, moyenne, total…)
Nous testerons un exemple de MapReduce qui va compter les mots dans le fichier purchases.txt. Afin de simplifier ce test de démarrage, je vous invite à cloner une repository de mon compte Github à l’aide de Git en suivant les étapes suivantes :
| Étape | Illustration |
|---|---|
| 1. Ouvrez IntelliJ IDEA et cliquez sur « Get from VCS ». | |
| 2. Rendez-vous sur le dépôt GitHub du projet et copiez le lien pour cloner le projet. | |
3. Ouvrez le fichier WordCount.java (dans src/main/java/...), puis cliquez sur Current File → Run Configuration.Sélectionnez JDK 11 et indiquez le chemin vers votre classe main. Dans Program Arguments, ajoutez : src/main/resources/input/file.txt src/main/resources/output |
|
| 4. Le fichier à analyser se trouve sous resources/input/file.txt. Exécutez le programme localement sur un fichier léger (file.txt) avant de le lancer sur le cluster. Après exécution, un dossier output sera créé dans resources, contenant les fichiers résultats du programme WordCount. Vous pouvez modifier le contenu de file.txt et relancer l’application pour observer l’effet du programme. |
|
5. Ouvrez le menu Maven (à droite), cliquez sur Install pour générer le fichier .jar. |
Exécution avec le réseau de docker-compose
Remarque: En accédant à n’importe quel conteneur (container), vous êtes capables de lancer les commandes de hdfs et avoir le même résultat.
Nous chargeons le fichier jar Wordcount2-0.jar, généré par votre application, sur le même container en se plaçant sous le dossier target qui se trouve en local (hors des containers, sur votre machine) et ce en tapant:
sudo docker cp Wordcount2-0.jar namenode:/Wordcount2-0.jar
Enfin, lancez MapReduce en tapant:
sudo docker exec -it namenode hadoop jar Wordcount2-0.jar tn.enit.tp1.WordCount input output
Le résultat de l’exécution sera comme suit:
Après avoir terminé, visualisez le résultat :
sudo docker exec -it namenode hadoop fs -tail output/part-r-00000
Homework
Sachant que le fichier purchases.txt présente les informations suivantes par colonne:
date\ttime\tstore name\titem description\tcost\tmethod of payment
Ecrire deux programmes MapReduce pour :
- 1 Déterminer le moyen de paiement le plus utilisé.
- 2 Déterminer le magasin ayant réalisé le plus de ventes.