Efficience des apps java dans le cloud

Thierno Diallo
Just-Tech-IT
Published in
8 min readNov 10, 2021

Lors de ma participation à Devoxx France 2021, j’ai eu l’occasion et le plaisir de participer à plusieurs conférences très intéressantes sur les architectures réactives, Kafka Stream et KsqlDB, et sur l’état de l’art des apis REST.

Parmi ces trois conférences qui ont retenues mon attention, j’ai particulièrement aimé la séance sur les architectures réactives et la compétitivité de java dans le cloud, c’est de cette dernière que je vous parlerai dans la suite de cet article.

1- Lourdeurs des applications Java déployées sur le cloud

Depuis les débuts de java il y a 25 ans, le langage a beaucoup évolué. Malgré tout, l’IT a évolué encore plus vite. Aujourd’hui nous ne développons pas ou ne déployons pas les mêmes applications, ni de la même manière, et les plateformes sur lesquelles nous déployons ne sont plus les mêmes non plus. Avant il y avait des systèmes qui tournaient pendant plusieurs mois voire années sans aucune évolution ou changement, avec le rythme d’une release tous les 6 mois ou plus. Alors qu’aujourd’hui, nous avons des applications qui évoluent très fréquemment, avec une forte demande en matière de souplesse, d’adaptation, de performance, de sécurité et de résilience. Donc, pour que java puisse être compétitif dans le cloud par rapport aux autres langages comme Node, il a fallu retravailler les fondamentaux à savoir la gestion de la mémoire et la manière dont les classes sont chargées par exemple. Avec l’utilisation sans cesse grandissante de la conteneurisation, des architectures micro-services ou des serverless ce besoin est devenu encore plus pressant. En 25 ans nous avons vu une grosse application monolithique se transformer à environ une dizaine de micro-services et ces micro-services passaient à une centaine des fonctions.

A titre de comparaison entre java, Node et GO le rapport sur la densité de déploiement sur une même plateforme calibrée pour 4 applications java, nous pouvons mettre environs 8 applications en Node, et environ 4 fois plus de GO. Par conséquent, java n’est pas forcément viable économiquement dans le cloud par rapport à Node et GO. Étant donné que l’objectif n’est pas non plus de transformer toutes les applications java en Node ou GO pour pouvoir les mettre dans le cloud, il a alors fallu optimiser le fonctionnement de java.

Pour résoudre ces différentes problématiques, une des solutions proposées pendant la conférence est le passage à une architecture réactive avec Quarkus et l’utilisation de la compilation native avec GraalVM.

2- Architecture réactive avec Quarkus

Pour gérer les problématiques de performance, de mémoire occupée et de mémoire ram utilisée, Quarkus a fait le choix d’adopter une architecture réactive. Pour expliquer de manière rapide les architectures réactives, ceux sont des architectures qui répondent aux cinq principes suivants à savoir disponibles, résilientes, souples, très faiblement couplées, et orientées messages. J’ai trouvé Quarkus facile d’utilisation pour les développeurs, et la mise en place du live reload (développer pendant que l’application tourne) est une feature très intéressante.

Dans un Framework traditionnel on construit un exécutable jar, war ou autre c’est le buildtime. Au moment du démarrage, l’application cherche et charge sa configuration, puis fait le scan du classpath pour trouver les éléments dont elle a besoin pour tourner, cette étape est appelée le runtime. Ainsi chaque Framework va se construire son écosystème et démarrer finalement, ce qui a tendance à allonger le temps de démarrage des applications.

L’idée intéressante implémentée dans Quarkus se base sur le fait de réaliser pendant le buildtime une grande partie des actions de l’étape runtime. Le chargement de la config ou le classpath scanning and loading par exemple. Ce qui conduit à avoir un package construit quasi sur mesure, et au moment du démarrage nous savons exactement ce dont a besoin. Par conséquent, lors du démarrage, on va directe à l’essentiel du démarrage et la configuration supplémentaire comme les user/pwd par exemple.

L’avantage que j’ai trouvé intéressant sur la réalisation d’une grande partie des actions au buildtime, est la capacité de construire des images natives, car l’application connait tout ce qu’il lui faut pour tourner. Par conséquent, elle peut être optimisé par le compilateur pour virer toute les librairies et dépendances non nécessaires.

Nous constatons de jour en jour l’intérêt grandissant pour conteneurisation de nos APIs par l’intermédiaire de Docker. Dés lors, se pose la question de pouvoir créer des livrables Dockers avec la technologie Java, sans pour autant embarquer une lourde JVM dans tous nos conteneurs. Lors de cette conférence nous avons parlé de GraalVM, qui est l’outil le plus utilisé et performant pour l’optimisation des apps java. Le problème de tous les compilateurs y compris GraalVM, c’est le nombre d’argument qu’il faut en entrer de la compilation. Pour faciliter l’utilisation de GraalVM, étant donné que Quarkus connait très bien l’application et tout ce qu’il lui faut pour démarrer, il est capable de fournir la commande GraalVM exacte qu’il faut pour faire la compilation native. L’image ci-dessous illustre parfaitement ces propos.

Quarkus

Quarkus est un Framework développé et maintenu par Redhat, il est basé sur un moteur réactif qui s’appelle Quarkus Reactive Core avec Netty et vert.x. Quarkus permet tout autant de faire de la programmation réactive que de l’impérative. Mais dans le cadre de cet article, nous allons parler que de la partie réactive.

Au-dessus de cette couche réactive, il y a des centaines d’extensions, lors de la conférence nous avons parlé que des extensions basiques pour faire une api REST+CRUD. Il y a le resteasy reactive pour faire des applications rest réactive, Hibernate réactive pour rendre la persistance de donnée réactive et le réactive rest client qui permet d’appeler des apis rest de manière réactive.

J’ai trouvé intéressant de pouvoir réaliser rapidement et facilement des apis réactives non-bloquantes avec très peu de codes ou librairies. Cependant, le fait d’avoir une app utilisable rapidement sans beaucoup d’effort ne pas l’apanage que de quarkus. Les mêmes choses existent avec spring, et spring web flux permet de faire du réactive aussi.

Pour initialiser une application quarkus il suffit d’aller sur https://code.quarkus.io/ pour les personnes qui ont déjà utilisé l’initialiseur de spring, elles ne seront pas dépaysées. Vous pouvez également l’initialiser via ligne de commande Maven avec

mvn io.quarkus.platform:quarkus-maven-plugin:2.4.1.Final:create \

-DprojectGroupId=org.acme \

-DprojectArtifactId=lifecycle-quickstart \

-DclassName=”org.acme.lifecycle.GreetingResource” \

-Dpath=”/hello”

L’aspect équivalence avec Spring au niveau du langage, des annotations ou des composants, fait de Quarkus un Framework facile à prendre en main pour un dev qui est habitué à utiliser spring.

Pendant cette conférence, j’ai découvert la librairie de programmation réactive mutiny pour faire des traitements et compositions d’actions de manière asynchrone. Mutiny est orienté évènement, Il offre 2 types à savoir le type Uni pour les actions asynchrones avec zéro ou un élément en réponse, puis le type Multi qui va gérer les flux de manière asynchrones.

J’ai appris les fondements de l’extension Resteasy reactive, qui est une nouvelle implémentation de JAX-RS, conçu pour fonctionner avec Vert.x, donc être complément réactive. Étant directement intégrée dans quarkus, une grande partie du travail est faite lors du buildtime.

Il se substitue à tout autre implémentation de JAX-RS, en plus il permet d’avoir de très bonne performance en mode bloquant et non bloquant.

La découverte de l‘api réactive pour Hibernate ORM « Hibernate reactive » était extrêmement positive. Dans le sens où elle permet de supporter les drivers non-bloquants de base de données, et gérer l’interaction réactive avec la base de données.

3- Compilation Native GraalVM

Concept

GraalVM est une plateforme (machine virtuelle) avec un compilateur intégré et très performant. Cette plateforme est conçue pour accélérer l’exécution des applications java, mais aussi elle possède la spécificité de supporter plusieurs autres langages comme Ruby, R, Javascript par exemple.

J’ai trouvé attrayante sa capacité polyglotte qui lui permet d’utiliser plusieurs langages dans une même application tout en éliminant les coûts d’appels inter-langage.

Pour tenir ses promesses de plateforme polyglotte, ainsi que l’assurance de rapidité d’exécution. GraalVM a ajouté un compilateur Just-In-Time optimisé, en plus de l’ajout du Framework truffle qui permet de supporter les autres langages et d’avoir une interopérabilité directe.

GraalVM permet également trois modes d’utilisation, à savoir le mode natif (AOT), l’exécution sur JVM (JIT), et Java on Truffle qui reprend le Framework Truffle pour exécuter du Java, en précisant que cette dernière option reste expérimentale, donc interdite en production.

J’ai particulièrement été impressionné par le mode natif, qui fait de la compilation anticipée (AOT) du code java vers un exécutable standalone, appelé image native.

Avec l’analyse statique, cette compilation anticipée a pour rôle d’optimiser en enlevant le code mort et en supprimant toutes les classes et dépendances y compris JDK qui ne sont pas nécessaires à l’exécution.

Le mode image native permet de réduire considérablement la mémoire occupée et utilisée par les exécutables. Par conséquent, plus d’exécutables lancer sur un espace restreint. Ce mode accélère également le temps de démarrage des applications.

En définitive, avec l’adoption de l’approche réactive ainsi que la compilation native sur la plus basique des apps REST HelloWorld. Nous avons une illustration de l’avantage certain sur la mémoire ram utilisée, ainsi que le temps de démarrage. Ce benchmark est réalisé avec Quarkus 2.0.0.Final, GraalVM Entreprise 21.2, Spring Boot 2.5.3 et Spring 5.3.X.

Avec l’ajout de la partie le sécurité, base de données et tout ce qui permet d’avoir une application CRUD complète. Nous aurons le récapitulatif suivant, je vous laisse le soin d’apprécier le gain

Avec l’association Quarkus et GraalVM, Java commence à rentrer en compétition avec les autres langages bien optimisés pour le cloud comme .Net Core, Node et GO.

J’ai trouvé la conférence très intéressante par rapport à l’approche d’architecture réactive de quarkus et son association avec GraalVM. Même si aujourd’hui Spring offre une possibilité de faire du réactif aussi et qu’on pourrait associer Spring et GraalVM, Spring native reste encore expérimentale. Donc, il faudra attendre la sortie de Spring 6 fin 2022, pour pouvoir le déployer en production. Alors que de Quarkus est prêt à l’emploi, même s’il pourrait éventuellement manquer de maturité, et les 2 tableaux récapitulatifs montrent un gain non négligeable de l’association quarkus graalVM.

Sources qui ont permis la rédaction de cet article :

Devoxx France 2021 : Microservices réactifs avec Quarkus (Clement ESCOFFIER,Stéphane ÉPARDAUD)

Site quarkus

Site GraalVM

Présentation de GraalVM par Oracle

--

--

Thierno Diallo
Just-Tech-IT

Staff Engineer/Technical Leader And Green Champion at Axa France