Démarrez avec HDInsight Server !

Les billets Installation d'HDInsight Server (Hadoop) sur une machine Windows et Créer une machine virtuelle HDInsight Server sur Windows Azure disponibles sur ce blog vous ont accompagné quant à la mise en place d’un cluster de test HDInsight Server de façon à disposer rapidement de services Hadoop opérationnels en environnement Windows.

Quelle que soit l’approche que vous ayez retenue au final, nous supposons dans ce billet que vous disposez à ce stade d’une installation opérationnelle d’HDInsight Server.

Une rapide présentation

Rendez-vous dans le dossier C:\Hadoop. C’est ici que tout a été installé.

image

Comme vous pouvez le constater, ce dossier racine contient un ensemble de dossiers :

  • Avec un premier lieu, un dossier GettingStarted auquel nous allons nous intéresser très prochainement ;
  • Un dossier hadoop-1.1.0-SNAPSHOT correspondant au dossier système d’Hadoop dans l’implémentation Hortonworks Data Platform (HDP) 1.1.0 pour Windows Server d’Hortonworks ;
  • Un dossier HDFS où seront stockées les données sur ce nœud (mais nous n’avons qu’un nœud ici…) ;
  • Les dossiers Hive-0.9.0, pig-0.9.3-SNAPSHOT et sqoop-1.4.2 qui contiennent respectivement les projets/surcouches Apache Hive (en version 0.9.0), Apache Pig (en version 0.9.3), Apache Sqoop (en version 1.4.2). Hive est un logiciel d'analyse de données permettant d'utiliser Hadoop avec une syntaxe proche du SQL appelé HiveQL et ce, via un mécanisme permettant de projeter une structure sur ces données. Pig est une plateforme d'analyse de données comparable à Hive, mais qui utilise le langage Pig Latin. Enfin, Sqoop est un outil conçu pour l'importation et l'exportation de données à partir de magasins de données structurées telles que des bases de données relationnelles, des entrepôts de données d'entreprise et des systèmes NoSQL ;
  • Un dossier java où la machine virtuelle Java (JVM) est installée ;
  • Un dossier websites intéressant à certains égards pour nous faciliter la vie au quotidien avec, par exemple, la console JavaScript ou encore l’interface de gestion du cluster, etc.

Ce dossier racine contient enfin les deux scripts start-onebox et stop-onebox pour respectivement démarrer et arrêter le service Hadoop. Dans notre cas de figure, il est déjà démarré.

Naviguez à présent dans le dossier GettingStarted (C:\Hadoop\GettingStarted). Ce dernier contient trois scripts Windows PowerShell :

  1. buildSamples.ps1 pour compiler les codes source si vous faites des modifications.
  2. importData.ps1 pour importer depuis un serveur IIS ses fichiers journaux (log) au format W3C Logging.
  3. runSamples.ps1 pour lancer les programmes en C# ou en Java, etc. sur le jeu de données importé auparavant.

Sélectionnez le fichier importData.ps1, faites un clic droit, puis sélectionnez Exécuter avec PowerShell pour le lancer. Trois fichiers appelés data_w3c_small.txt, data_w3c_medium.txt, et data_w3c_large.txt sont alors produits.

image

Le script insère ensuite directement les fichiers générés dans HDFS. Pour le vérifier, lancez le Hadoop Command Line (icone sur le bureau) puis tapez la ligne suivante :

hadoop dfs –ls /w3c/input

Une rapide explication s’impose : hadoop fait appel à l’application, dfs spécifie que nous voulons accéder au système de fichiers, -ls est un argument qui précise de lister les éléments trouvés (comme sous Unix), et /w3c/input/ correspond au chemin du dossier.

Vous devriez voir trois dossiers comme ceci :

image

Le répertoire small contient le fichier data_w3c_small.txt, et ainsi de suite.

Intéressons-nous à présent au script runSamples.ps1. Ce dernier prend 4 arguments :

  1. scenario : vous n’en avez qu’un à considérer ici : en l’occurrence « w3c ».
  2. size : « small », « medium » ou « large ». Cela correspond au volume de données que vous voulez analyser. Plus il sera petit, plus l’analyse sera rapide (avec toutefois un temps non compressible lié à la soumission du job lui-même).
  3. method : « csharp », « java », « pig », ou « hive ». Cela correspond aux deux différentes implémentations du programme, l’une est en Java (dans le dossier du même nom) et l’autre en C#. Vous pouvez d’ailleurs y « jeter un œil » au passage. Pig et Hive présentent simplement un cas d’utilisation dans les deux langages.
  4. job : « totalhits », « avgtime » ou « errors ». Ce sont vos cas de test. Le premier calcule sur les données le nombre total de vues pour chaque page ; il en ressort une liste. Le deuxième exprime la durée moyenne qu’un utilisateur passe sur une page ; de façon similaire, il en ressort la liste des pages avec le temps passé dessus. Le troisième indique combien d’erreurs sont affichées sur le nombre de visionnages ; cela permet de savoir quelle page pose le plus de problèmes aux visiteurs.

Ces précisions faites, il vous suffit de lancer runSamples dans la console Windows PowerShell depuis le répertoire GettingStarted :

cd c:/hadoop/GettingStarted/)
powershell –ExecutionPolicy unrestricted –F runSamples.ps1 w3c small java avgtime

La commande powershell permet d’exécuter tout simplement des scripts Windows PowerShell : l’argument -ExecutionPolicy est nécessaire pour exécuter sans erreur le script, l’argument -F spécifie l’emplacement et le nom du script. Les quatre mots suivants sont les arguments injectés dans le script PowerShell et correspondent dans l’ordre aux arguments scenario, size, method, et job vus ci-avant.

image

Votre job est lancé : vous allez voir apparaître le pourcentage d’avancement des deux étapes « map » et « reduce ». A la fin du traitement, l’affichage de la console permet de faire ressortir le top 3 des pages avec un temps moyen le plus élevé.

Cette rapide introduction étant faite, intéressons-nous à votre première application.

 

Une première application « from scratch »

Pour votre première application, nous avons besoin d’une problématique à traiter : « Vous voulez savoir quels sont les types de browsers utilisés par les utilisateurs du site hébergé par votre serveur IIS ».

Pour ce faire, vous avez à disposition les fichiers journaux récupérés par l’exercice précédent. Examinons-les.

Ouvrez le fichier data_w3c_small sous C:\Hadoop\GettingStarted\w3c\ data_w3c_small.txt.

On constate que le fichier est constitué de 15 colonnes. Celle qui vous intéresse est l’avant dernière (la 14) : cs(User-Agent) :

image

Vous pouvez vous reporter au format W3C Logging des fichiers journaux d’IIS pour plus de détails ici. En bref, pour ce qui vous intéresse dans le cas présent compte tenu de l’objectif fixé, User-Agent correspond au type de browser. Vous aurez notamment d’indiqué le moteur HTML et le nom du navigateur ensuite.

L’exemple suivant indique que l’utilisateur possède Internet Explorer 10 avec le moteur de rendu HTML Trident (vous savez aussi que le navigateur est installé sur le système d’exploitation Windows 7) :

Mozilla/5.0+(compatible;+MSIE+10.0;+Windows+NT+6.1;+WOW64;+Trident/6.0)

L’article User Agent String explained vous donne toutes les informations nécessaires sur le browser correspondant à un User Agent donné.

Algorithme

Passons maintenant à l’algorithme Map/Reduce qui sera appliqué par Hadoop sur chacune de nos données.

Vous allez à présent écrire cette application en JavaScript via la console interactive proposée dans le portail de gestion Microsoft HDInsight Dashboard qui vous permettra de le faire simplement.

Il est en effet proposé aux utilisateurs d’HDInsight (que ça soit Windows Azure HDInsight ou HDInsight Server comme ici) d’écrire le code Map/Reduce en JavaScript. Vous noterez que ceci n’est pas proposé par défaut dans Apache Hadoop.

Une telle capacité permet de se concentrer uniquement sur les parties « importantes » de notre algorithme et masque les parties « superficielles » de Map/Reduce en Java comme les « imports » ou encore l’instanciation de types spécifiques.

Le code de démonstration est censé être clair… Vous nous le direz ;)

Ouvrez votre environnement de développement (IDE) préféré pour faire du JavaScript. C’est parti ! Si vous n’en avez pas, vous pouvez vous prendre Notepad++ comme dans la suite de ce billet pour les exemples d’illustration. Vous pouvez trouver télécharger une version ici.

A ce stade, vous vous êtes intéressés à la structure fichier journal et vous en avez retiré le numéro de colonne de UserAgent : la 14ème.

Map

Le modèle de base pour la méthode map en JavaScript est la suivante ; A vous de la personnaliser.

var map = function(cle, valeur, context){

       

}

Vous y ajoutez ceci :

var parties = valeur.split(new RegExp("\\s"));

Vous éclatez ainsi la valeur qui vous est passée en paramètre dans un tableau parties via une expression régulière. L’élément de séparation des colonnes est \s ce qui correspond à un espace tout simplement. Pour une première initiation aux expressions régulières, vous pouvez par exemple vous reporter au tutoriel Les expressions régulières.

La suite :

if(parties.length != 15 || parties[13] == "-")

   return;

Vous testez si le tableau « parties » ne contient pas 15 cases pour savoir si le « record » est bien formaté. Vous regardez ensuite si la case n°14 (c’est-à-dire la 13 en partant de 0) est égale au caractère "-", ce qui indiquerait l’absence de donnée. Si ces tests réussissent, alors le record est mal formé et vous ne pouvez pas récupérer de clé valide à insérer dans la Map. Donc vous passez au record suivant.

Cette ligne permet d’émettre le résultat de la méthode map sur le record courant.

context.write(p

arties[13], 1) ;

Voici le code complet :

var map = function(cle, valeur, context){

   var parties = valeur.split(new RegExp("\\s"));

       

   if(parties.length != 15 || parties[13] == "-")

      return;

 

   context.write(parties[13], 1);

}

Vous en avez fini avec cette méthode. Passons à l’implémentation de votre Reducer.

Reduce

Le modèle de base se définit comme ceci :

var reduce = function(cle, valeurs, context){

       

}

Il reçoit en paramètre la clé à laquelle corresponds plusieurs valeurs. Un objet context aussi permet d’émettre le résultat final.

var somme = 0 ;

C’est votre variable stockant la somme de toutes les valeurs.

while(valeurs.hastNext()){

   somme += parseInt(valeurs.next());

}

Vous bouclez sur les valeurs pour additionner celles-ci dans la somme.

context.write(cle, somme);

Vous émettez la somme finale pour la clé correspondante.

Voici le code complet :

var map = function(cle, valeur, context){

   var parties = valeur.split(new RegExp("\\s"));

       

   if(parties.length != 15 || parties[13] == "-")

      return;

       

   context.write(parties[13], 1);

}

 

var reduce = function(cle, valeurs, context){

   var somme = 0;

       

   while(valeurs.hasNext()){

      somme += parseInt(valeurs.next());

   }

       

   context.write(cle, somme);

}

Exécution

Vous en avez terminé pour ce qui est du code. Enregistrez ce fichier par exemple sous le nom navigateurs_detection.js à la racine du disque C :

Ensuite, sur le bureau de la machine virtuelle, exécutez le portail de gestion Microsoft HDInsight Dashboard en cliquant sur le raccourci éponyme.

image

Cliquez ensuite sur Interactive Console dans la section Your Cluster : https://localhost:8085/Cluster/InteractiveJS

Exécutez la procédure suivante : Tapez « #put » dans la console puis  « Entrée ». Cette commande appelle en réalité le système de fichier HDFS pour y insérer un nouveau fichier. Avant d’exécuter du code avec Hadoop, il sera impératif de l’ajouter sur HDFS. Le # dans la console interactiveprécise que la commande suivant celui-ci est une commande générale d’Hadoop. Cette commande #put correspond à :

hadoop dfs –put c:/monfichier.ext /mondossierhdfs/monfichier.ext

image

Dans Source, cliquez sur Browse pour parcourir et recherchez le fichier JavaScript C:\navigateurs_dectection.js.

Dans Destination, précisez « ./navigateurs_detection.js », puis cliquez sur Upload

image

A ce stade, vous avez placé votre premier fichier sur HDFS en utilisant la console interactive.

Vous devez vous assurer que le dossier « /w3c/out » qui stockera le résultat n’existe pas, sinon lors de l’exécution du programme, vous rencontrerez une erreur comme suit : « … at org.apache.hadoop.util.RunJar.main(RunJar.java:…)… ».

En effet, le système HDFS stocke les données une et une seule fois, aucune mise à jour n’est possible ; le caractère immuable des données fait que la parallélisation est possible. Les fichiers que vous stockez sont pour cette raison au final en lecture seule. Si nécessaire, vous pouvez les supprimer au préalable via la commande Hadoop rmr. Entrez la ligne suivant dans la console JS :

#rmr /w3c/out

Exécutez ensuite notre code par le biais de la commande runJs :

runJs("navigateurs_detection.js", "/w3c/input/large", "w3c/out") ;

La fonction runJs prend comme premier paramètre le chemin d’accès du fichier JavaScript contenant les fonctions map() et reduce() . Le deuxième paramètre représente le chemin du répertoire des données à traiter. Vos fichiers journaux sont stockés dedans. Le troisième indique le chemin où sera stocké le résultat de votre traitement Map/Reduce sur les données d’entrée.

image

Une fois l’exécution terminée, un message apparait du type « INFO mapred.JobClient : Map output records=5656 ». Le loader, lui, disparaitra.

Visualisation du résultat

L’exécution de votre programme étant terminée, le résultat a été placé sous le répertoire /w3c/out. Certes, mais comment visualise-t-on le résultat de manière compréhensible ?

Vous pouvez visionner le résultat dans la console JavaScript:

fichier = fs.read("/w3c/out");

Nom du browser User Agent (chaine identifiant le browser) Décompte
Chrome 22 Mozilla/5.0+(Windows+NT+6.1;+WOW64)+AppleWebKit/537.1+(KHTML,+like+Gecko)+Chrome/22.0.1207.1+Safari/537.1 962
Internet Explorer 6 Mozilla/5.0(Windows; +U;+MSIE+6.0;+Windows+NT+5.1;+SV1;+.NET+CLR+2.0.50727) 1905
Firefox 14 Mozilla/5.0+(Windows;+U;+Windows+NT+6.1;+WOW64;+en-US;+rv:2.0.4)+Gecko/20120718+AskTbAVR-IDW/3.12.5.17700+Firefox/14.0.1 919
Firefox 14 pour Ubuntu Mozilla/5.0+(X11;+Ubuntu;+Linux+x86_64;+rv:14.0)+Gecko/20100101+Firefox/14.0.1 919
Internet Explorer 10 Mozilla/5.0+(compatible;+MSIE+10.0;+Windows+NT+6.1;+WOW64;+Trident/6.0) 951

Graph

Il est possible, via la console JavaScript et l’objet graph, de générer des graphiques en fonction des données récupérées. Il faut cependant les préparer au préalable, et ce de façon à ce que graph connaisse le formatage de notre résultat.

Commencez par récupérer votre variable « fichier » remplie précédemment, puis parcourez-la à l’aide de la méthode parse :

resultat = parse(fichier.data, "userAgent,count:long");

La méthode parse dé-sérialise la chaine contenue dans fichier.data dans un tableau JavaScript (Array). Vous devez lui indiquer comment est formatée la chaine et quelles sont les colonnes avec leurs types (si le type est absent, string est mis par défaut) : userAgent et count.

Voici ce qui est affiché :

[

    0: {

        userAgent: "Mozilla/5.0+(Windows+NT+6.1;+WOW64)+AppleWebKit/537.1+(KHTML,+like+Gecko)+Chrome/22.0.1207.1+Safari/537.1"

        count: "962"

    }

    1: {

        userAgent: "Mozilla/5.0+(Windows;+U;+MSIE+6.0;+Windows+NT+5.1;+SV1;+.NET+CLR+2.0.50727)"

        count: "1905"

    }

    2: {

        userAgent: "Mozilla/5.0+(Windows;+U;+Windows+NT+6.1;+WOW64;+en-US;+rv:2.0.4)+Gecko/20120718+AskTbAVR-IDW/3.12.5.17700+Firefox/14.0.1"

        count: "919"

    }

    3: {

        userAgent: "Mozilla/5.0+(X11;+Ubuntu;+Linux+x86_64;+rv:14.0)+Gecko/20100101+Firefox/14.0.1"

        count: "919"

    }

    4: {

        userAgent: "Mozilla/5.0+(compatible;+MSIE+10.0;+Windows+NT+6.1;+WOW64;+Trident/6.0)"

        count: "951"

    }

]

Comme vous l’aurez probablement reconnu, il s’agit d’une structure JSON (JavaScript Objet Notation), qui contient 5 éléments. Chaque élément possède deux attributs : userAgent et count.

Le fait que vous utilisiez JavaScript permet certaines facilités quant à la modification dynamique de cette structure. Vous allez donc en profiter et ajouter un 3ème attribut, en l’occurence name, et ainsi donner un nom simplifié aux browsers.

D’après le tableau précédent, appliquez le code suivant dans la console :

resultat[0].name = "Chrome 22"; resultat[1].name = "Internet Explorer 6"; resultat[2].name = "Firefox 14"; resultat[3].name = "Firefox 14 Linux"; resultat[4].name = "Internet Explorer 10";

Vous avez ainsi modifié pour chacun des résultats la structure de l’élément en ajoutant un attribut name.

Construisez maintenant la structure pour paramétrer votre graphique. D’après la documentation, l’objet options se compose des éléments suivants :

options (object) objet d’options, avec
x (string) Indique quelle propriété est en abscisse
y (string) Indique quelle propriété est en ordonnée
title (string) Le titre du graphique
orientation (number) Utile pour incliner les entêtes de colonne
tickInterval (number) Pour décaler les entêtes de colonne

Tapez le code suivant :

options = {x :"name", y : "count", title: "Popularité des navigateurs sur le site"};

Vous êtes prêts à présent pour lancer la génération du graphique. Entrez la ligne suivante :

graph.pie(resultat, options);

Et voilà!

image

graph est le nom de l’objet JavaScript exposé par la console interactive. La fonction pie peut être remplacée par la fonction bar pour avoir un graphique de type histogramme. A vous de jouer à présent !

Pour cela, vous pouvez visionner la démonstration didactique réalisée par Benjamin Guinebertière lors des après-midi du développement, reprendre le tutoriel Using Interactive JavaScript for Data Visualization in Hadoop on Windows Azure Cluster, consulter le tutoriel Running Hadoop Jobs on Windows Azure, Importing Data from Windows Azure Marketplace, and Analysing the Data with the Excel Hive Add-In sur le lancement de jobs avec HDInsight, l’importation de données récupérées depuis Windows Azure Marketplace, ainsi qu’une analyse finale des données avec Excel, etc.

Ceci conclut notre billet. Bien sûr, vous pouvez suivre la même procédure de programme JavaScript sous Windows Azure HDInsight Service comme ce service propose la même console interactive. A ce propos, vous trouverez une documentation sur l’utilisation de la console interactiveici.