Archives de Catégorie: Getting started

Getting started with Apache Camel : Part 1

Je voulais écrire un court billet sur les tests dans Camel. Puis je me suis rendu compte que je n’avais jamais évoqué Camel sur ce blog. Ce qui est un peu étrange vu que c’est le framework que j’utilise tous les jours, sur plusieurs projets, depuis plus d’un an. Et que c’est l’un des outils les plus cools et les plus indispensables pour garder votre intégrité mentale dès qu’il s’agit de router des messages entre différentes machines/protocoles/wtf has imagined the architect guy before you.

Donc je vais vous raconter comment on peut faire des trucs géniaux dans Camel. D’abord le nom complet est Apache Camel, un projet qui fête ses 5 ans, avec pas mal de contributeurs, dont une grande partie vient de la société FuseSource (récemment acquise par RedHat). Pas vraiment de soucis à se faire sur la maturité du projet donc. Mais à quoi ça sert ? Il faut voir Camel comme un routeur de messages entre vos différents applicatifs, certains appelleront ça un ESB léger. D’ailleurs Apache Service Mix, qui est l’artellerie lourde en matière d’ESB Apache se base sur Camel pour sa gestion des routes. D’autres appelleront ça un framework d’intégration, à la Spring Integration mais en plus complet et plus agréable à utiliser. D’ailleurs si vous êtes un fan de Spring, aucun problème l’interopérabilité est vraiment excellente.

Les introductions à Camel me laissent toujours un peu sur ma faim, sans doute parce que ce n’est pas au premier coup d’oeil que l’on comprend sa puissance. Mais au fil des projets, on tombe sur souvent sur des use cases qui correspondent exactement à ce que propose Camel dans un de ses nombreux modules ou patterns, et c’est la que la magie opère. Ce n’est pas rare que l’on me demande d’ajouter une fonctionnalité et que Camel permette de répondre : ‘Pas de problème, il y a un pattern qui fait exactement ça’.

Il faut un peu de temps pour se faire au fonctionnement et appréhender les différents patterns. Car, au début, Apache Camel à été créé comme une implémentation Open Source des EIPs (Enterprise Integration Patterns), qui sont à peu près aussi chiants à lire que les Design Pattern : tant que l’on n’en a pas eu besoin ça n’a pas vraiment de sens.

Organisation
Quand vous démarrez un projet, vous n’avez besoin que d’une seule dépendance : camel-core (actuellement en version 2.10.x). Elle contient les fameux EIPs de base ainsi que la gestion des protocoles les plus courants (fichier par exemple). Ensuite si vous voulez faire quelque chose d’autre comme des appels ftp, il faut ajouter le module correspondant, camel-ftp, dans vos dépendances. La liste des modules disponibles est impressionante : vous pouvez interagir avec tout ce dont vous pouvez avoir besoin : de MongoDb à un AS400 en passant par un LDAP, Nagios, JDBC, des flux RSS… Il y a également des modules qui ne sont pas dans le repo officiel (c’était le cas des Websockets jusqu’à peu encore) car ils sont en cours de stabilisation, ou d’autres pour des problèmes de licence (module SAP par exemple). Tous les protocoles réseaux sont également gérés. Bref il faut faire quelque chose de très très exotique pour ne pas trouver son bonheur.

Pour avoir modestement contribué à quelques bugfixes et features, le code du core est très bien pensé, écrit et testé. Les modules sont eux de qualité un peu plus variable, mais tous ceux couramment utilisés sont très bien faits et production-ready.

A quoi ca ressemble une route ?
Ces routes peuvent être écrites en XML, mais comme 95% des développeurs je trouve ça pas terriblement fun, j’utilise l’autre alternative, la DSL fournie par Camel, qui permet d’écrire les routes directement en Java (qui a en plus l’immense avantage de vous donner l’autocomplétion dans votre IDE). C’est un peu perturbant au début, parce que l’on écrit pas des méthodes comme dans un projet classique, on écrit la déclaration des routes que les messages vont suivre dans l’application.

Par exemple :

from("file://inbox?delete=true").to("bean:handleOrder").to("file:outbox");

Voilà, ça c’est une route. Basique certes, mais qui permet de récupérer un fichier dans un répertoire inbox, d’envoyer son contenu (que l’on imagine être une liste de commande) à un bean Java qui s’occupera de les traiter, avant de placer le fichier de commandes traitées dans un répertoire outbox.

Même si on a jamais fait de Camel de sa vie, la DSL se lit assez bien, une déclaration de route se fait de la façon suivante :
– un point d’entrée (identifié par le ‘from’) qui s’appelle un Endpoint en langage Camel. Le triplet de déclaration d’un endpoint est souvent le même à savoir un protocole (ici ‘file’), un nom (ici ‘inbox’ qui correspond au répertoire) puis des options après le ? (ici pour indiquer que les fichiers sont supprimés après lecture)
– un ensemble d’étape (identifiés par ‘to’), la dernière étant le point de sortie, sur le même modèle.

Dans cette route il n’y a pas de pattern particulier, c’est une route basique du type ‘mon message va de là à là’. Camel va se charger pour vous de faire les conversions de type nécessaire. Si les commandes sont en xml dans le fichier, il va convertir le xml en objets Java pour pouvoir appeler le bean de traitement de commande, puis reconvertir en xml pour les placer dans le fichier de sortie.

Admettons que maintenant votre système de commande expose également un webservice REST qui doit appeler le même bean et également pousser le fichier de commandes traitées dans le répertoire outbox. Easy! D’abord on découpe la route précédente en 2, grâce au mot clé ‘direct’ qui est en fait un moyen de créer des sous routes.

from("file://inbox?delete=true").to("direct:orders");
 from("direct:orders").to("bean:handleOrder").to("file:outbox");

Maintenant ajouter le webservice se résume à créer une route qui écoute les requêtes entrantes grâce au module cxfrs pour du REST et qui appelle la route direct:orders

from("cxfrs:bean:orderRest").to("direct:orders");

Il y a bien sûr un peu de code pour indiquer à cxfrs que l’on attend les requêtes sur tel port avec tels paramètres, mais la route en elle-même se réduit à ça.

Pattern
Avant de voir un premier pattern, il faut comprendre comment sont organisés les messages dans Camel. Nous avons vu que la déclaration de route est une suite d’étapes. Entre chacune de ces étapes, l’objet qui va transiter est un Exchange, qui contient un message In et un message Out. A chaque étape l’exchange entre avec le message In rempli et le message Out vide, puis la partie Out va être remplie avec le résultat de l’étape. Lors de l’étape suivante, ce message Out va devenir le message In et ainsi de suite. Une fois que l’on a compris ce principe de chaine (un out devient le in de l’étape suivante, qui remplit le out, qui devient à son tour le message in de l’étape suivante etc…), tout devient très simple. Un message en lui même est composé d’un ensemble de header et d’un body.

Donc si vous voulez utiliser un pattern Camel comme par exemple filtrer les messages, vous utilisez la fonction filter dans la DSL

from("direct:orders").filter(header("filiale").isEqualTo("Europe")).to("direct:europe");

Si vos commandes de la filiale Europe doivent subir un traitement spécial, vous pouvez filtrer les messages sur ce header. Camel fournit pas mal de méthode pour établir ces filtres de façon simple (ici sur un header), mais vous pouvez également appeler une méthode de votre métier pour filtrer.

Allez, un dernier exemple de pattern moins connu que filter et qui sert beaucoup : ‘recipientList’. Il permet de router dynamiquement un message.
Par exemple :

from("direct:orders").recipientList(header("filiale").prepend("direct:"));
 from("direct:europe").to(...);
 from("direct:asie").to(...);

Camel va appeler la sous-route qui correspond à la bonne filiale. Si vous ajouter une nouvelle filiale dans votre SI, vous avez seulement à écrire la sous route qui correspond. C’est pas cool ça?

J’ai encore des dizaines de trucs géniaux sur Camel, mais on va s’arrêter là pour aujourd’hui et on reprendra la prochaine fois. Stay tuned!

Publicités

CSS sucks, do Less!

L’écriture d’une feuille de style est l’un des moments les plus douloureux pour tout développeur Web : la science occulte des CSS et sa verbosité en font une soupe rarement agréable à avaler. Mais un outil peut changer tout ça : Less!

Less est un preprocesseur CSS et n’est pas magique : vous devrez tout de même travailler pour avoir un style graphique convenable. Mais la où il innove, c’est par l’ajout de quelques fonctionnalités bien pratiques, et on se demande comment nous avons pu nous en passer jusque la.

Do Less

Pour démarrer, un fichier css peut être un fichier less : vous le renommez en .less et le tour est joué. Ensuite, pour utiliser ce fichier, plusieurs choix s’offrent à vous. Vous pouvez inclure less.js dans votre page web et le laisser transformer vos fichiers less en css.

<script src="less.js" type="text/javascript"></script>
<link rel="stylesheet/less" type="text/css" href="styles.less">

Ou vous pouvez compiler directement vos fichiers less en css, selon le type de votre application :
– Avec des compilateurs existants comme less.app
– Avec le module less de nodejs
– Si vous faites du Play!, vous pouvez utiliser le module prévu. A noter qu’en Play!2, le support de less est natif, la compilation se fait de façon transparente pour vous. Bref, Less commence à être connu et intégré un peu partout. Le magnifique Twitter Bootstrap par exemple, un super bootstrap css qui vous permet de faire un style sympa même sans rien comprendre à l’art obscur des css, est fait avec Less. Mais bon, Less, ça fait quoi ?

Variables

Que tout ceux qui n’ont jamais pesté pour changer la couleur d’un thème lève la main! Bon, je ne peux pas voir, mais je suis sûr que vous n’êtes pas nombreux. Tout ça à cause de l’absence de variable en CSS. Voyons un peux comment Less remédie à ce problème, et à bien d’autres… Les variables sont nos amies : c’est la première chose que l’on apprend en programmation. On se retrouve un peu démuni en CSS, avec l’obligation de copier/coller n fois la même couleur ou la taille de police, et la galère qui suit pour un changement. Avec Less, c’est fini!Si vous voulez créer un thème, après avoir repéré le code couleur qui vous faisait rêver sur ColourLovers, vous pouvez définir vos premières variables :

@body_color: #262626;
@font_color: #EAF2D9;

On peut également définir d’autres variables, telles que la taille de la police :

@font_size: 20px;

Là où ça devient intéressant, c’est que l’on peut également faire des opérations (pas n’importe quoi hein, juste des opérations mathématiques de base) :

@big_font_size: font_size + 2px;

Fonctions

Si l’on a des variables et des opérations, vous vous doutez que l’on a aussi … des fonctions ! Baptisées “mixins” elles permettent de créer des styles avec des paramètres. Exemple :  les petits bords arrondis sympas que l’on veut mettre sur tous les boutons mais qui sont définis avec des styles spécifiques à chaque navigateur, et que l’on doit répéter à chaque taille d’arrondis que l’on veut.
Less nous permet de créer une fonction border-radius avec un seul paramètre nommé radius

.border-radius(@radius){
 border-radius: @radius;
 -webkit-border-radius: @radius;
 -moz-border-radius: @radius;
}

Cette fonction peut ensuite être appelée dans votre style :

.border-radius(10px);

Et ca devient franchement cool, quand on voit que d’autres ont pris le temps de faire des fonctions à notre place, et que l’on peut utiliser ces fichiers dans nos styles, lesselements ou encore dans le Bootstrap Twitter (oui, je suis fan).

Vous n’aurez plus jamais besoin d’écrire un préfixe navigateur (voir l’excellent screencast de nettuts), et ça, ça n’a pas de prix!

Less inclue lui aussi nativement un certain nombre de fonctions portant sur le traitement des couleurs (saturate, lighten, etc http://lesscss.org/#-color-functions). Par exemple :

fade(@color, 50%);

renvoie une couleur 50% plus transparente. Cool, huh ?

Nesting

Maintenant que nous avons vu les briques de base, on peut se pencher un peu plus sur l’apparence d’un fichier .less. On a l’habitude en css de répéter pour chaque régle toute les classes concernées, ce qui devient vite très verbeux :

.share {
 ...
}
.share .name {
 ...
}
.share .tag {
 ...
}
.share .tag .price {
 ...
}

En less, on peut faire quelque chose de plus simple et plus logique :

.share {
  ...
  .name {
    ...
  }
  .tag {
    ...
    .price {
      ...
    }
  }
}

Ce nesting peut s’appliquer aussi bien aux classes, aux ids et aux éléments.
Le nesting a de plus l’avantage d’inciter a regrouper les règles, ce qui peut vite tourner à l’anarchie dans un fichier css classique (qui n’a jamais ajouté sa règle tout en bas du fichier pour aller vite …).

Import

Toujours dans l’idée d’avoir un style plus clair, il est possible de découper ses fichiers less en fichier plus petits et de faire des inclusions là où ils sont nécessaires. Ainsi, vous pouvez avoir un fichier de variables, avec les propriétés générales de l’application, couleurs, font etc… et un fichier de fonctions utilitaires que vous incluez ensuite dans vos fichiers de style.

@import "variables.less";
@import "utils.less";

Magique non ? Moi je ne peux plus m’en passer !

Il existe bien sûr des alternatives à Less telles que Sass issu du monde Ruby (excellent screencast pour le découvrir) ou Stylus, Cet article met d’ailleurs en avant les différences entre Sass et Less.

Le prochain article reprendra la mini appli nodejs des articles précédents et ajoutera un peu de style en less ! Stay tuned !

Getting Started with Hadoop : Part 2

Disclaimer : Ce billet est la deuxième partie d’un article écrit pour la revue Programmez  (n°144) et traite de la technologie Hadoop. Si vous avez manqué la première partie, la voici. J’en profite également pour citer un article de businessinsider qui vous donnera peut être envie découvrir cette techno :  les startups qui emploient les ex-Yahoo, ex-Facebook et ex-Google. Et l’article est parfaitement dans l’actualité avec la release de la version 1.0.0 !

Exemple
Prenons un exemple pratique : vous voulez trier une pile de pizzas, chaque pizza ayant un parfum (4 fromages, margarita…) et une forme (ronde, carrée, triangle..). Pour cela vous avez à votre disposition 3 serveurs (3 noeuds dans votre cluster). Quelles vont être les phases map et reduce ?
La phase map va consister à répartir les pizzas selon leur forme. Chaque serveur va recevoir une pile de pizzas à traiter et pour chaque pizza va écrire un couple (clé, valeur) de sortie composé de la forme de la pizza et de la pizza.
(ronde, pizza1), (ronde, pizza2), (carrée, pizza3) …

Une fois toutes les pizzas traitées par les serveurs, on se retrouve avec une liste de couple (clé, valeur) avec les clés représentant les formes de pizza. Hadoop va alors redistribuer cet ensemble de données sur nos 3 serveurs en envoyant les pizzas carrées sur le premier, les rondes sur le second etc… Éventuellement, si les pizzas carrées sont trop nombreuses pour être traitées sur un seul serveur, elles seront envoyées en partie sur le serveur un et en partie sur le serveur deux.

Chaque reducer va alors donner un couple (clé, valeur) en sortie indiquant le nombre de chaque saveur pour les clés qu’il a reçues. On crée ici une nouvelle clé composée de la forme et de la saveur.
(carrée_4fromages, 234), (ronde_margarita, 128), (triangle_margarita,6) …

Cet exemple est un cas d’école, et même si vous allez rarement trier des pizzas, vous pouvez chaîner plusieurs mappers et/ou reducers pour arriver à vos fins sur des opérations plus compliquées.

Parmi les exemples notables d’utilisation, nous avons bien sûr Twitter, Google ou Facebook qui s’en servent massivement pour toutes les opérations d’indexation, de traitement de leurs logs serveur (avec plusieurs teraoctets traités chaque jour) ou encore les prédictions de tendances. Mais on retrouve aussi Hadoop chez des opérateurs de téléphonie mobile (test de nouveaux forfaits sur de vastes volumes de données), ou dans des banques pour des calculs de prime, ou pour des calculs de facturation complexes mais ponctuels. Ou encore dans l’industrie pour les suivis RFID qui peuvent générer des quantités incroyables de données.

Un dernier exemple intéressant est celui du New York Times. Afin de générer plusieurs teraoctets de PDFs à partir de leurs archives et de les ouvrir au public, leur équipe a implémenté un programme map/reduce pour réaliser efficacement cette tâche. Et plutôt que d’acheter de nouvelles machines qui ne leur serviraient plus par la suite, elle s’est appuyée sur des instances Amazon : 100 instances, pendant 24h pour un coût en infrastructure dérisoire de 240$. Résultat : 1.5 To de PDF générés dans la journée, avec le résultat hébergé dans le stockage S3 (Simple Stockage Service, service de stockage dans le cloud de la société Amazon) et prêt à être utilisé.

HDFS
Hadoop n’est pas seulement le framework qui vous permet d’écrire des programmes distribués en vous simplifiant la tâche, il met aussi a disposition un système de fichier pensé pour ce type de traitement. Dans un cluster Hadoop, les données sont réparties entre les différents noeuds du cluster. Chaque bloc de données est même répliqué sur plusieurs noeuds pour éviter toute perte (la valeur par défaut de cette redondance est de 3, la donnée se trouvera donc sur 3 noeuds distincts de votre cluster).

Pour répartir ces données de façon performante, un système de fichier distribué a été créé : Hadoop Distributed File System (HDFS) inspiré là aussi de Google et de son Google File System. Ce système de fichier est écrit en Java et vous assure un système de fichier portable. Même si les données sont réparties, elles sont accessibles par n’importe quel noeud lors du traitement (et sont alors transférées si nécessaires depuis leur noeud de stockage vers le noeud affecté au traitement). Ce système de fichier est également capable de monitorer les noeuds, de répliquer et de répartir les données en cas de perte de serveur. Chaque noeud de votre cluster est, en régle générale, également un noeud de stockage.

Lorsque l’on veut traiter un ensemble de données (par exemple un fichier XML de plusieurs centaines de Mo), on va d’abord monter ces données sur le système de fichier HDFS. Pour cela Hadoop fournit un ensemble de commandes très proches de celles que l’on trouve dans l’univers Unix : ls pour lister, put pour ajouter, rm pour supprimer, cat pour lire… Une fois les données montées, on peut démarrer le traitement ; HDFS va alors diviser chaque fichier d’entrée en bloc de données (par défaut de 64Mb) et l’envoyer à un noeud pour calcul, en privilégiant bien sûr les blocs présents physiquement sur le serveur. L’idée est plutôt de déplacer les traitements vers les données que l’inverse, ce qui est beaucoup moins coûteux en performance et en bande passante.

Ecosystème
Hadoop a aussi un très riche écosystème d’outils qui répondent à des besoins différents.

  • Apache Pig est un langage de requête pour analyser un vaste ensemble de données, né chez Yahoo. C’est une abstraction comme peut l’être SQL pour écrire des requêtes qui sont alors traduites en job Map/Reduce et exécutées de façon distribuée sur le cluster. Cela peut simplifier considérablement l’écriture d’une requête !
  • Apache Hive : un data warehouse libre implémentant un langage de requête orienté SQL (HiveSQL) dont la mise en œuvre se traduit par l’exécution de jobs Map/Reduce orchestrés par Hadoop.
  • Sqoop va, lui, vous permettre d’importer vos données stockées dans une base SQL dans HDFS. Le nom vient d’ailleurs de la contraction SQL-to-Hadoop. Il peut également importer les données dans Hive.
  • Flume permet également de collecter des données, mais plutôt des logs.
  • Apache HBase est une base de données orientée colonne s’inscrivant dans la mouvance NoSQL dont le design s’inspire de BigTable (Google). Elle supporte jusqu’à plusieurs millions de lignes et fonctionne au dessus de HDFS.
  • Oozie est un moteur de workflow pour orchestrer vos programme Map/Reduce ou vos scripts Pig.
  • Hue (Hadoop User Experience) est une interface graphique web qui permet d’administrer Hadoop, de parcourir votre répertoire HDFS, de voir les programmes en cours d’exécution etc…


Bref, beaucoup d’utilitaires sont là pour vous aider !

Comment démarrer simplement ?
Une société s’est spécialisée dans le support d’Hadoop auprès des entreprises : il s’agit de la société Cloudera, qui compte dans ses rangs nombre de commiters du projet, dont Doug Cutting. Cloudera fournit un ensemble de ressources très utiles pour aller plus loin, des vidéos mais aussi une machine virtuelle Ubuntu avec tous les outils précités d’ores et déjà installés et configurés. C’est donc un moyen simple de tester ce que peut vous offrir Hadoop. Le framework est d’ailleurs fourni avec quelques exemples de programmes sous forme de jar, que vous pouvez lancer dans la VM. Le navigateur installé vous permettra de monitorer l’avancement de votre programme lors de son exécution.

Hadoop est donc un outil à connaître et qui vous sera peut être utile dès demain. Il ouvre des perspectives intéressantes sur la façon de traiter vos données et n’est pas seulement réservé aux ‘big players’ du web. Si votre application produit trop de données pour que les outils classiques puissent les traiter, ou que ceux-ci les traitent trop lentement, ou de façon trop coûteuse, pensez Hadoop ! Son implémentation du pattern Map/Reduce vous permettra de découvrir en douceur les joies de la scalabilité, et son formidable éco-système, à peine abordé ici, vous ouvrira un univers sans limite. Et quand on voit le nombre de startups qui se lancent sur cette techno, on se dit que Hadoop, c’est définitivement hype!

Getting Started with Hadoop : Part 1

Disclaimer : Ce billet est la première partie d’un article écrit pour la revue Programmez qui est en kiosque ce mois de Septembre  (n°144) et traite de la technologie Hadoop (une petite pause au milieu de la série consacrée à Node.js).

Avez vous déjà essayé d’indexer le web ? Non ? Et bien Google l’a fait, et le fait tous les jours. En quasi temps réel. Grande nouvelle me direz vous, on le sait depuis longtemps ! Mais ne vous êtes vous jamais demandé comment ? Avoir les plus grandes fermes de serveurs et embaucher les cerveaux les plus brillants ne suffit pas : il s’agit aussi de faire ça intelligemment ! Comment effectuer des traitements sur un ensemble de données de cette taille? La firme de Mountain View a partagé quelques uns de ses secrets en Décembre 2004 dans un whitepaper nommé “MapReduce: Simplified Data Processing on Large Clusters”. Un nom un peu barbare pour dévoiler les principes d’un algorithme simple, MapReduce, pour traiter des données sur des clusters de machines, mais sans en révéler les détails d’implémentation.

Qu’à cela ne tienne, quelques passionnés, Doug Cutting (créateur du projet Apache Lucene, un moteur d’indexation de documents) en tête, se mettent à réaliser une implémentation open source de MapReduce : Apache Hadoop était né ! L’objectif est alors pour Doug d’accélérer un autre de ses projets open source, le projet Apache Nutch, un moteur d’indexation web. Après quelques temps, une version de Nutch basée sur ce qui deviendra Hadoop, est rendue disponible. Et elle se révèle bien plus rapide et simple que la précédente. Yahoo pressent l’intérêt de la chose et va alors employer Doug. Ce dernier et une équipe travaille à plein temps sur le projet Hadoop (nommé d’ailleurs avec le surnom du jouet du fils de Doug, un éléphant qui est aussi devenu le logo). Aujourd’hui la détection de spam et l’indexation des sites web chez Yahoo se basent sur Apache Hadoop, dont la première release date de 2008.

Intérêt

Hadoop ne se destine pas à être utilisé en temps réel, c’est un outil qui vous permet d’effectuer vos traitements batchs. Il se base sur l’algorithme MapReduce afin d’effectuer le traitement de vastes volumes de données sur un serveur ou, et c’est toute sa puissance, sur un cluster de serveurs. Ce n’est pas une solution de stockage de données, et Hadoop ne s’inscrit donc pas dans la mouvance NoSQL, même si on les retrouve souvent associés en pratique (car pour traiter de grandes quantités de données, il faut déjà les stocker et c’est là que NoSQL a tout son sens). Ceci étant dit, quel intérêt pour vous et moi qui ne sommes ni Google, ni Twitter et qui ne possédons pas une ferme de serveurs ? Tout d’abord avec le prix de l’espace de stockage qui diminue, on serait bien tenté de stocker de plus en plus d’informations dans nos applications (de la donnée texte à la photo ou vidéo), et, pour les traiter, d’utiliser quelques serveurs au lieu d’un. Voire même d’utiliser la puissance du Cloud pour le faire grâce à son prix dérisoire, Amazon par exemple permettant de louer un serveur pendant une heure pour 0.085$. Ou peut être pour gagner en vitesse de traitement : au lieu d’acheter un magnifique serveur octocore, peut être que vos deux vieux serveurs qui prennent la poussière viennent de retrouver un intérêt…

Principe

Mais sur quoi repose ce modèle de traitement des données ? Tout s’articule sur le découpage de vos programmes en deux parties distinctes dont les exécutions vont être successives : la phase ‘map’ et la phase ‘reduce’. Le mapper est là pour filtrer et transformer les entrées en une sortie que le reducer pourra agréger une fois la première phase terminée, aboutissant alors au résultat souhaité, que ce soit un simple calcul statistique ou un traitement métier plus complexe. Ces deux phases ne sont pas issues de l’imaginaire des développeurs, mais bien des retours terrains constatés par les Googlers qui travaillaient sur ces problématiques.

Chaque phase est en fait une simple méthode, écrite en Java ou éventuellement dans votre langage préféré (Python, Ruby…), de traitement de données à implémenter. Lors de la première phase, MapReduce reçoit les données et donne chaque élément à traiter à chaque mapper (sur chaque noeud de votre cluster, soit de 1 à n machines). A l’issue de cette phase les données traitées sont redistribuées à chaque reducer (idem, chaque noeud de votre cluster, de 1 à n machines) pour arriver au résultat final.

Même si parfois découper votre traitement en deux phases vous semblera non trivial, une fois cette étape réalisée, passer l’exécution de votre programme sur un cluster de n machines ne sera pas plus compliqué qu’un changement de fichier de configuration. Quand vous écrivez votre programme en suivant le modèle MapReduce, Hadoop se charge ensuite pour vous de passer à l’échelle supérieure.

Si nous n’utilisions pas un framework comme Hadoop, nous devrions aussi écrire une fonction de partitionnement pour répartir les données entre les différents noeuds, une autre méthode pour les redistribuer entre les deux phases, gérer le load-balancing, les possibles échecs de traitement, les inévitables pannes matérielles serveur, etc… Beaucoup de travail pas forcément passionnant !  Mais Hadoop se charge là aussi des tâches ingrates et les optimise probablement mieux que ce que nous aurions pu faire. En résumé, écrire un programme Hadoop est donc aussi simple qu’écrire une méthode Map et une méthode Reduce, et à vous la scalabilté !

Dans un programme MapReduce, aucune valeur n’est traitée sans une clé associée. Les fonctions map et reduce ne reçoivent pas de simples données mais des paires (clé, valeur). Même chose pour les données sortantes des fonctions. Le mapper peut produire 0, 1 ou n couples (clé, valeur) pour un couple (clé, valeur) entrant. Le reducer, lui, va réduire une liste de couples (clé, valeur) produite par les mappers en une seule valeur par clé.

To be continued : si vous êtes impatient, foncez au bureau de presse le plus proche. Sinon je mettrai en ligne la suite dans quelques temps. Ce numéro de Programmez contient également un article de @AgnesCrepet, mon amie JDuchess, sur le BDD (si vous ne savez pas ce que c’est vous avez deux bonnes raisons d’acheter ce numéro). Et c’est un très bon article, écrit avec Mauro Talevi, commiter JBehave, je ne le dis pas juste parce que c’est une amie! 

Node, Express et Jade

Après un article de présentation et un premier “Hello world”, passons à la suite. Nous avons créé un serveur http basique. Pour créer une véritable application web, il reste encore du travail, à minima créer des pages qui seront renvoyées par le serveur. D’où notre travail du jour :
– créer les vues de l’application,
– créer le routage des requêtes afin de renvoyer la bonne vue.
L’idée est de créer un affichage du cours des actions d’une bourse virtuelle. Pour cela, on ne va pas tout faire nous même. En avant !

Quand je vous disais que Node.js fourmillait de modules, je ne mentais pas. Différentes solutions de moteur de template  s’offrent à vous, ou mieux des frameworks web (qui s’appuient donc sur des moteurs de templating, mais aussi des modules CSS, de routage etc…).

Express  est probablement le framework le plus connu et utilisé. Développé par le talentueux TJ Holowaychuk, Express s’appuie sur Connect  (un framework de serveur http qui regroupe un ensemble de middleware, inspiré de Rack). Le toujours très bon site howtonode en donne une explication intéressante.

Il utilise par défaut le moteur de template Jade  mais d’autres sont également disponibles.
Bien d’autres solutions de frameworks web existent et vous allez trouver des fans de chacune. Si vous avez un module préféré, n’hésitez pas à le signaler en commentaire.

Suivons donc la hype, et découvrons Express et Jade!

Installation express

Comme souvent on trouve moult ressources  pour bien installer Express. Si vous ne l’avez pas déjà fait, je vous conseille d’installer npm (Node Packet Manager), utilitaire très pratique qui se charge de récupérer pour vous les modules que vous voulez et de les installer (vous avez dit Maven ?). L’installation d’Express par NPM se fait alors en une ligne de commande. Une fois Express installé, créez un nouveau projet ‘shares’ avec la commande

express shares

Si vous explorez le dossier créé (ou directement sur Github ), vous trouvez une architecture typique projet web a la Rails/Grails/Play! :
– un fichier package.json équivalent à un pom.xml
– un dossier views pour les vues de l’application
– un dossier public qui contient les différentes ressources (images, styles, js)
– un fichier principal app.js

Ce dernier nous intéresse plus particulièrement, on y trouve deux parties intéressantes :
– la partie Configuration avec déjà quelques modules déclarés
– la partie Routes, qui permettra de définir quelle vue sera renvoyée pour une route donnée.
Le serveur est lancé sur le port 3000, donc si vous avez bien suivi un

node app.js

suivi d’un saut dans le navigateur vous amène à une belle page d’accueil.

Non ? Alors il vous manque peut être quelques modules : comme on le ferait pour un build Maven il faut récupérer les dépendances du projet avant de pouvoir travailler.

npm install -d

s’en charge pour vous. On relance le serveur et voilà !

Ma première route

Nous allons modifier la route existante pour la remplacer par une a nous

app.get('/', function(req, res){
 res.render('shares', {title : 'Shares', shares : shares});
});

Ainsi une requête sur l’url de notre serveur renverra la vue shares à laquelle nous passons un ensemble de variables (qui seront utilisées pour générer la vue d’après le template comme nous allons le voir incessamment).
Ces variables sont donc le titre de la page et un objet qui représente un tableau d’actions, que nous devons donc définir.

var shares = [{name:"Google",price:120}, {name:"Apple",price:132}, {name:"Microsoft",price:92}]

Chaque action est un objet simple composé d’un nom et d’un prix.

Les routes peuvent également récupérer des paramètres de l’url : si on ajoute une route comme la suivante

app.get('/:name', function(req, res){
 res.render('shares', {title : req.params.name,
    shares : shares.filter(function(share){return share.name.toLowerCase() == req.params.name.toLowerCase()})});
});

alors accéder à la page ‘/google’ donnera une page dont le titre est ‘google’ et la seule action listée celle de … Google.
Vous pouvez voir le code modifié ici.

Passons maintenant à l’écriture de ce template !

Un moteur de template qui envoie

Quel que ce soit votre langage/framework préféré, si vous faites du web, il faut bien écrire les pages html. Et il faut reconnaître que c’est rarement la partie la plus excitante, il faut penser à bien fermer ses balises, à choisir des ids et des classes pertinents, tout en se préparant à la grande bataille du CSS qui s’annonce. Boring…

Les rubyistes ont souvent de bonnes idées et on en trouve dans Rails notamment par poignée (quand on est un profane et curieux comme moi, la série de screencast Railscast est une bonne ressource pour découvrir et se tenir informé). L’une de ses bonnes idées se nomme Haml et sa devise donne le ton : « markup haiku ». Haml vise à remplacer les gros templates hideux par quelque chose de plus léger (poétique serait quand même un peu exagéré…). Mais nous ne sommes pas là pour parler Ruby. En revanche Haml a un successeur spirituel dans le monde Javascript et il s’agit de Jade (écrit par le même développeur qu’Express, qui est décidément un garçon très occupé). Le plus simple pour comprendre est de voir ça en action.

Vous avez devant vous votre IDE/éditeur de texte préféré, page blanche et vous entrez

html

Une fois compilé par Jade, ce tag se transforme en

<html></html>

Vous voulez ajouter une div avec un id

div#price 12 euros

va donner

<div id=”prices”>12 euros<div>

ou encore plus simplement

#price 12 euros

car le tag par défaut est une div.

On peut également ajouter une classe

div.prices

ou

.prices

donnera

<div class=”.prices”></div>

Besoin d’ajouter un attribut ?

a(href=’/prices’) Prices

donne

<a href=’/prices’>Prices</a>

Oh et j’oubliais, la déclaration de doctype s’écrit avec un ‘triple bang’ (!!!)

Nice ? Un peu de dynamique maintenant. Si nous avons un article avec un prix, et que l’on passe cet objet au template suivant :

#price #{item.price} euros

nous obtenons

<div id=”price”>12 euros</div>

Ces deux screencasts vous emmèneront un peu plus loin dans la découverte si vous le désirez.
Vous avez maintenant installé Express et eu un aperçu de Jade. Il est temps de faire notre premier template Jade pour Express.

Si vous ouvrez le fichier layout.jade présent dans le répertoire view vous trouvez :

!!!
html
 head
   title= title
   link(rel='stylesheet', href='/stylesheets/style.css')
 body!= body

On retrouve la déclaration de la doctype (triple bang), les balises html, head et body bien connues. On voit également comment s’effectue le chargement d’un style, et l’utilisation de la variable title passée en paramètre du template. A l’instar de Ruby, l’indentation est significative : un bloc indenté est un sous bloc du bloc précédent.
Ce layout est utilisé a chaque appel, et body sera remplacé par le template appelé (le template shares dans notre exemple).

Le template index.jade contient la page d’accueil. Elle ne nous sera plus nécessaire nous pouvons la supprimer. En revanche il nous faut créer la vue shares. Pour cela on peut créer un fichier shares.jade ou un dossier shares contenant un fichier index.jade. Cette deuxième méthode est retenue car nous allons utiliser plusieurs fichiers pour cette vue et ils seront regroupés dans ce dossier par soucis de lisibilité.

Voici a quoi va ressembler votre fichier index.jade

h1 Share's price
.shares
 != partial('share', shares)

La balise h1 contiendra le texte “Share’s price” puis une div avec la classe shares contiendra une “vue partielle”. Cette déclaration permet de façon simple de dire au template que pour chaque action de la collection ‘shares’ passée en paramètre, il faudra effectuer un rendu particulier. Ce sous template est créé dans un template annexe nommé ‘share.jade’ :

.share
 .name #{share.name}
 .tag
   .price(id=share.name) #{share.price}$

Ce template va être appelé pour chaque action, et pour celle-ci va créer une div de classe ‘share’ contenant une div ‘name’ avec le nom de l’action et une div ‘tag’ pour le prix. Cette dernière div contient une div ‘price’ dont l’identifiant est dynamique (pour les besoins du prochain billet) et le prix en $.

Si on relance le serveur vous devez avoir à l’écran la liste des actions !

Et pour tester la deuxième route, si l’on accède à la page ‘/google’, nous obtenons :

Vous pouvez récupérer les sources de cet article sur Github

git clone git@github.com:cexbrayat/shares.git

Pour lancer l’application

npm install -d
node app.js

Jade commence à se répandre, on trouve ainsi Scalate qui s’appuie dessus et est disponible comme moteur de template pour vos projets java (on trouve aussi un module Play!). C’est un outil très intéressant et pratique, à suivre et surveiller!

 

La prochaine fois on découvrira plus en avant Express et on parlera CSS !

Getting started with Node.js : Part 2

Après un premier article d’introduction et avant de passer à un premier Hello world (passage obligatoire avant des choses plus intéressantes), nous allons revenir sur le fonctionnement de Node.

Everything runs in parallel, except your code !

Node.js est “single threaded”, il ne garde donc qu’un seul thread pour votre code ! C’est à dire que faire un “sleep” va bloquer votre serveur et, pendant ce temps là, il ne servira de nouvelles requêtes. Pour des actions très consommatrices de CPU, il peut donc y avoir des blocages (ce n’est pas magique non plus!).

Mais, toutes les actions IO sont lancées de manière asynchrone. Donc si l’une de vos actions (par exemple une lecture en base) est bloquante ou prend beaucoup de temps (les actions IO prennent généralement beaucoup de temps par rapport à votre code), alors votre serveur est toujours capable de servir d’autres requêtes. Get it ?

Call me back

La programmation asynchrone avec événement est intimement liée à la notion de callback et est souvent utilisée en Javascript. On retrouve aussi ce principe dans GWT (normal puisque votre Java se retrouvera au final en … Javascript).

En utilisant des callbacks, vous avez la garantie que votre code n’est pas interrompu et que ce callback soit exécuté une fois l’action terminée. Il n’est pas si simple de travailler de cette façon, pas forcément naturelle dans la plupart des langages.

Il est temps maintenant de faire un premier serveur. Tout d’abord vous devez installer Node.js. Comme la procédure varie selon votre OS, je vous renvoie vers l’excellent site howtonode, qui contient un ensemble de ressource pour Node.js dont une très bonne procédure d’installation.

Maintenant, commençons à coder une première application web. Pour cela nous allons avoir besoin :
– d’un serveur HTTP pour servir les pages web,
– d’un routeur pour répondre aux différentes requêtes selon l’URL,
– de différents handlers de requêtes,
– écrire également les différentes pages html pour les handlers afin de renvoyer le contenu au navigateur.

Si vous prenez votre langage favori, certaines de ces tâches ne sont pas nécessaires (votre Tomcat ou Apache HTTP s’en occupe pour vous). Avec Node.js les choses sont un peu différentes, il nous faut tout écrire, notamment le serveur HTTP… Mais vous allez voir, c’est simple et rapide ! Et pour cette première introduction, nous allons nous contenter du serveur.

Mon premier serveur HTTP

Créez un fichier server.js et collez le code suivant :

var http = require("http");
http.createServer(function(request, response) {
  response.writeHead(200, {"Content-Type": "text/plain"});
  response.write("Node is hype!");
  response.end();
}).listen(9000);

Et voila votre premier serveur ! Le code est assez explicite : il crée un serveur en local sur le port 9000 qui renvoie une page contenant “Node is hype”. Pour tester, lancer la commande “node server.js” et ouvrez votre navigateur (si vous avez suivi, vous connaissez l’URL).

Le module http est utilisé dans le code. Vous en utiliserez beaucoup dans vos développements, c’est l’une des forces de Node.js : beaucoup de modules existent et font probablement déjà ce que vous voulez faire.

L’autre point intéressant est l’argument passé en paramètre de la fonction createServer(). C’est une fonction ! Pour les habitués de Javascript (ou des langages fonctionnels) rien d’étonnant. Pour les purs Javaistes cela peut surprendre… La fonction passée est une fonction anonyme, elle n’est pas nommée dans le code. On pourrait écrire le même code différemment :

function requestHandler(request, response) {
  response.writeHead(200, {"Content-Type": "text/plain"});
  response.write("Node is hype!");
  response.end();
}
http.createServer(requestHandler).listen(8888);

En fait cette fonction est notre handler de requête et votre premier callback. En effet à l’arrivée de chaque requête, c’est cette fonction qui sera appelée (c’est la partie event-driven/callback de Node.js). Vous voyez donc peut-être comment résoudre le problème des fonctions qui prennent beaucoup de temps et risquent de bloquer votre serveur au début : il suffit d’en faire des callbacks pour que Node.js continue à servir les autres requêtes.

Organiser son code

Vous vous interrogez peut être sur l’organisation du code. Généralement les tutoriaux vous permette de garder toute la logique dans un seul fichier source. Pour une vraie application, même légère, on se retrouve rapidement à vouloir séparer le code. Cela peut se faire assez simplement avec des modules, que vous pouvez utiliser dans votre code. Vous avez vu le module “http”, il est temps de faire votre propre module “server” qui démarrera le … serveur.
Pour cela il suffit de “wrapper” le code existant dans une fonction et d’exporter cette fonction.

var http = require("http");
function start(){
  http.createServer(function(request, response) {
    response.writeHead(200, {"Content-Type": "text/plain"});
    response.write("Node is hype!");
    response.end();
  }).listen(9000);
}
exports.start = start;

Vous pouvez alors faire un autre fichier main.js ou vous utilisez ce module.

var server = require("./server");
server.start();

Simple n’est-ce pas ?
Maintenant que nous savons faire un module et un serveur de base, nous allons pouvoir nous attaquer le plat de résistance. Stay tuned!

Getting started with Node.js : Part 1

Vous en avez peut être entendu parler, l’un des outils hype du moment est node.js. On le voit partout sur les timelines Twitter et de façon plus surprenante, souvent relayé par des javaistes. Node.js est la pour vous aider à coder côté serveur des applications scalables et qui tiennent la charge comme jamais : c’est le fameux C10K problem. C’est un sujet vraiment passionnant, et on trouve quantité de ressources dessus.

Fact 1 : node.js est un outil pour créer des serveur javascript.

Du Javascript côté serveur! Pourquoi un tel engouement me direz vous ? Le Javascript, on connaît à peu près, on en fait souvent côté client avec des librairies géniales… Mais de là à en faire aussi sur le serveur ! C’est lent en plus le Javascript non ?
Niveau lenteur, vous pouvez être rassuré : node.js se base sur l’excellent moteur javascript Google V8, l’implémentation utilisée dans Google Chrome. Donc disons que cela va assez vite (et vous trouverez des pseudos benchmarks qui penchent dans l’une ou l’autre direction). On est finalement pas si loin de Java : Lars Bak, un des contributeurs de V8, a travaillé sur la JVM et Hotspot (et l’un de ses brevets était d’ailleurs dans la contestation d’origine de Oracle vs. Google).

Fact 2 : node.js est un outil pour créer des serveurs asynchrones et non bloquants

Javascript admettons, mais quelle avantage par rapport à mon serveur Apache préféré ?
L’approche historique et basique des serveurs web était de forker un process pour une requête entrante. Lorsque vous avez plusieurs milliers de connexions on se retrouve vite à plusieurs milliers de process. Qui demandent chacun du temps pour le fork (fork latency), de la mémoire pendant leur exécution, des changements de contexte, un scheduler qui doit dire qui peut faire quoi (même si depuis linux 2.6, le scheduler est en O(1)), et bien sûr de les nettoyer une fois fermés.
Apache Httpd utilise ce système de ‘one process per connection’ avec évidemment des subtilités (pre-fork des process, chaque process gère plusieurs requêtes), mais, de façon schématique, on retrouve donc ces problèmes pour un nombre important de connexions.

L’une des solutions plus efficaces était d’utiliser des threads à la place des process, ou en complément (pour en revenir à Apache Htppd, c’est la qu’intervient le fameux mod worker). Mais c’est encore lent sur certains OS. D’où l’utilisation de thread pools : les threads sont créés en bloc au démarrage puis chaque thread est affecté à une connexion. Les problèmes commencent quand vous avez plus de connexions que de threads disponibles : la requête est alors en attente. Pas encore le top niveau scalabilité…

A la différence de notre Apache Httpd, Node.js ne se base pas sur des threads : c’est un serveur asynchrone qui utilise un process monothread et des I/O non bloquants. L’asynchronisme permet au thread d’exécuter des callbacks lorsqu’il est notifié d’une connexion. Contrairement au modèle évoqué ci-dessus, node.js ne réserve pas un thread à chaque connexion, ce qui va lui permettre de tenir de bien plus fortes charges sans problème de mémoire.

Les I/O regroupent les accès disques, accès base de données, accès réseaux, bref tout ce qui prend du temps sur un ordinateur moderne (latence, débit limité etc…). Ici tous les I/O sont non bloquants, c’est à dire que tout appel est effectué en asynchrone, avec un callback qui sera exécuté une fois l’accès réalisé. Et tous les modules pour node.js doivent utiliser ce principe. Heureusement, même si node.js est relativement jeune, on trouve déjà près de 2000 modules disponibles (basés sur common.js et simples à developper)!

Cela permet alors de servir plusieurs centaines de requêtes par seconde sans problème.

D’autres serveurs proposent ce principe et certains depuis des années :
nginx (prononcé EngineX) par exemple. Avec des performances intéressantes. Lighttpd lui est souvent comparé (merci à @jponge).
Twisted aussi pour les fans de Python.
EventMachine pour les rubyistes.
– En Java, on se tourne vers JBoss Netty, Apache Mina ou Deft (ou Loft, un portage de deft en Scala, merci à @samklr). NIO2 se profilant à l’horizon, les serveurs Java n’auront peut être plus grand chose à envier à node.js. Même JavaEE, avec la spécification Servlet 3.0 et le support de l’asynchronisme suit ce chemin.

Fact 3 : node.js est multi OS

La plupart de ces serveurs se basent, comme node.js, sur l’instruction Unix select (ou des équivalents améliorés comme epoll voire des non POSIX comme kqueue) pour être notifiés d’une nouvelle connexion avant de se rendormir. Et quid de Windows ? C’était justement la nouvelle de ces derniers jours : Microsoft va supporter la société Joyent, où travaille le créateur de node.js, Ryan Dahl, pour un meilleur support de leurs OS.

Voilà comment faire un premier article sur node.js sans en montrer une seule ligne !
Il est probable que vous n’ayez que rarement à traiter 10000 users en parallèle : mais si c’est le cas node.js est un outil intéressant à connaître. Au delà de node.js en particulier, il devient illusoire de pratiquer le métier de développeur web sans connaître un minimum de Javascript. Node.js m’a donné envie de m’y remettre et c’est déjà ça !

Si vous voulez voir comment faire des websockets facilement avec node.js et continuer la découverte de cet univers foisonnant, stay tuned !