TP1 Mise en place d'un traitement en lots

Premier TP

By Mariem ZAOUALI

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éé: image

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 ». Get from VCS
2. Rendez-vous sur le dépôt GitHub du projet et copiez le lien pour cloner le projet. Lien du dépôt GitHub
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
Configuration de l'exécution
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.
Résultat de l'exécution locale
5. Ouvrez le menu Maven (à droite), cliquez sur Install pour générer le fichier .jar. Génération du jar avec Maven

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: image

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.