Cette année, nous prévoyons de développer sérieusement les thÚmes des conteneurs, et . Une suite logique de ces thÚmes sera le récit du framework Quarkus, déjà sur Habré. L'article d'aujourd'hui n'est pas tant consacré à la structure de la « Java subatomique ultra-rapide », mais plutÎt aux perspectives que Quarkus apporte à l'Enterprise.

Java et la JVM restent extrĂȘmement populaires, mais lors de l'utilisation de technologies sans serveur et de microservices axĂ©s sur le cloud, Java et d'autres langages pour la JVM sont de moins en moins utilisĂ©s, car ils prennent trop de mĂ©moire et se chargent trop lentement, ce qui les rend inadaptĂ©s Ă l'utilisation avec des conteneurs Ă courte durĂ©e de vie. Heureusement, cette situation commence Ă changer grĂące Ă Quarkus.
Java subatomique ultra-rapide a atteint un nouveau niveau !
42 versions, 8 mois de travail communautaire et 177 dĂ©veloppeurs incroyables â tout cela a abouti Ă la sortie en novembre 2019 , une version qui marque une Ă©tape importante dans le dĂ©veloppement du projet et propose de nombreuses fonctionnalitĂ©s intĂ©ressantes (vous pouvez en lire plus Ă propos de cela dans ).
Aujourd'hui, nous allons expliquer comment Quarkus unit les modÚles de programmation impératifs et réactifs sur la base d'un noyau réactif unique. Nous commencerons par un bref aperçu historique, puis nous examinerons en détail en quoi consiste le dualisme du noyau réactif de Quarkus et comment -les développeurs peuvent tirer parti de ces avantages.
, et -les fonctions sont aujourd'hui, ce qu'on appelle, en plein essor. RĂ©cemment, la crĂ©ation d'architectures orientĂ©es vers le cloud est devenue beaucoup plus simple et accessible, mais des dĂ©fis subsistent â surtout pour les dĂ©veloppeurs Java. Par exemple, dans le cas des fonctions serverless et des microservices, il y a un besoin urgent de rĂ©duire le temps de dĂ©marrage, de diminuer l'utilisation de la mĂ©moire et de rendre leur dĂ©veloppement plus pratique et agrĂ©able. Java a fait quelques amĂ©liorations ces derniĂšres annĂ©es, comme l'optimisation du fonctionnement pour les conteneurs et autres. Cependant, faire fonctionner Java correctement dans un conteneur reste difficile. C'est pourquoi nous commencerons par examiner certaines des complexitĂ©s internes de Java, qui se manifestent particuliĂšrement lors du dĂ©veloppement d'applications Java orientĂ©es conteneurs.
Commençons par l'histoire.

Flux et conteneurs
Depuis la version 8u131, Java a commencĂ© Ă supporter les conteneurs grĂące Ă des amĂ©liorations fonctionnalitĂ© ergonomique. En particulier, la JVM sait dĂ©sormais sur combien de cĆurs de processeur elle s'exĂ©cute et peut configurer les pools de threads en consĂ©quence - gĂ©nĂ©ralement des pools fork/join. C'est formidable, mais supposons que nous ayons une application Web traditionnelle utilisant des servlets HTTP et s'exĂ©cutant sous Tomcat, Jetty, etc. En consĂ©quence, cette application attribuera un thread distinct Ă chaque requĂȘte et lui permettra de bloquer ce thread en attendant des opĂ©rations d'entrĂ©e-sortie, comme lors de l'accĂšs Ă une base de donnĂ©es, Ă des fichiers ou Ă d'autres services. Cela signifie que la taille de cette application ne dĂ©pend pas du nombre de cĆurs disponibles, mais du nombre de requĂȘtes simultanĂ©es. De plus, cela signifie que les quotas ou limites dans Kubernetes concernant le nombre de cĆurs ne seront pas vraiment utiles ici, et que le rĂ©sultat final sera un throttling.
Ăpuisement de la mĂ©moire
Les threads sont de la mĂ©moire. Et les limitations de mĂ©moire Ă l'intĂ©rieur des conteneurs ne sont pas une panacĂ©e. Commencez simplement Ă augmenter le nombre d'applications et de threads, et tĂŽt ou tard vous rencontrerez une augmentation critique de la frĂ©quence des commutations et, par consĂ©quent, une dĂ©gradation des performances. De plus, si l'application utilise des frameworks de microservices traditionnels ou se connecte Ă une base de donnĂ©es, ou utilise le cache, ou consomme de la mĂ©moire d'une autre maniĂšre, vous avez absolument besoin d'un outil qui vous permet de voir Ă l'intĂ©rieur de la JVM et de comprendre comment elle gĂšre la mĂ©moire, sans pour autant tuer la JVM elle-mĂȘme (par exemple, XX:+UseCGroupMemoryLimitForHeap). Et mĂȘme si, depuis Java 9, la JVM a appris Ă reconnaĂźtre les cgroups et Ă s'adapter en consĂ©quence, la rĂ©servation et la gestion de la mĂ©moire restent des tĂąches assez complexes.
Quotas et limites
Java 11 a introduit le support des quotas CPU (comme PreferContainerQuotaForCPUCount). Kubernetes propose Ă©galement un support pour les limites et quotas. Oui, tout cela a du sens, mais si l'application sort Ă nouveau des limites allouĂ©es, nous revenons Ă la situation oĂč la taille - comme avec les applications Java traditionnelles - est dĂ©terminĂ©e par le nombre de cĆurs avec un thread sĂ©parĂ© allouĂ© Ă chaque requĂȘte, donc tout cela n'est pas d'une grande utilitĂ©.
De plus, si l'on utilise des quotas et des limites ou des fonctions de mise Ă l'Ă©chelle horizontale (scale-out) de la plateforme sous-jacente de Kubernetes, le problĂšme ne se rĂ©sout pas de lui-mĂȘme. Nous dĂ©pensons simplement plus de ressources pour rĂ©soudre le problĂšme initial ou finissons par un surconsommation des ressources. Et si c'est un systĂšme trĂšs chargĂ© dans un cloud public accessible au public, nous commençons presque certainement Ă utiliser plus de ressources que nĂ©cessaire.
Et que faire avec tout cela ?
Pour faire simple, il faut utiliser des bibliothĂšques et des frameworks d'entrĂ©e-sortie asynchrones et non bloquants, comme Netty, ou Akka. Ils conviennent beaucoup mieux au travail dans des conteneurs en raison de leur nature rĂ©active. GrĂące Ă l'entrĂ©e-sortie non bloquante, un mĂȘme thread peut traiter plusieurs requĂȘtes simultanĂ©ment. Pendant qu'une requĂȘte attend des rĂ©sultats d'entrĂ©e-sortie, le thread qui la traite est libĂ©rĂ© et s'occupe d'une autre requĂȘte. Et lorsque les rĂ©sultats d'entrĂ©e-sortie arrivent enfin, le traitement de la premiĂšre requĂȘte se poursuit. En alternant le traitement des requĂȘtes dans un mĂȘme thread, on peut rĂ©duire le nombre total de threads et diminuer la consommation de ressources liĂ©e au traitement des requĂȘtes.
Avec l'entrĂ©e-sortie non bloquante, le nombre de cĆurs devient un paramĂštre clĂ©, car c'est ce qui dĂ©termine le nombre de threads d'entrĂ©e-sortie qui peuvent s'exĂ©cuter en parallĂšle. Lorsque cela est utilisĂ© correctement, cela permet de rĂ©partir efficacement la charge entre les cĆurs et de gĂ©rer des charges plus Ă©levĂ©es avec moins de ressources.
Comment, c'est tout ?
Non, il y a encore autre chose. La programmation rĂ©active aide Ă mieux utiliser les ressources, mais cela a aussi un coĂ»t. En particulier, le code devra ĂȘtre réécrit selon les principes de non-bloquage, et il faudra Ă©viter le blocage des threads d'entrĂ©e-sortie. C'est un tout autre modĂšle de dĂ©veloppement et d'exĂ©cution. Et bien qu'il existe un grand nombre de bibliothĂšques utiles, cela reprĂ©sente tout de mĂȘme un changement radical de la façon de penser habituelle.
Tout d'abord, vous devez apprendre à écrire du code qui s'exécute de maniÚre asynchrone. DÚs que vous commencez à utiliser des entrées-sorties non bloquantes, vous devez spécifier clairement ce qui doit se passer lors de la réception d'une réponse à la demande. Il n'est plus possible de bloquer et d'attendre. En revanche, vous pouvez passer des rappels, utiliser la programmation réactive ou des continuations. Mais ce n'est pas tout : pour utiliser des entrées-sorties non bloquantes, vous avez besoin de serveurs et de clients non bloquants, de préférence partout. Dans le cas de HTTP, c'est simple, mais il y a aussi des bases de données, des systÚmes de fichiers et bien d'autres choses.
Et bien que la rĂ©activitĂ© totale et intĂ©grale offre un maximum d'efficacitĂ©, ce changement peut ĂȘtre difficile Ă digĂ©rer en pratique. C'est pourquoi la possibilitĂ© de combiner code rĂ©actif et impĂ©ratif devient une condition nĂ©cessaire pour :
- Utiliser efficacement les ressources dans les domaines les plus sollicités du systÚme logiciel ;
- Utiliser un code au style plus simple dans ses autres parties.
Découvrez Quarkus
En rĂ©alitĂ©, c'est lĂ toute la philosophie de Quarkus â unir les modĂšles rĂ©actif et impĂ©ratif dans le cadre d'un mĂȘme environnement d'exĂ©cution.
Au cĆur de Quarkus se trouvent Vert.x et Netty, sur lesquels repose une sĂ©rie de frameworks et d'extensions rĂ©actifs conçus pour aider le dĂ©veloppeur. Quarkus est destinĂ© Ă la construction non seulement de microservices HTTP, mais aussi d'architectures pilotĂ©es par des Ă©vĂ©nements. GrĂące Ă sa nature rĂ©active, il fonctionne trĂšs efficacement avec des systĂšmes de messagerie (Apache Kafka, AMQP, etc.).
Tout le secret rĂ©side dans la maniĂšre d'utiliser le mĂȘme moteur rĂ©actif pour le code impĂ©ratif et le code rĂ©actif.

Quarkus s'en occupe brillamment. Le choix entre une approche impĂ©rative et rĂ©active est Ă©vident : utiliser un noyau rĂ©actif pour les deux. Et ce sur quoi il aide beaucoup, câest le code non bloquant rapide qui traite presque tout ce qui passe par le thread de la boucle d'Ă©vĂ©nements (event-loop thread, aussi appelĂ© IO thread). Mais si vous avez des applications REST classiques ou des applications cĂŽtĂ© client, Quarkus est prĂȘt avec un modĂšle de programmation impĂ©ratif. Par exemple, le support HTTP dans Quarkus est construit sur l'utilisation d'un moteur non bloquant et rĂ©actif (Eclipse Vert.x et Netty). Toutes les requĂȘtes HTTP reçues par votre application passent d'abord par la boucle d'Ă©vĂ©nements (IO Thread), puis sont envoyĂ©es Ă la partie du code qui gĂšre les requĂȘtes. Selon la destination, le code de gestion des requĂȘtes peut ĂȘtre appelĂ© dans un thread sĂ©parĂ© (le soi-disant worker thread, utilisĂ© dans le cas des servlets et Jax-RS) ou utiliser le thread d'entrĂ©e-sortie d'origine (le chemin rĂ©actif).

Pour les connecteurs des systÚmes de transmission de messages, des clients non bloquants sont utilisés, fonctionnant sur le moteur Vert.x. Vous pouvez donc envoyer, recevoir et traiter efficacement des messages depuis des systÚmes de type middleware de messaging.
Sur le site plusieurs bons guides ont été rassemblés pour vous aider à démarrer avec Quarkus :
De plus, nous avons prĂ©parĂ© des cours pratiques en ligne pour dĂ©couvrir divers aspects de la programmation rĂ©active, et pour les suivre, il suffit d'un navigateur, aucune IDE n'est nĂ©cessaire, et mĂȘme un ordinateur n'est pas obligatoire. Vous pouvez trouver ces cours .
Ressources utiles
- Le site du projet Quarkus â
- Le projet Quarkus sur GitHub â
- Le Twitter du projet Quarkus â
- Le chat du projet Quarkus â
- Les forums du projet Quarkus â !forum/quarkus-dev
10 tutoriels vidéo sur Quarkus pour se familiariser avec le sujet
Comme indiquĂ© sur le site , â c'est - une pile Java orientĂ©e, optimisĂ©e pour GraalVM et OpenJDK HotSpot, assemblĂ©e Ă partir des meilleures bibliothĂšques et standards Java.
Pour vous aider à comprendre le sujet, nous avons sélectionné 10 tutoriels vidéo qui couvrent divers aspects de Quarkus et des exemples d'utilisation :
1. Présentation de Quarkus : framework Java de nouvelle génération pour Kubernetes
Auteurs : Thomas Qvarnstrom et Jason Greene
L'objectif du projet Quarkus est de créer une plateforme Java pour Kubernetes et les environnements serverless, tout en combinant les modÚles de programmation réactifs et impératifs dans un seul environnement d'exécution, permettant aux développeurs de varier flexiblement leur approche dans un large éventail d'architectures d'applications distribuées. En savoir plus dans la conférence d'introduction ci-dessous.

2. Quarkus : java subatomique ultra-rapide
Auteur : Burr Sutter
Le tutoriel vidéo du séminaire en ligne DevNation Live montre comment utiliser Quarkus pour optimiser les applications Java d'entreprise, APIs, microservices et fonctions serverless dans un environnement Kubernetes/OpenShift, les rendant beaucoup plus petites, plus rapides et évolutives.

3. Quarkus et GraalVM : propulsons Hibernate Ă des vitesses extrĂȘmes et rĂ©duisons-le Ă des tailles subatomiques
Auteur : Sanne Grinovero
Dans cette présentation, vous découvrirez comment Quarkus a été développé, comment il fonctionne et comment il rend compatibles des bibliothÚques complexes comme Hibernate ORM avec les images natives de GraalVM.

4. Apprenons à développer des applications serverless
Auteur : Marthen Luther
La vidéo ci-dessous montre comment créer une simple application Java avec Quarkus et la déployer en tant qu'application serverless sur Knative.

5. Quarkus : codez avec plaisir
Auteur : Edson Yanaga
Un guide vidéo pour créer votre premier projet Quarkus, permettant de comprendre pourquoi Quarkus séduit les développeurs.

6. Java et conteneurs â quel sera leur avenir commun ?
Auteur : Mark Little
Cette présentation présente l'histoire de Java et explique pourquoi Quarkus est l'avenir de Java.

7. Quarkus : java subatomique ultra-rapide
Auteur : Dimitris Andreadis
Aperçu des avantages de Quarkus qui ont été reconnus par les développeurs : simplicité, vitesses ultra-rapides, meilleures bibliothÚques et normes.

8. Quarkus et systÚmes réactifs subatomiques
Auteur : Clement Escoffier
Grùce à l'intégration avec GraalVM, Quarkus offre une expérience de développement ultra-rapide et un environnement d'exécution subatomique. L'auteur parle de l'aspect réactif de Quarkus et de la façon de l'utiliser pour créer des applications réactives et des applications de streaming.

9. Quarkus et développement rapide d'applications dans Eclipse MicroProfile
Auteur : John Clingan
En combinant Eclipse MicroProfile et Quarkus, les développeurs peuvent créer des applications conteneurisées MicroProfile entiÚrement fonctionnelles, qui se lancent en quelques dizaines de millisecondes. La vidéo explique en détail comment coder une application conteneurisée MicroProfile pour un déploiement sur la plateforme Kubernetes.

10. Java, version « Turbo »
Auteur : Marcus Biel
L'auteur montre comment utiliser Quarkus pour créer des conteneurs Java super petits et super rapides, permettant de réaliser une véritable percée, notamment dans les environnements sans serveur.

Source : habr.com
