Hoe Quarkus imperatief en reactief programmeren combineert

Dit jaar zijn we van plan containerthema's serieus te ontwikkelen, Cloud-native Java и Kubernetes. Een logisch vervolg op deze onderwerpen zal al een verhaal over het Quarkus-framework zijn beschouwd op Habré. Het artikel van vandaag gaat minder over het ontwerp van "subatomair supersnel Java" en meer over de belofte die Quarkus naar Enterprise brengt.

Hoe Quarkus imperatief en reactief programmeren combineert

Java en de JVM zijn nog steeds enorm populair, maar bij het werken met serverloze technologieën en cloud-native microservices worden Java en andere JVM-talen steeds minder gebruikt omdat ze te veel geheugenruimte in beslag nemen en te traag zijn om te laden, waardoor ze slecht geschikt voor gebruik met containers met een korte levensduur. Gelukkig begint deze situatie nu te veranderen dankzij Quarkus.

Supersnel subatomair Java heeft een nieuw niveau bereikt!

42 releases, 8 maanden gemeenschapswerk en 177 geweldige ontwikkelaars - het resultaat van dit alles was de release in november 2019 Quarkus 1.0, een release die een belangrijke mijlpaal markeert in de ontwikkeling van het project en veel coole functies en mogelijkheden biedt (je kunt er meer over lezen in Aankondiging).

Vandaag laten we u zien hoe Quarkus imperatieve en reactieve programmeermodellen combineert in één enkele reactieve kern. We beginnen met een korte geschiedenis en gaan dan in detail in op wat het reactieve kerndualisme van Quarkus is en hoe Java-Ontwikkelaars kunnen profiteren van deze voordelen.

Microdiensten, gebeurtenisgestuurde architecturen и serverless-functies – dit alles is, zoals ze zeggen, vandaag de dag in opkomst. De laatste tijd is het creëren van cloudgerichte architecturen veel eenvoudiger en toegankelijker geworden, maar er blijven problemen bestaan, vooral voor Java-ontwikkelaars. In het geval van serverloze functies en microservices is er bijvoorbeeld een dringende behoefte om de opstarttijd te verkorten, het geheugengebruik te verminderen en de ontwikkeling ervan toch handiger en leuker te maken. Java heeft de afgelopen jaren verschillende verbeteringen aangebracht, zoals verbeterde ergonomiefunctionaliteit voor containers enzovoort. Het is echter nog steeds een uitdaging om Java goed te laten werken in een container. We beginnen dus met het bekijken van enkele van de inherente complexiteiten van Java, die vooral acuut zijn bij het ontwikkelen van containergeoriënteerde Java-applicaties.

Laten we eerst eens naar de geschiedenis kijken.

Hoe Quarkus imperatief en reactief programmeren combineert

Beken en containers

Vanaf versie 8u131 begon Java containers min of meer te ondersteunen vanwege verbeteringen in de ergonomische functionaliteit. In het bijzonder weet de JVM nu op hoeveel processorkernen hij draait en kan hij threadpools (meestal fork/join-pools) dienovereenkomstig configureren. Dit is natuurlijk geweldig, maar laten we zeggen dat we een traditionele webapplicatie hebben die HTTP-servlets gebruikt en draait in Tomcat, Jetty, enz. Als gevolg hiervan zal deze applicatie elk verzoek een aparte thread geven en deze thread laten blokkeren tijdens het wachten op I/O-bewerkingen, bijvoorbeeld bij toegang tot de database, bestanden of andere services. Dat wil zeggen dat de grootte van een dergelijke applicatie niet afhankelijk is van het aantal beschikbare cores, maar van het aantal gelijktijdige verzoeken. Bovendien betekent dit dat quota of limieten in Kubernetes op het aantal cores hier niet veel zullen helpen, en dat de zaak uiteindelijk zal eindigen in throttling.

Geheugenuitputting

Draden zijn geheugen. En geheugenbeperkingen binnen containers zijn geenszins een wondermiddel. Begin gewoon met het vergroten van het aantal applicaties en threads, en vroeg of laat zul je te maken krijgen met een kritische toename van de schakelfrequentie en, als gevolg daarvan, prestatievermindering. En als uw applicatie traditionele microserviceframeworks gebruikt, verbinding maakt met een database, caching gebruikt of op een andere manier geheugen in beslag neemt, heeft u uiteraard een tool nodig waarmee u in de JVM kunt kijken en kunt zien hoe deze het geheugen beheert zonder het te doden. JVM zelf (bijvoorbeeld XX:+UseCGroupMemoryLimitForHeap). En hoewel de JVM sinds Java 9 heeft geleerd cgroups te accepteren en zich dienovereenkomstig aan te passen, blijft het reserveren en beheren van geheugen een tamelijk complexe zaak.

Quota en limieten

Java 11 introduceerde ondersteuning voor CPU-quota (zoals PreferContainerQuotaForCPUCount). Kubernetes biedt ook ondersteuning voor limieten en quota. Ja, dit is allemaal logisch, maar als de applicatie opnieuw het toegewezen quotum overschrijdt, eindigen we opnieuw met de grootte - zoals het geval is bij traditionele Java-applicaties - bepaald door het aantal cores en met de toewijzing van een aparte thread voor elke kern. verzoek, dan heeft dit alles weinig zin.
Als je bovendien gebruik maakt van quota's en limieten of van de scale-out-functies van het onderliggende platform van Kubernetes, lost het probleem zich ook niet vanzelf op. We besteden eenvoudigweg meer middelen aan het oplossen van het oorspronkelijke probleem, anders geven we uiteindelijk te veel uit. En als het een zwaarbelast systeem in een openbare cloud betreft, gebruiken we vrijwel zeker meer bronnen dan we werkelijk nodig hebben.

En wat te doen met dit alles?

Simpel gezegd: gebruik asynchrone en niet-blokkerende I/O-bibliotheken en frameworks zoals Netty, Vert.x of Akka. Ze zijn veel beter geschikt om in containers te werken vanwege hun reactieve karakter. Dankzij niet-blokkerende I/O kan dezelfde thread meerdere gelijktijdige verzoeken verwerken. Terwijl één verzoek wacht op I/O-resultaten, wordt de thread die het verzoek verwerkt vrijgegeven en overgenomen door een ander verzoek. En wanneer de I/O-resultaten eindelijk binnenkomen, gaat de verwerking van het eerste verzoek door. Door verzoeken binnen dezelfde thread interleaved te verwerken, kunt u het totale aantal threads verminderen en het resourceverbruik voor het verwerken van verzoeken verminderen.

Met niet-blokkerende I/O wordt het aantal cores een sleutelparameter, omdat het het aantal I/O-threads bepaalt dat parallel kan worden uitgevoerd. Wanneer u dit op de juiste manier gebruikt, kunt u de belasting effectief over de kernen verdelen en hogere werklasten aan met minder middelen.

Hoe, is dat alles?

Nee, er is nog iets. Reactief programmeren helpt om hulpbronnen beter te gebruiken, maar heeft ook een prijs. In het bijzonder zal de code moeten worden herschreven volgens de principes van non-blocking en moet het blokkeren van I/O-threads worden vermeden. En dit is een heel ander model van ontwikkeling en uitvoering. En hoewel er hier veel nuttige bibliotheken zijn, is het nog steeds een radicale verandering in de gebruikelijke manier van denken.

Eerst moet u leren hoe u code schrijft die asynchroon wordt uitgevoerd. Zodra u niet-blokkerende I/O gaat gebruiken, moet u expliciet specificeren wat er moet gebeuren als er een antwoord op een verzoek wordt ontvangen. Simpelweg blokkeren en wachten werkt niet meer. In plaats daarvan kunt u terugbellen doorgeven, reactief programmeren of doorgaan. Maar dat is nog niet alles: om niet-blokkerende I/O te gebruiken, heb je zowel niet-blokkerende servers als clients nodig, bij voorkeur overal. In het geval van HTTP is alles eenvoudig, maar er zijn ook databases, bestandssystemen en nog veel meer.

En hoewel totale end-to-end-reactiviteit de efficiëntie maximaliseert, kan een dergelijke verschuiving in de praktijk moeilijk te verdragen zijn. Daarom wordt het vermogen om reactieve en imperatieve code te combineren een vereiste om:

  1. Effectief gebruik maken van bronnen in de meest belaste gebieden van het softwaresysteem;
  2. Gebruik eenvoudigere stijlcode in de overige delen.

Maak kennis met Quarkus

Eigenlijk is dit de essentie van Quarkus: reactieve en imperatieve modellen combineren binnen één runtime-omgeving.

Quarkus is gebaseerd op Vert.x en Netty, met daarbovenop een reeks reactieve frameworks en extensies om de ontwikkelaar te helpen. Quarkus is niet alleen ontworpen voor het bouwen van HTTP-microservices, maar ook voor gebeurtenisgestuurde architecturen. Vanwege het reactieve karakter werkt het zeer effectief met berichtensystemen (Apache Kafka, AMQP, enz.).

De truc is om dezelfde reactieve engine te gebruiken voor zowel imperatieve als reactieve code.

Hoe Quarkus imperatief en reactief programmeren combineert

Quarkus doet dit op briljante wijze. De keuze tussen imperatief en reactief ligt voor de hand: gebruik voor beide een reactieve kernel. Waar het echt mee helpt is snelle, niet-blokkerende code die bijna alles afhandelt wat door de event-loop-thread gaat, ook wel IO-thread genoemd. Maar als je klassieke REST- of client-side applicaties hebt, heeft Quarkus een imperatief programmeermodel klaarstaan. HTTP-ondersteuning in Quarkus is bijvoorbeeld gebaseerd op het gebruik van een niet-blokkerende en reactieve engine (Eclipse Vert.x en Netty). Alle HTTP-verzoeken die door uw applicatie worden ontvangen, worden eerst door een gebeurtenislus (IO Thread) geleid en vervolgens verzonden naar het deel van de code dat de verzoeken beheert. Afhankelijk van de bestemming kan de request management code binnen een aparte thread worden aangeroepen (de zogenaamde worker thread, gebruikt in het geval van servlets en Jax-RS) of de source I/O thread gebruiken (reactieve route).

Hoe Quarkus imperatief en reactief programmeren combineert

Messaging-systeemconnectors gebruiken niet-blokkerende clients die bovenop de Vert.x-engine draaien. Daarom kunt u effectief berichten verzenden, ontvangen en verwerken vanuit messaging-middlewaresystemen.

De site Quarkus.io Hier zijn enkele goede tutorials om u op weg te helpen met Quarkus:

We hebben ook online praktische tutorials gemaakt om u verschillende aspecten van reactief programmeren te leren, in slechts een browser, zonder IDE en zonder computer. Deze lessen kun je vinden hier.

Handige hulpmiddelen

10 videolessen over Quarkus om vertrouwd te raken met het onderwerp

Zoals ze op de website zeggen Quarkus.io, kwark - is Kubernetes-georiënteerde Java-stack, op maat gemaakt voor GraalVM en OpenJDK HotSpot en samengesteld uit de beste Java-bibliotheken en standaarden.

Om u te helpen het onderwerp te begrijpen, hebben we 10 video-tutorials geselecteerd die verschillende aspecten van Quarkus behandelen en voorbeelden van het gebruik ervan:

1. Introductie van Quarkus: het Java-framework van de volgende generatie voor Kubernetes

Door Thomas Qvarnstrom en Jason Greene
Het doel van het Quarkus-project is om een ​​Java-platform te creëren voor Kubernetes en serverloze omgevingen, en om reactieve en imperatieve programmeermodellen te combineren in één enkele runtime-omgeving, zodat ontwikkelaars hun aanpak flexibel kunnen variëren bij het werken met een breed scala aan gedistribueerde applicatie-architecturen. Lees er meer over in onderstaande inleidende lezing.

2. Quarkus: supersnel subatomair Java

Door: Burr Sutter
Deze video-tutorial van DevNation Live laat zien hoe u Quarkus kunt gebruiken om zakelijke Java-applicaties, API's, microservices en serverloze functies in een Kubernetes/OpenShift-omgeving te optimaliseren, waardoor ze veel kleiner, sneller en schaalbaarder worden.

3. Quarkus en GraalVM: Hibernate versnellen tot supersnelheden en verkleinen tot subatomaire afmetingen

Auteur: Sanne Grinovero
Uit de presentatie leert u hoe Quarkus is ontstaan, hoe het werkt en hoe u complexe bibliotheken, zoals Hibernate ORM, compatibel kunt maken met native GraalVM-images.

4. Leer serverloze applicaties ontwikkelen

Schrijver: Maarten Luther
De onderstaande video laat zien hoe u een eenvoudige Java-applicatie kunt maken met Quarkus en deze kunt implementeren als een serverloze applicatie op Knative.

5. Quarkus: Veel codeerplezier

Auteur: Edson Yanaga
Een videogids voor het maken van uw eerste Quarkus-project, zodat u begrijpt waarom Quarkus de harten van ontwikkelaars verovert.

6. Java en containers - wat hun toekomst samen zal zijn

Geplaatst door Mark Little
Deze presentatie introduceert de geschiedenis van Java en legt uit waarom Quarkus de toekomst van Java is.

7. Quarkus: supersnel subatomair Java

Auteur: Dimitris Andreadis
Een overzicht van de voordelen van Quarkus die erkenning hebben gekregen van ontwikkelaars: eenvoud, ultrahoge snelheden, de beste bibliotheken en standaarden.

8. Quarkus en subatomaire raketsystemen

Auteur: Clement Escoffier
Door integratie met GraalVM biedt Quarkus een ultrasnelle ontwikkelingservaring en een subatomaire runtime-omgeving. De auteur vertelt over de reactieve kant van Quarkus en hoe je deze kunt gebruiken om reactieve en streaming-applicaties te bouwen.

9. Quarkus en snelle applicatieontwikkeling in Eclipse MicroProfile

Auteur: John Clingan
Door Eclipse MicroProfile en Quarkus te combineren, kunnen ontwikkelaars volledig uitgeruste MicroProfile-applicaties in containers creëren die in tientallen milliseconden worden gestart. De video gaat gedetailleerd in op het coderen van een gecontaineriseerde MicroProfile-applicatie voor implementatie op het Kubernetes-platform.

10. Java, "Turbo"-versie

Auteur: Marcus Biel
De auteur laat zien hoe je Quarkus kunt gebruiken om superkleine, supersnelle Java-containers te maken die echte doorbraken mogelijk maken, vooral in serverloze omgevingen.



Bron: www.habr.com

Voeg een reactie