Le langage de pro­gram­ma­tion Java est reconnu de longue date comme une ins­ti­tu­tion dans le secteur in­for­ma­tique. Il est apparu durant les premières années d’internet, mais le Web s’est développé à toute vitesse depuis. Outre l’ar­chi­tec­ture classique client-serveur, il existe un vaste éventail de modèles al­ter­na­tifs dignes d’intérêt : les ap­pli­ca­tions basées sur des con­te­neurs, les mi­cro­ser­vices, l’in­for­ma­tique sans serveur, et les applis Web réactives se sont imposés dans la vie de tous les jours. Ces types d’ap­pli­ca­tions ont jusqu’à présent été difficile à con­fi­gu­rer avec Java. Grâce à la structure Quarkus, les choses ont commencé à changer. Le manager de RedHat Ken Johnson exprime cela ainsi :

Citation

« … it’s a very small Java stack, perfect for con­tai­ners, ser­ver­less and other scenarios where you’re running Java ap­pli­ca­tions in the cloud. »

– Ken Johnson, source : https://www.openshift.com/blog/quarks-is-here-for-your-java

Trans­la­tion : « … il s’agit d’une toute petite Java stack, qui est parfaite pour les con­te­neurs, le sans serveur et d’autres scénarios où des ap­pli­ca­tions Java sont exécutées sur le Cloud. » (traduit par IONOS)

Dans cet article, nous allons vous présentez Quarkus et vous montrer dans quelle mesure cette structure ré­vo­lu­tionne la création d’ap­pli­ca­tions Java.

Qu’est-ce qui rend Quarkus spécial ?

Quarkus est une structure dé­ve­lop­pée par RedHat pour créer des ap­pli­ca­tions Java. Quarkus a été développé dans le but d’exécuter des pro­grammes Java dans des con­te­neurs. Elle se concentre en par­ti­cu­lier sur le fait de soutenir le logiciel d’or­ches­tra­tion Ku­ber­netes. Un autre point focal du dé­ve­lop­pe­ment de Quarkus concerne l’uti­li­sa­tion des bi­blio­thèques et des standards établis de Java.

« HotSpot », du projet OpenJDK, est utilisé comme une Machine Javal Virtuelle (JVM) en tant que couche d’exécution du code Java. En outre, le dé­ve­lop­pe­ment « GraalVM », qui développe à partir de HotSpot, peut également être utilisé. Ce dernier permet au code Java d’être compilé en code in­for­ma­tique exé­cu­table di­rec­te­ment. Pour com­prendre quel avantage immédiat apporte l’uti­li­sa­tion de Quarkus, examinons d’abord de quelle manière les ap­pli­ca­tions Java sont exécutées avec et sans Quarkus.

Comment les ap­pli­ca­tions Java sont-elles tra­di­tion­nel­le­ment exécutées ?

L’idée fon­da­men­tal qui a rendu Java ré­vo­lu­tion­naire lors de son ap­pa­ri­tion était aussi simple que fas­ci­nante : Java rendait possible le fait d’écrire un programme sans être dépendant d’un support matériel ou d’un système d’ex­ploi­ta­tion spé­ci­fique. L’in­dé­pen­dance d’une telle pla­te­forme est souvent résumée en cette simple phrase : « write once, run anywhere » (« écrire une fois, exécuter n’importe où »). La por­ta­bi­lité inhérente à ce programme lui permet d’être déplacé d’une pla­te­forme à l’autre. Un vrai tour de magie ! Mais alors, comment ça marche ?

De même que pour les autres langages de pro­gram­ma­tion, un programme Java commence avec un code source qui peut être lu par un être humain. Dans l’optique d’exécuter les ins­truc­tions du texte source sur un or­di­na­teur, des ins­truc­tions ciblées sont générées au format du pro­ces­seur spé­ci­fique. Avec Java, une autre étape in­ter­mé­diaire entre en jeu : le texte source est d’abord traduit dans un format in­ter­mé­diaire, que l’on appelle le bytecode (« code en byte »), comme c’est le cas avec le langage Python. Le bytecode est ensuite exécuté dans la « Machine Virtuelle Java » (JVM). Si l’on souhaite exécuter un programme Java sur un appareil, un JVM doit y être installé.

Le bytecode est tra­di­tion­nel­le­ment in­ter­prété pour être exécuté dans le JVM. Les ins­truc­tions en bytecode sont traduites morceau par morceau en des ins­truc­tions en code machine et exécutées. Le processus de « com­pi­la­tion juste à temps » (JIT) est plus efficace. Avec ce processus, le bytecode est également converti en code machine, mais une op­ti­mi­sa­tion com­plé­men­taire entre également en jeu. En gros, exécuter un programme Java implique de suivre les étapes suivantes :

  1. Compiler le code source Java en bytecode avec la commande de com­pi­la­tion Java 'javac' :
javac java_program.java
  1. Exécuter le bytecode Java avec la commande d’exécution 'java' – le code machine est alors généré :
java java_program
Note

Nous parlons ici d’une « machine virtuelle ». Bien que le terme soit le même, en l’oc­cur­rence, il ne renvoie à aucun type de tech­no­lo­gie dédié à rendre un système d’ex­ploi­ta­tion virtuel. Au lieu de cela, le code in­ter­mé­diaire est traduit en code machine.

Si pratique que soit le modèle « write once, run anywhere » de Java, cette approche présente quelques fai­blesses : avoir recours au JVM implique des limites non né­gli­geables. D’un côté, démarrer le JVM prend un certain temps, lequel vient s’ajouter au temps d’exécution de l’ap­pli­ca­tion en elle-même. D’un autre côté, outre la con­som­ma­tion de mémoire plus élevée, une perte en termes de per­for­mances est notable. Tout ceci joue un rôle mineur s’agissant des ap­pli­ca­tions qui sont exécutées sur une longue période. En revanche, cette approche ne convient que peu aux ap­pli­ca­tions à courte durée de vie et basées sur des con­te­neurs. Dans un monde idéal, celles-ci devraient démarrer le plus vite possible. Il est inac­cep­table d’attendre quelques secondes pour les voir se lancer.

Comment les ap­pli­ca­tions Java sont-elles exécutées avec Quarkus ?

À la dif­fé­rence de l’exécution native des ap­pli­ca­tions Java, Quarkus offre plusieurs avantages. Eta­blis­sons une dif­fé­rence entre les deux modes supportés par Quarkus :

  1. Op­ti­mi­sa­tion du bytecode et exécution dans le JVM
  2. Exécution en tant que code natif après la com­pi­la­tion

Le code Java écrit avec Quarkus peut être exécuté nor­ma­le­ment dans le JVM. Quoi qu’il en soit, il existe des avantages con­si­dé­rables en termes de con­som­ma­tion de mémoire et de temps de démarrage d’une ap­pli­ca­tion en cours d’exécution. Pour parvenir à cela, Quarkus a recours à quelques astuces. Plus pré­ci­sé­ment, un certain nombre d’étapes chro­no­phages sont déplacées du processus d’exécution à celui de dé­ve­lop­pe­ment. Ceci comprend les étapes qui, dans les autres cas, ont lieu à chaque fois qu’une ap­pli­ca­tion Java est exécutée :

  • Charger et analyser les con­fi­gu­ra­tions
  • Scanner le chemin de classe Java et résoudre les an­no­ta­tions
  • Créer des modèles d’entités pour les bases de données ou équi­va­lents lorsque cela s’applique

Avec Quarkus, ces étapes sont menées à bien une seule fois et les résultats sont mis en cache pour une ré­cu­pé­ra­tion rapide. Une op­ti­mi­sa­tion com­plé­men­taire des per­for­mances a lieu via le fait, pour Quarkus, de réduire la quantité d’in­for­ma­tion dynamique dis­po­nible à l’exécution. Ceci est remplacé par des cons­truc­tions statiques cor­res­pon­dantes. C’est par­ti­cu­liè­re­ment utile quant à l’uti­li­sa­tion qui a lieu dans les con­te­neurs. Une ap­pli­ca­tion con­te­neu­ri­sée n’est de toute façon gé­né­ra­le­ment pas modifiée et est toujours exécutée dans le même en­vi­ron­ne­ment.

Le second mode supporté par Quarkus pour exécuter des ap­pli­ca­tions Java est encore plus in­té­res­sant. Avec la com­pi­la­tion anticipée (AOT), un code machine di­rec­te­ment exé­cu­table est généré depuis la source Java à la place du bytecode, ce qui signifie qu’il n’y a plus besoin d’un JVM sur le matériel cible. Le programme est uni­que­ment exé­cu­table sur des ar­chi­tec­tures de pro­ces­seur spé­ci­fiques et doit être compilé à nouveau sur d’autres pla­te­formes. Quoi qu’il en soit, cette res­tric­tion n’est en général pas per­ti­nente pour un usage dans des con­te­neurs. Les économies en termes de con­som­ma­tion de mémoire et de temps de démarrage d’ap­pli­ca­tions réalisées grâce à la com­pi­la­tion AOT sont tout sim­ple­ment épous­tou­flantes. Comparez les niveaux ré­fé­rences de per­for­mance exposés ci-dessous depuis la page d’accueil of­fi­cielle de Quarkus :

Ap­pli­ca­tion Scénario Mémoire utilisée Durée avant la première réponse
Quarkus + AOT REST 12 MB 0.02 s
Quarkus + AOT REST + CRUD 28 MB 0.04 s
Quarkus + JIT REST 73 MB 0.94 s
Quarkus + JIT REST + CRUD 145 MB 2.03 s
Cloud Native Stack REST 136 MB 4.3 s
Cloud Native Stack REST + CRUD 209 MB 9.5 s
Note

En ce qui concerne la ter­mi­no­lo­gie : REST signifie que seul un serveur Web est en cours d’exécution dans le conteneur. Dans le scénario REST + CRUD, une base de données est exécutée en même temps que le serveur Web. Pour une stack Cloud native, le conteneur contient un JVM, en sup­plé­ment de l’ap­pli­ca­tion Java.

Dans quel but utilise-t-on Quarkus ?

Quarkus est bien plus qu’une simple structure d’ap­pli­ca­tion : ce logiciel a été conçu pour redéfinir ce que cela signifie de dé­ve­lop­per des ap­pli­ca­tions avec Java. À titre de rappel : tra­di­tion­nel­le­ment, il était plus important pour une ap­pli­ca­tion Java d’être exécutée de manière stable sur une longue période. Le temps que mettait une ap­pli­ca­tion à démarrer était perçu comme se­con­daire.

Prenez les ap­pli­ca­tions basées sur des con­te­neurs : de nouveaux con­te­neurs peuvent être lancés au­to­ma­ti­que­ment par un logiciel d’or­ches­tra­tion. L’ap­pli­ca­tion dans le conteneur doit alors être prête à être im­mé­dia­te­ment utilisée. En outre, plusieurs con­te­neurs re­don­dants sont souvent lancés pour un même service. La réduction en termes de con­som­ma­tion de res­sources réalisée avec Quarkus est mul­ti­pliée en con­sé­quence.

Le manager de RedHat Alex Handy résume les choses ainsi :

Citation

« When you think of ser­ver­less computing, mi­cro­ser­vices and the […] cloud, there’s one language you’re probably not [thinking of]: Java. And that’s a real shame. […] Java was and is the workhorse language of business. It remains the third most popular language in the world […] It’s been the language of choice for cor­po­ra­tions that need to keep a single ap­pli­ca­tion up and running for years at a time. »

– Alex Handy, source : https://the­news­tack.io/quarkus-gives-spring-boot-users-a-path-to-ser­ver­less-and-live-coding/

Tra­duc­tion : « Lorsque vous pensez à l’in­for­ma­tique sans serveur, aux mi­cro­ser­vices et au […] Cloud, il y a un langage auquel vous ne [pensez] pro­ba­ble­ment pas : Java, et c’est vraiment dommage […] Java était et est encore le cheval de bataille des langages dans le monde des affaires. Il reste le troisième langage le plus populaire au monde […] Il n’a cessé d’être le choix n°1 des en­tre­prises qui ont besoin d’avoir une ap­pli­ca­tion à la fois qui reste fonc­tion­nelle et per­for­mante pendant des années. » (traduit par IONOS)

Les avantages de Quarkus sont évidents. Quoi qu’il en soit, la structure connaît aussi quelques limites. En tant que tel, Quarkus n’a pas été conçu, au départ, pour migrer des ap­pli­ca­tions Java exis­tantes. Au contraire, il vaut mieux utiliser Quarkus en tant que point de départ pour un nouveau dé­ve­lop­pe­ment. Nous allons jeter un œil à quelques zones d’ap­pli­ca­tion spé­ci­fiques ci-dessous. Dans tous les exemples cités, Maven ou Gradle est utilisé en tant qu’outil de dé­ve­lop­pe­ment. La zone d’ap­pli­ca­tion est dé­ter­mi­née en con­fi­gu­rant la commande « mvn » ou « gradle ». L’outil de dé­ve­lop­pe­ment génère ensuite au­to­ma­ti­que­ment les con­fi­gu­ra­tions et artefacts né­ces­saires.

Exécuter des ap­pli­ca­tions de mi­cro­ser­vice dans Ku­ber­netes avec Java et Quarkus

Ku­ber­netes constitue un logiciel d’or­ches­tra­tion pour les ap­pli­ca­tions conteneur. Il est assez courant d’avoir recours à Ku­ber­netes avec des con­te­neurs Docker. Les services in­di­vi­duels d’une ap­pli­ca­tion sont sau­ve­gar­dés en tant qu’images Docker et gérés par Ku­ber­netes. L’or­ches­tra­teur prend en charge la gestion des con­te­neurs générés depuis les images : Ku­ber­netes démarre, contrôle et supervise les services. Souvent, plusieurs copies d’un même service sont lancées pour partager la charge et augmenter la tolérance aux pannes. Si l’un des services s’in­ter­rompt, le conteneur est détruit et un autre conteneur est créé depuis la même image. Java Quarkus comprend les con­fi­gu­ra­tions qui sont né­ces­saires pour un usage dans Ku­ber­netes.

Mettre en œuvre des APIs REST et des ap­pli­ca­tions sans serveurs avec Java et Quarkus

REST est un style d’ar­chi­tec­ture établi de longue date pour les ap­pli­ca­tions Web. Les APIs en par­ti­cu­lier sont prin­ci­pa­le­ment mises en place en suivant cette approche. Une API REST est basée sur une ar­chi­tec­ture serveur-client. La com­mu­ni­ca­tion prend place via le protocole http à l’aide des « verbes » GET, POST, PUT, DELETE. Ceux-ci cor­res­pon­dent aux fameux « verbes » CRUD (« create, read, update, delete » (« créer, lire, ac­tua­li­ser, supprimer ») issus de l’en­vi­ron­ne­ment des bases de données. Un échange de données entre une API et un uti­li­sa­teur prend en général place via JSON.

L’in­for­ma­tique sans serveur constitue une ar­chi­tec­ture al­ter­na­tive pour les ap­pli­ca­tions basées sur le Cloud. Dans ce modèle, également connu sous le nom de « Function as a Service » (« Fonction en tant que service ») (FaaS), une seule fonction est exécutée briè­ve­ment dans un conteneur. La fonction est appelée, réalise un calcul, et est à nouveau éteinte. En dépit de son nom, les fonctions sans serveurs con­ti­nuent à être exécutées sur des serveurs. Les pro­gram­meurs n’ont plus à s’inquiéter à leur sujet. Avec AWS Lambda, les Fonctions Google Cloud et les Fonctions Microsoft Azure, les en­vi­ron­ne­ments sans serveurs sont dis­po­nibles sur toutes les prin­ci­pales pla­te­formes de Cloud. Le code Java peut être utilisé sur ces pla­te­formes par le biais de Quarkus.

Conseil

Créez votre propre API-REST sur un serveur dédié de IONOS.

Dé­ve­lop­per des applis Web réactives à l’aide de Java et Quarkus

À la dif­fé­rence de la pro­gram­ma­tion im­pé­ra­tive, la pro­gram­ma­tion réactive re­pré­sente un paradigme de pro­gram­ma­tion moderne. Les actions qui devraient avoir lieu lorsque certains évé­ne­ments se pro­dui­sent sont décrites par un pro­gram­meur. Les re­pré­sen­tants les plus célèbres de ce style de pro­gram­ma­tion sont les struc­tures « React » et « Vue », écrites en Ja­vaS­cript. Chacune de celles-ci se focalise sur la création d’in­ter­faces uti­li­sa­teur basées sur le Web. Avec Quarkus, les ap­pli­ca­tions peuvent être mises en œuvre dans un style impératif et réactif. Il est même possible de combiner les deux pa­ra­digmes.

Où Quarkus est-il utilisé ?

Quarkus a été conçu dans l’optique d’optimiser les ap­pli­ca­tions Java pour qu’elles soient utilisées dans des con­te­neurs et des en­vi­ron­ne­ments Cloud. La pos­si­bi­lité de compiler un programme Java di­rec­te­ment dans du code machine, néanmoins, ouvre des pos­si­bi­li­tés d’ap­pli­ca­tions autrement plus in­té­res­santes. Jetons un œil aux zones d’ap­pli­ca­tion actuelles les plus in­té­res­santes de Quarkus.

Com­men­çons par nous rappeler comment est exécuté un programme Java développé avec Quarkus. Au fil du processus de dé­ve­lop­pe­ment, le code source Java est compilé en bytecode, lequel est ensuite traduit en code machine lorsqu’il est exécuté. Le bytecode peut être exécuté avec Quarkus, qui est ensuite exécuté dans un en­vi­ron­ne­ment d’exécution Java, tel que le HotSpot VM, via in­ter­pré­ta­tion ou com­pi­la­tion à la volée (JIT). Selon la con­fi­gu­ra­tion, diverses op­ti­mi­sa­tions per­ti­nentes sur le plan des per­for­mances entrent en jeu.

D’un autre côté, GraalVM, basé sur HotSpot, peut être utilisé pour générer une image native à l’aide d’une com­pi­la­tion anticipée (AOT). L’image native est un fichier binaire qui contient toutes les bi­blio­thèques et dé­pen­dances né­ces­saires pour exécuter l’ap­pli­ca­tion. Dans la mesure où aucun JVM n’est né­ces­saire pour l’exécution, les gains de per­for­mance les plus im­por­tants sont gagnés via une com­pi­la­tion AOT.

Les ap­pli­ca­tions Java dans les en­vi­ron­ne­ments de conteneur

Ku­ber­netes entre en général en ligne de compte lorsque l’on utilise une appli Java dans des con­te­neurs. On peut également avoir recours à une appli Java packagée comme une image Docker sur un cluster OpenShift. L’uti­li­sa­tion de Quarkus avec Ku­ber­netes peut également être testée par vos soins, par exemple, en passant par l’ins­tal­la­tion de minikube sur votre système local.

Les fonctions Java dans les en­vi­ron­ne­ments sans serveurs

Utilisez Quarkus pour mettre fa­ci­le­ment en place une fonction écrite en Java dans des en­vi­ron­ne­ments sans serveur d’Amazon, Google et Microsoft.

Les pro­grammes Java dans les systèmes intégrés

Compte tenu de la capacité à créer une image native depuis une ap­pli­ca­tion Java, le code Java peut également être utilisé dans les systèmes intégrés. La com­pi­la­tion AOT se révèle utile ici, étant donné qu’elle permet une faible con­som­ma­tion de mémoire et des durées de démarrage rapides pour une ap­pli­ca­tion spé­ci­fique.

Conseil

Utilisez Managed Ku­ber­netes de IONOS pour vos applis basées sur les con­te­neurs.

Quarkus comparé à d’autres struc­tures

Quarkus convient à un vaste éventail de dif­fé­rents scénarios d’ap­pli­ca­tions. D’autres struc­tures sont plus spé­ci­fiques à certains égards. Jetons à un œil à quelques al­ter­na­tives si­mi­laires.

  • React : cette structure Ja­vaS­cript s’est érigée en standard dans le domaine éponyme de la pro­gram­ma­tion réactive.
  • Open Liberty : cette structure d’IBM permet également le dé­ve­lop­pe­ment d’ap­pli­ca­tions de mi­cro­ser­vice avec Java. À l’instar de Quarkus, Open Liberty comprend une fonc­tion­na­lité de re­char­ge­ment à chaud.
  • Micronaut : avec la structure Micronaut, les mi­cro­ser­vices et les ap­pli­ca­tions sans serveurs peuvent être pro­gram­mées dans Java. De même qu’avec Quarkus, GraalVM est utilisé ici.
  • Spring/Spring Boot: Spring est pro­ba­ble­ment la structure Java la plus populaire pour les ap­pli­ca­tions Web. Spring est basé sur GraalVM et, outre la création de mi­cro­ser­vices, il supporte la pro­gram­ma­tion réactive et le re­char­ge­ment à chaud. Si on compare leurs per­for­mances, Quarkus l’emporte sur Spring. Un projet Spring en cours peut être migré vers Quarkus de manière re­la­ti­ve­ment facile.

Quels sont les avantages et les in­con­vé­nients de Quarkus ?

Le principal avantage de dé­ve­lop­per des ap­pli­ca­tions avec Quarkus est le gain en termes de per­for­mances. Ceci revêt une im­por­tance par­ti­cu­lière lorsque l’on a recours à des ap­pli­ca­tions Java dans des en­vi­ron­ne­ments de con­te­neurs. Les bénéfices en termes de per­for­mances com­pren­nent :

  • Une durée de démarrage d’ap­pli­ca­tion rapide
  • Une faible con­som­ma­tion de mémoire par l’ap­pli­ca­tion en cours d’exécution
  • Un éche­lon­nage des services quasi-immédiat
  • Un faible espace né­ces­saire pour les images natives

Outre ses avantages sur le plan des per­for­mances, Quarkus brille plus que tout par son ergonomie. Les dé­ve­lop­peurs habitués à Java EE et Spring peuvent aisément apprendre à utiliser la structure. Ils bé­né­fi­cient également du fait que Quarkus est basé sur une structure solide. Les tech­no­lo­gies standard suivantes sont utilisées, en plus des autres :

  • Eclipse Mi­cro­Pro­file
  • Spring De­pen­dency Injection
  • Hibernate ORM

Quarkus offre également un en­vi­ron­ne­ment de code en ligne, dans lequel les dé­ve­lop­peurs peuvent ra­pi­de­ment créer des pro­to­types. La fonc­tion­na­lité de re­char­ge­ment à chaud contribue à un dé­ve­lop­pe­ment tout en douceur : après avoir activé le mode dev, les chan­ge­ments apportés au code source et à la con­fi­gu­ra­tion sont compilés en arrière-plan. Le dé­ve­lop­peur doit seulement recharger la fenêtre du na­vi­ga­teur pour com­prendre ces chan­ge­ments.

Enfin, nous pouvons conclure avec les in­con­vé­nients d’utiliser Quarkus. Ces derniers con­cer­nent prin­ci­pa­le­ment des op­ti­mi­sa­tions qui entrent en jeu lors de la com­pi­la­tion.

  • En par­ti­cu­lier, réduire les in­for­ma­tions dy­na­miques générées durant l’exécution peut conduire à des problèmes dans le cadre de certains scénarios.
  • Les pos­si­bi­li­tés d’in­tros­pec­tion limitées à l’extrême peuvent rendre difficile le fait de débugger une ap­pli­ca­tion.
  • Le processus hautement optimisé de dé­ve­lop­pe­ment des images natives prend beaucoup de temps.

Quarkus n’a pas été conçu pour le premier projet Java venu. À certains égards, utiliser cette structure nécessite que des processus soient convertis.

Aller au menu principal