Le Web 2.0 et l'explosion des clients mobiles ont changé la manière de concevoir l'architecture de nos applications. Node.js a été l'une des premières technologies à essayer de répondre à ce défi par l'utilisation d'un environnement non bloquant et asynchrone. L'année dernière, vert.x, une technologie similaire, mais réalisée sur la machine virtuelle Java, a débarqué. Contrairement à Node.js, vert.x suit une approche réellement polyglotte et autorise les développeurs à créer leurs systèmes avec JavaScript, Groovy, Java et d'autres langages. Même mélangés au sein d'une application.
InfoQ a contacté Eberhard Wolff pour discuter des différences entre ces deux technologies, les nouveaux défis pour créer des architectures basées sur celles-ci et les avantages qu'elles fournissent à l'utilisation.
Eberhard était auparavant consultant principal pour SpringSource et est maintenant l'architecte et le directeur de la technologie chez adesso AG. Il analyse et conçoit des systèmes d'entreprise depuis des années et a passé les derniers mois à s'intéresser à vert.x.
InfoQ: Node.js a maintenant 4 ans, vert.x bientôt 2 et il devient évident qu'il y a un besoin pour ces technologies et leurs concepts. Quel est ton point de vue sur Node.js et vert.x ? Où est-il est intéressant d'utiliser ces technologies ? Pour quels cas d'utilisations sont-elles faites ?
Eberhard Wolff: Je pense qu'il y a une demande grandissante pour gérer un nombre important de clients dans des environnements de hautes performances. Un modèle asynchrone est très utile ici, il est simplement possible de gérer un nombre plus important de clients en utilisant moins de thread. Mais il y a plus avec vert.x. Sur la JVM, vous avez habituellement un seul langage de programmation dans une application. Java est toujours le langage dominant et préféré. Puis, il y a Scala avec ses propres framework ou par exemple les Clojure. Ceci est différent de ce qui se passe avec .NET. Depuis le tout début, .NET se voulait polyglotte, même au sein de la même application. vert.x permet à différent langage de coopérer plus facilement dans la JVM. Il y a aussi des wrappers qui rendent l'utilisation du framework plus naturelle dans chaque langage. Vous pouvez exécuter votre code JavaScript dans la JVM et, en transférant des objets JSON sur le bus d'événement de vert.x, vous pouvez l'intégrer avec différents langages tels que Java ou Scala. C'est une évolution intéressante, car il s'agit de la seule approche, à ma connaissance, qui est réellement polyglotte. Et il y un défi sur la JVM à propos de la modularité : comment rendre chaque module déployable individuellement ? Une possibilité serait d'utiliser OSGi. Cependant, ce n'est toujours pas utilisé de manière globale. Une autre solution serait de déployer de multiples fichiers WAR sur un serveur et les laisser communiquer en SOAP, mais il s'agit d'une solution complexe avec un coût important pour les performances. vert.x offre une solution élégante pour la modularisation. Donc vert.x est un framework très intéressant, car il est asynchrone, polyglotte et modulable.
InfoQ: En parlant de Node.js, je suis en train d'écrire une application qui sera exécutée dans le serveur Node.js. Il fonctionne dans un mode mono-thread pour traiter les requêtes et a la possibilité de transférer ces requêtes à un pool de threads si nécessaire. Cela signifie que je n'ai pas de modularité ou différents composants qui pourraient communiquer entre eux. Comment vert.x fonctionne dans ce cas là ?
Eberhard: Dans vert.x, un bus d'événement est utilisé par les modules pour s'envoyer des événements. Ces événements peuvent contenir par exemple des objets en JSON. Les modules dans vert.x ont des classloaders séparés, donc ils peuvent vraiment être vus comme des composants séparés. Vous pouvez donc mettre des fonctionnalités dans différents modules. Par exemple, il y a un module disponible sur GitHub pour interagir avec MongoDB. Il consomme des événements sur le bus d'événements et enregistre les données dans la base de données. Comparé à la programmation asynchrone, cela peut sembler être une fonctionnalité mineure, mais je crois que c'est vraiment important. Cela répond à des problèmes que vous rencontrez régulièrement dans des applications d'entreprise.
InfoQ: Peux-tu nous en dire un peu plus concernant le bus d'événements ? Est-ce que c'est une sorte de Java Messaging System avec des sujets et des files d'attente ?
Eberhard: Il fournit un système de publication/souscription et aussi une communication point à point. Il peut également être réparti sur plusieurs nœuds. Cependant, les événements sont transitoires. Ils ne sont pas stockés sur tout type de stockage stable. Par conséquent, les événements peuvent être perdus. Ceci est différent de JMS qui mettent l'accent sur la fiabilité alors que le bus d'événements vert.x met l'accent sur la performance.
InfoQ: À quel point les modules sont-ils indépendants les uns des autres ? Peut-on vraiment choisir un composant et le remplacer ou le mettre à jour en production ? Est-ce que les messages pour ce module sont mis en file d'attente en attendant qu'il soit de retour et fonctionnel ?
Eberhard: Les modules peuvent être remplacés ou mis à jour en production. Mais les événements ne sont pas enregistrés. Donc ils seront perdus aussi longtemps que le destinataire est indisponible.
InfoQ: À quoi ressemblent le paysage d'un système dans cet environnement ? Après tout, je ne peux pas dire que je veux être performant et scalable d'une part alors que de l'autre part j'intègre des systèmes qui n'intègrent pas ses concepts.
Eberhard: C'est un autre avantage de vert.x: vous pouvez définir des workers appelés worker verticles. Les workers verticles utilisent un pool de thread, donc vous pouvez intégrer du code legacy qui a besoin de faire des appels IO bloquants. Le pool de thread est séparé de la boucle d'événement principale. Donc la boucle d'événement ne sera pas bloquée par un worker verticle. Un worker peut faire n'importe quelle tache qu'il doit faire, synchrone, appels IO bloquants, etc. Cette fonctionnalité est actuellement très importante puisqu'il y a énormément de librairies dans le monde Java qui ne sont pas prévues pour être non bloquant.
InfoQ: Comment cela peut-il être évalué lorsque vous concevez un nouveau système ? J'ai lu une interview de Ryan Dahl, le créateur de Node.js, où il a déclaré que le choix de JavaScript était une bonne idée, car il y avait seulement quelques modules autour. Mais "seulement quelques modules" signifiait aussi qu'il ne peut pas y avoir beaucoup de mauvais modules (modules non conçus pour être utilisés de manière asynchrone). Je pense que si je choisis arbitrairement une bibliothèque Java, je risque très rapidement d'avoir des problèmes. Tu es d'accord avec ça ?
Eberhard: Exactement. Mais c'est ici que les worker verticles interviennent. Je comprends le choix qu'a fait Node.js. Simplement parce que les développeurs JavaScript ont l'habitude de travailler en mode asynchrone. Ils font de la programmation asynchrone depuis toujours grâce à l'AJAX. Il y a, ou il y a eu, des voix qui se sont élévés dans la communauté Java pour dire qu'ils "savent construire de grands systèmes, mais que les personnes en JavaScript ne font que des frontends simplistes." Mais avec AJAX, les gens en JavaScript ont toujours eu à gérer des callbacks et de l'asynchrone et c'est très naturel pour eux. C'est pour cela qu'il est normal de créer quelque chose comme Node.js en JavaScript maintenant que nous avons des environnements JavaScript performants. vert.x le démontre aussi: regardez les exemples vert.x, en Java il y a des classes anonymes à la place des fonctions en JavaScript. Cela produit énormément de code supplémentaire. Dans mon esprit, il s'agit d'une des erreurs les plus classiques de conception dans le langage Java. L'idée même des classes anonymes est mauvaise. Le problème sera enfin résolu avec Java 8.
InfoQ: Tu dis que la communauté Java demande aux développeurs JavaScript d'"aller créer des frontends". Est-ce un désavantage pour Node.js d'avoir beaucoup de personnes capables de créer des programmes en JavaScript alors que la création de grands systèmes sur Node.js demande une expérience totalement différente ? Est-ce que l'on ne risque pas de voir des personnes concevoir de grands systèmes sans avoir la compétence de le faire à cause de ces nouveaux langages qui arrivent dans les entreprises ?
Eberhard: La communauté Java a traditionnellement construit des systèmes backend et est habitué à travailler sur de grands systèmes. Un grand nombre des idées sur la conception de grands systèmes sont issues de la communauté Java. Mais je ne jugerais pas un développeur sur le langage qu'il utilise. Concernant la programmation asynchrone, elle est tout simplement dans leurs veines. Pour les grands systèmes, la modularisation est très importante. vert.x offre une alternative intéressante. Avec une modularisation correcte, vous pouvez découper un gros système en de petites pièces. Et encore mieux, le concept de modularisation est basé sur un système de messages, ce qui apporte d'autres avantages. Vous allez avoir une très faible dépendance entre les modules puisque le système dépend uniquement de messages et non d'appels de méthodes.
InfoQ: Et en utilisant JSON, nous avons un format de message qui est relativement léger et qui aide à éviter les problèmes de compatibilités.
Eberhard: C'est exact. Mais JSON est juste une des possibilités. JSON ne permet pas d'avoir des définitions avec un schéma. Certains disent que les schémas sont mauvais parce qu'ils rendent les choses inflexibles. Ils prétendent que vous vous retrouvez avec modèle en cascade où vous définissez les interfaces en premier puis vous construisez votre système en vous basant dessus. Cependant, je crois que ça serait une bonne chose de pouvoir vérifier que les messages JSON sont structurés de la manière dont je l'attends. Et c'est là que je reconnais un problème avec JSON. Habituellement, vous voulez une sorte de contrat qui définit la structure attendue des données. Et je pense, vous pouvez bénéficier des avantages des schémas XML dans de telles situations.
InfoQ: J'ai eu une drôle d'expérience avec les types dynamiques il y a quelque mois. J'ai accueilli une formation où l'on a codé une sorte de clone de Twitter basé sur PhoneGap, Node.js et MongoDB. A un moment, la personne qui faisant le frontend a eu une idée, pour ajouter des images dans leurs "tweets". Ces images étaient transférées via le serveur Node dans la base de données et ensuite retournaient sur le frontend. Quand l'équipe frontend a montré cette fonctionnalité, les équipes de Node et de la base de données étaient très surprises, car elles ne savaient pas qu'elles manipulaient des images. C'était très intéressant dans cette situation, même si je pense que cela peut poser des problèmes importants.
Eberhard: C'est exactement l'avantage d'un schéma flexible. Mais si plusieurs équipes sont impliquées dans le développement, vous voulez généralement une sorte de contrat entre les interfaces. Pour réaliser ce contrat, vous avez besoin de schéma. Ce que tu décris montre aux autres des points intéressants : qu'est-ce que vous avez pour interpréter les données ? Dans la pile que tu mentionnes, tu n'es pas intéressé dans le contrôle et la vérification des données dans tout le système. Tu veux juste stocker des documents JSON. Ce qui est à l'intérieur du document n'est pas pertinent parce que tu n'as pas besoin de les interpréter. C'est peut-être une des différences avec les systèmes d'entreprise. Si vous dites "c'est un client", alors vous devez savoir à quoi ressemblent les données d'un client.
InfoQ: Il y a un peu de l'idéologie JavaScript ou de typage dynamique derrière ça. Quand ça marche, nage et cancane comme un canard, j'appelle ça un canard. Si cela ressemble au type que j'attends et que ça contient les données dont j'ai besoin, le reste est sans importance.
Eberhard: Exactement. Mais il y a des problèmes. Quand vous avez une représentation d'un client et que vous vous attendez à avoir une date de naissance, alors vous pouvez le définir dans le schéma. C'est là où les schémas XML sont excellent parce qu'ils ont un système de typage très sophistiqué. Vous pouvez même définir à quoi ressemble un nombre avec des expressions régulières. Et si quelqu'un enfreint le schéma, il doit avoir des soucis à le faire. Le schéma va lui dire que ses données sont invalides. Il peut s'en servir comme un avertissement préventif.
InfoQ: C'est toujours du JSON qui est utilisé sur le bus d'événements ?
Eberhard: Il est possible d'utiliser n'importe quel objet. Cependant, si vous utilisez des objets Java, vous allez avoir des problèmes de sérialisations et classloader. C'est pourquoi JSON est la solution préférée dans ce contexte et que c'est ce qui est généralement utilisé.
InfoQ: Concernant des technologies telles que Node.js ou vert.x, dirais-tu que les architectures pour des applications importantes sont basées sur ces technologies ? Ou penses-tu plutôt que ces technologies sont juste utilisées dans une partie bien définie de ces architectures ? Si je m'en souviens bien, LinkedIn gère le trafic pour les appareils mobiles via Node.js mais l'application est en soi une application d'entreprise «normale».
Eberhard: À l'heure actuelle, je crois que cela va prendre du temps avant que ces technologies ne soient largement utilisées dans les applications d'entreprises normales. Il y a une vraie migration à faire. C'est un peu différent pour vert.x. vert.x peut être embarqué dans d'autres applications. Mais pour pouvoir l'utiliser pleinement, vous devez utiliser son environnement d'exécution. Cet environnement est très différent des environnements classiques Java. Il y a juste un processus Java et pas de servlet ou de conteneur d'application. Mais il y a une tendance à aller vers des systèmes asynchrones. Il y a Erlang, Scala, Akka et des frameworks comme Spring Integration ou Apache Camel, chacun ayant des approches différentes. Par exemple, Spring Integration ou Apache Camel fournissent divers connecteurs, envoient des messages asynchrones et traitent les données. Donc ils fournissent une solution d'intégration, comme expliquée dans le livre "Enterprise Integration Patterns". L'idée derrière Erlang était d'avoir des performances et une fiabilité élevées. vert.x est similaire. Travailler de manière asynchrone est une manière spécifique de construire un système qui est en train de devenir de plus en plus important.
InfoQ: Qu'en penses-tu, personne ne devrait essayer de le faire avec ces technologies ? Quels sont les pièges que je pourrais rencontrer ?
Eberhard: La question est, dans quel contexte ces solutions sont-elles particulièrement utiles ? Je pense que leurs places c'est celle où l'on peut créer des systèmes performants, et plus particulièrement pour un nombre très important de clients. Pour le dire autrement : si tu veux créer une application web classique, ce n'est peut-être pas la meilleure des solutions.
InfoQ: Comment utiliser un framework existant avec vert.x ? Est-ce que je peux simplement choisir n'importe quel framework existant et par exemple utiliser un framework comme Apache Wicket pour délivrer les pages web ?
Eberhard: Malheureusement c'est n'est pas aussi simple parce que la majorité des frameworks front sont basé sur les API servlet. L'API servlet est bloquante et donc non compatible avec vert.x. Tu dois donc concevoir une solution utilisant un moteur de templating et prendre soin de délivrer des pages HTML toi même. Mais un cas d'utilisation typique serait de créer un backend en utilisant JSON avec des interfaces REST pour les frontends en JavaScript. Tu vas avoir plus de logique dans ton front et moins dans le back. Pas nécessairement moins de logique métier, mais par exemple la logique pour faire le rendu des pages HTML.
InfoQ: Tu as mentionné les environnements de production. Est-ce que tu penses qu'ils vont utiliser plus de scénarios basés sur le cloud dans ce contexte ? Ou est-ce qu'il n'y a actuellement pas trop de différences et que l'exploitation doit apprendre de nouveaux paradigmes ?
Eberhard: Cela dépend de ce que tu appelles "cloud". Le problème avec la majorité des PasS est qu'ils exposent juste les API servlet et tu te retrouves dans la même situation dont venons juste de parler. Ce n'est pas un problème de déployer des applications vert.x sur des IaaS mais je ne vois pas de gros avantages à utiliser vert.x par rapport aux autres technologies Java dans ce domaine.
InfoQ: Parlons un peu plus de l'aide apporté par ces outils sur le temps de développement. Si tu a Node.js à l'esprit, tu trouveras des IDE qui supporteront plus ou moins bien JavaScript, mais même les meilleurs sont à des années-lumière de ce que l'on utilise quand on développe des applications Java. Vis-à-vis de la qualité, cela semble identique : il y a des améliorations, mais c'est encore insuffisant. Dans quelle situation se trouve vert.x sur ce sujet ?
Eberhard: Ce qui est bien avec vert.x, c'est que vous pouvez utiliser le mécanisme de redéploiement. Cela rend le développement beaucoup plus facile. Et vous avez aussi l'avantage que vert.x compile et exécute n'importe quel fichier source que tu lui fournis. Cependant il n'y a pas de plug-in Eclipse.
InfoQ: D'ailleurs, je suppose que tu peux utiliser tout ce qui existe déjà. Par exemple les infrastructures pour les tests ou faire de la revue de code automatique sur toute la partie que l'on décide de faire en Java ?
Eberhard: Vous pouvez le faire oui. Mais comme je le disais avant, les concepts de modularisation et de déploiement sont différents. Vous faites donc face à des problèmes difficiles.
InfoQ: Qu'en est-il du debug avec vert.x ? Est-il possible de juste s'attacher au process ?
Eberhard: Bien sûr, cette fonctionnalité est fournie par la JVM. Utiliser la JVM apporte certains avantages. Le code est exécuté sur une machine virtuelle extrêmement optimisée qui exécute du bytecode. Et je pense que c'est plus facile de créer une VM optimisée pour du bytecode que pour du JavaScript. Ce que l'équipe V8 a fait est juste ahurissant et très passionnant. Mais il y a énormément d'ingénierie qui a été investie dans la JVM. Et c'est une très bonne idée de pouvoir compter dessus et de l'utiliser. Il y a des mesures qui montre que vert.x est plus rapide que Node.js, mais quelque soit le facteur, comme pour tous les autres benchmark, c'est difficile à interpréter.
InfoQ: Oui c'est vrai, mais cela semble logique. D'un côté, ce que l'équipe V8 a créé ces dernières années est très intéressant. Mais de l'autre côté, on a quelque chose comme 20 ans de développement sur la JVM. Et on doit dire qu'il y a certains concepts sur lesquels s'appuie le moteur V8 pour être performant. Si vous n'appliquez pas ces concepts, vous pouvez écrire du code syntaxiquement correct, mais en contradiction avec ses concepts et avoir des performances faibles. Je pense que cela ne peut pas arriver en Java de la même manière. Je peux bien sûr écrire du mauvais code et des boucles idiotes, mais il s'agit d'un autre type d'erreur.
Eberhard: C'est un peu comme comparer des pommes et des bananes. En fait, on doit comparer l'ensemble de la pile : Rhino et la JVM pour JavaScript avec vert.x et V8 pour Node.js. Le support des langages dynamiques n’était pas sur la JVM au début. Une autre chose est que vous pouvez utiliser plusieurs boucles d'événements avec vert.x, habituellement une pour chaque coeur CPU. Cela ne semble pas être le cas avec V8. Cela signifie que si j'ai un serveur avec 8 coeurs, je suis obligé de lancer plusieurs serveurs Node. Alors qu'avec verx.x, j'aurai juste à démarrer une seule JVM avec 8 boucles d'événements. Ceci est très différent et peut-être plus efficace. Mais comme je le disais, les benchmarks sont un sujet très complexe.
InfoQ: On arrive à la fin et pour résumer peux-tu me dire quels sont les principaux avantages de vert.x ? Tu n'arrives pas à cacher ton intérêt pour ce sujet.
Eberhard: Il y a plusieurs raisons pour lesquelles je pense que c'est une technologie intéressante et que je considère importante. Premièrement, les IO asynchrones vont devenir très importantes pour la JVM. Ensuite, il y a une meilleure modularisation. Ceci est un problème pour un nombre important de projets et il est difficile d'avoir une bonne solution. Et dernièrement, je pense que c'est pertinent, parce qu'à mon avis, la JVM va devenir de plus en plus polyglotte. Je ne pense pas que Java comme unique langage est nécessaire pour l'avenir de la JVM. vert.x va aider à aller dans ce sens, car il est réellement polyglotte. La difficulté est que pour en tirer pleinement partie, les conteneurs d'applications et les servlets doivent être remplacés par vert.x.
Eberhard Wolff est un membre fondateur des Java Champions, auteur de nombreux articles et livres et aussi speaker régulier dans différentes conférences internationales. Il a des compétences en Java, Spring, NoSQL et le Cloud. Il travaille aussi comme architecte et responsable technologique d'adesso AG à Berlin en Allemagne.