Comment Quarkus combine la programmation impérative et réactive

Cette année, nous prévoyons de développer sérieusement des thèmes de conteneurs, Cloud-Native Java et Kubernetes . Une suite logique de ces sujets sera l'histoire du framework Quarkus, déjà envisagée sur Habré. L'article d'aujourd'hui se concentre non pas tant sur le «périphérique Java ultrarapide subatomique» que sur les perspectives que Quarkus apporte à Enterprise. (Soit dit en passant, inscrivez-vous et accédez à notre webinaire « This is Quarkus - Kubernetes native Java framework », qui se tiendra le 27 mai. Nous montrerons comment repartir de zéro ou transférer des solutions toutes faites)



Java et la JVM sont toujours extrêmement populaires, mais lorsque vous travaillez avec des technologies sans serveur et des microservices orientés cloud, Java et d'autres langages pour la JVM sont de moins en moins utilisés, car ils occupent trop d'espace mémoire et se chargent trop lentement, ce qui les rend inappropriés pour utiliser avec des conteneurs de courte durée. Heureusement, cette situation commence actuellement à changer grâce à Quarkus.

Java subatomique ultrarapide a atteint un nouveau niveau!


42 versions, 8 mois de travail communautaire et 177 développeurs incroyables - le résultat de tout a été la sortie en novembre 2019 de Quarkus 1.0 , une version qui marque une étape importante dans le développement du projet et offre de nombreuses fonctionnalités et capacités intéressantes (vous en trouverez plus à ce sujet dans l' annonce ) .

Aujourd'hui, nous expliquerons comment Quarkus combine des modèles de programmation impératifs et réactifs basés sur un seul cœur réactif. Nous commençons par un bref historique, puis examinons de plus près à quoi réagit le double cœur de Quarkus et comment les développeurs Java peuvent en tirer parti.

Mikroservisy , architecture événementielle et sans serveur-fonctions - tout cela aujourd'hui, comme on dit, est en augmentation. Récemment, la création d'architectures basées sur le cloud est devenue beaucoup plus simple et plus abordable, mais des problèmes persistent - en particulier pour les développeurs Java. Par exemple, dans le cas des fonctions sans serveur et des microservices, il est urgent de réduire le temps de démarrage, de réduire la consommation de mémoire et de rendre leur développement plus pratique et plus agréable. Ces dernières années, Java a apporté plusieurs améliorations, telles que la fonctionnalité d'ergonomie modifiée pour les conteneurs, etc. Cependant, faire fonctionner Java dans le conteneur n'est toujours pas facile. Par conséquent, nous commencerons par examiner certaines des complexités intrinsèques de Java, qui sont particulièrement aiguës lors du développement d'applications Java orientées conteneurs.

Commençons d'abord par l'histoire.


Streams et conteneurs


À partir de la version 8u131, Java dispose de conteneurs plus ou moins pris en charge en raison de l'amélioration des fonctionnalités ergonomiques. En particulier, la JVM sait maintenant combien de cœurs de processeur elle exécute et peut configurer correctement les pools de threads - généralement les pools de fork / join. Bien sûr, c'est génial, mais disons que nous avons une application Web traditionnelle qui utilise des servlets HTTP et s'exécute sur Tomcat, Jetty, etc. Par conséquent, cette application donnera à chaque demande un flux distinct et lui permettra de bloquer ce flux en attendant les opérations d'E / S, par exemple, lors de l'accès à une base de données, des fichiers ou d'autres services. Autrement dit, la taille d'une telle application ne dépend pas du nombre de cœurs disponibles, mais du nombre de demandes simultanées. En outre, cela signifie que les quotas ou les limites dans Kubernetes par le nombre de cœurs ne seront pas particulièrement utiles ici,et l'accord se terminera au trot.

Manque de mémoire


Les flux sont de la mémoire. Et les restrictions de mémoire intra-conteneur ne sont en aucun cas 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 de commutation et, par conséquent, une dégradation des performances. De plus, si l'application utilise des infrastructures de microservices traditionnelles ou se connecte à la base de données, ou utilise la mise en cache, ou consomme en outre de la mémoire, vous avez absolument besoin d'un outil qui vous permet de regarder à l'intérieur de la JVM et de voir comment elle gère la mémoire, et de ne pas tuer JVM elle-même (par exemple XX: + UseCGroupMemoryLimitForHeap). Et même en dépit du fait qu'à partir de Java 9, la JVM a appris à accepter les cgroups et à s'adapter en conséquence, la sauvegarde et la gestion de la mémoire restent une affaire assez compliquée.

Quotas et limites


Java 11 a introduit la prise en charge des quotas de processeur (comme PreferContainerQuotaForCPUCount). Kubernetes propose également une prise en charge des limites et des quotas. Oui, tout cela a du sens, mais si l'application dépasse à nouveau le quota alloué, nous arrivons à nouveau à la conclusion que la taille - comme c'est le cas avec les applications Java traditionnelles - est déterminée par le nombre de cœurs et l'allocation d'un thread séparé pour chaque demande, puis il y a peu de sens dans tout cela.
En outre, si vous utilisez des quotas et des limites ou des fonctions de mise à l'échelle horizontale (scale-out) de la plate-forme qui sous-tend Kubernetes, le problème ne se résout pas lui-même. Nous dépensons simplement plus de ressources pour résoudre le problème d'origine ou, par conséquent, nous finissons par utiliser des ressources. Et s'il s'agit d'un système très chargé dans un cloud public et public, nous commencerons presque certainement à utiliser plus de ressources qu'il n'en a réellement besoin.

Et que faire de tout ça?


Si de manière simple, utilisez des bibliothèques d'E / S asynchrones et non bloquantes et des cadres comme Netty, Vert.x ou Akka. Ils sont beaucoup mieux adaptés pour travailler en conteneurs en raison de leur nature réactive. Grâce aux E / S non bloquantes, le même thread peut traiter plusieurs requêtes simultanées à la fois. Pendant qu'une requête attend les résultats d'E / S, son thread de traitement est libéré et pris pour une autre requête. Et lorsque les résultats d'E / S arrivent enfin, le traitement de la première demande se poursuit. En alternant le traitement des demandes dans le même flux, vous pouvez réduire le nombre total de threads et réduire la consommation de ressources pour le traitement des demandes.

Avec des E / S non bloquantes, le nombre de cœurs devient un paramètre clé, car il détermine le nombre de threads d'E / S pouvant s'exécuter en parallèle. Lorsqu'il est utilisé correctement, cela vous permet de répartir efficacement la charge entre les cœurs et de faire face à des charges plus élevées avec moins de ressources.

Comment et c'est tout?


Non, il y a encore une chose. La programmation réactive permet de mieux utiliser les ressources, mais a également un prix. En particulier, le code devra être réécrit selon les principes de non-blocage et éviter de bloquer les flux d'entrée-sortie. Et c'est un modèle de développement et de mise en œuvre complètement différent. Et bien qu'il existe de nombreuses bibliothèques utiles, il s'agit toujours d'un changement fondamental dans 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 E / S non bloquantes, vous devez explicitement prescrire ce qui doit se produire lorsque vous recevez une réponse à la demande. Le blocage et l'attente échoueront. En retour, vous pouvez passer des rappels, utiliser une programmation réactive ou une continuation. Mais ce n'est pas tout: pour utiliser des E / S non bloquantes, vous avez besoin à la fois de serveurs et de clients non bloquants, et de préférence partout. Dans le cas de HTTP, tout est simple, mais il y a aussi une base de données, des systèmes de fichiers et bien plus encore.

Bien que la réactivité totale de bout en bout donne une efficacité maximale, un tel changement peut être difficile à digérer dans la pratique. Par conséquent, la capacité de combiner du code réactif et impératif devient une condition nécessaire pour:

  1. Utiliser efficacement les ressources dans les zones les plus chargées du système logiciel;
  2. Utilisez un code de style plus simple dans ses autres parties.

Présentation de Quarkus


En fait, c'est l'essence de Quarkus - combiner des modèles réactifs et impératifs dans un environnement d'exécution.

Quarkus est basé sur Vert.x et Netty, en plus desquels un certain nombre de frameworks réactifs et d'extensions sont utilisés pour aider le développeur. Quarkus est conçu pour construire non seulement des microservices HTTP, mais également des architectures événementielles. De par sa nature réactive, il fonctionne très efficacement avec les systèmes de messagerie (Apache Kafka, AMQP, etc.).

L'astuce consiste à utiliser le même moteur à réaction pour le code impératif et réactif.



Quarkus le fait avec brio. Le choix entre impératif et réactif est évident - utiliser à la fois l'un et l'autre noyau réactif. Et avec ce que cela aide beaucoup, c'est avec un code non bloquant rapide qui traite presque tout ce qui passe par le thread de boucle d'événement (thread de boucle d'événement, alias thread IO). Mais si vous avez des applications REST classiques ou côté client, Quarkus est prêt pour un modèle de programmation impératif. Par exemple, la prise en charge HTTP dans Quarkus est basée sur l'utilisation d'un moteur à réaction et non bloquant (Eclipse Vert.x et Netty). Toutes les demandes HTTP reçues par votre application passent d'abord par la boucle d'événements (thread IO), puis elles sont envoyées à la partie du code qui gère les demandes.Selon la destination, le code de contrôle de la demande peut être appelé dans un thread séparé (le soi-disant thread de travail, utilisé dans le cas des servlets et Jax-RS) ou utiliser le flux d'entrée-sortie d'origine (route réactive route réactive).



Les clients non bloquants travaillant au-dessus du moteur Vert.x sont utilisés pour les connecteurs des systèmes de messagerie. Par conséquent, vous pouvez envoyer, recevoir et traiter efficacement des messages à partir de systèmes de classe middleware de messagerie.

Le site Quarkus.io a rassemblé quelques bonnes directives pour vous aider à démarrer avec Quarkus:


De plus, nous avons préparé des leçons pratiques en ligne pour vous familiariser avec divers aspects de la programmation réactive, de plus, un simple navigateur suffit pour les compléter, aucun IDE n'est requis pour cela et un ordinateur n'est pas nécessaire. Retrouvez ces leçons ici .

Ressources utiles




10 tutoriels vidéo Quarkus pour vous familiariser avec le sujet


Selon le site Web Quarkus.io , Quarkus est une pile Java orientée Kubernetes conçue pour GraalVM et OpenJDK HotSpot et compilée à partir des meilleures bibliothèques et normes Java.

Pour vous aider à comprendre le sujet, nous avons sélectionné 10 didacticiels vidéo qui couvrent divers aspects de Quarkus et des exemples de son utilisation:

1. Présentation de Quarkus: le 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 plate-forme Java pour Kubernetes et les environnements sans serveur, et de combiner des modèles de programmation réactifs et impératifs en un seul runtime afin que les développeurs pourrait varier de manière flexible l'approche lorsque vous travaillez avec un large éventail d'architectures d'applications distribuées. Apprenez-en plus dans la leçon d'introduction ci-dessous.



2. Quarkus: Java subatomique ultrarapide


Auteur: Burr Sutter Un
didacticiel vidéo de la conférence en ligne DevNation Live montre comment utiliser Quarkus pour optimiser les applications Java d'entreprise, les API, les microservices et les fonctionnalités sans serveur dans Kubernetes / OpenShift, ce qui les rend beaucoup plus petits, plus rapides et plus évolutifs.



3. Quarkus et GraalVM: nous accélérons Hibernate à de super vitesses et nous nous plaçons à des tailles subatomiques


Auteur: Sane Grinovero
À partir de la présentation, vous apprendrez comment Quarkus est apparu, comment il fonctionne et comment il vous permet de rendre des bibliothèques complexes comme Hibernate ORM compatibles avec les images natives GraalVM.



4. Apprendre à développer des applications sans serveur


Publié par Marthen Luther
La vidéo ci-dessous montre comment créer une application Java simple à l'aide de Quarkus et la déployer en tant qu'application sans serveur sur Knative.



5. Quarkus: coder avec plaisir


Publié par Edson Yanaga
Wideguide pour créer votre premier projet Quarkus afin de comprendre pourquoi Quarkus gagne le cœur des développeurs.



6. Java et conteneurs - quel sera leur avenir commun


Publié par Mark Little
Cette présentation présente l'histoire de Java et explique pourquoi Quarkus est l'avenir de Java.



7. Quarkus: Java subatomique ultrarapide


Auteur: Dimitris Andreadis Dimitris Andreadis
Un aperçu des développeurs acclamés de Quarkus: simplicité, vitesses ultra-rapides, meilleures bibliothèques et normes.



8. Quarkus et systèmes réactifs subatomiques


Publié par Clement Escoffier
Grâce à l'intégration avec GraalVM, Quarkus offre une expérience de développement ultra-rapide et un runtime subatomique. L'auteur parle du côté réactif de Quarkus et comment l'utiliser lors de la création d'applications réactives et d'applications de streaming.



9. Quarkus et développement rapide d'applications chez Eclipse MicroProfile


Publié par John Clingan En
combinant Eclipse MicroProfile et Quarkus, les développeurs peuvent créer des applications de conteneur MicroProfile entièrement fonctionnelles qui s'exécutent en quelques dizaines de millisecondes. La vidéo explique comment coder l'application conteneur MicroProfile pour le déploiement sur la plate-forme Kubernetes.



10. Java, version Turbo


Publié par Marcus Biel
L'auteur montre comment utiliser Quarkus pour créer des conteneurs Java super petits et super rapides pour une véritable percée, en particulier dans les environnements sans serveur.


All Articles