Hvordan Quarkus kombinerer imperativ og reaktiv programmering

I år planlægger vi seriøst at udvikle containertemaer, Cloud-native Java и Kubernetes. En logisk fortsættelse af disse emner vil allerede være en historie om Quarkus-rammen taget i betragtning på Habré. Dagens artikel handler mindre om designet af "subatomic superhurtig Java" og mere om det løfte, som Quarkus giver Enterprise.

Hvordan Quarkus kombinerer imperativ og reaktiv programmering

Java og JVM er stadig ekstremt populære, men når man arbejder med serverløse teknologier og cloud-native mikrotjenester, bruges Java og andre JVM-sprog mindre og mindre, fordi de optager for meget hukommelse og er for langsomme til at indlæse, hvilket gør dem dårligt egnet til brug med kortlivede beholdere. Heldigvis begynder denne situation nu at ændre sig takket være Quarkus.

Superhurtig subatomisk Java har nået et nyt niveau!

42 udgivelser, 8 måneders samfundsarbejde og 177 fantastiske udviklere - resultatet af det hele var udgivelsen i november 2019 Quarkus 1.0, en udgivelse, der markerer en vigtig milepæl i udviklingen af ​​projektet og tilbyder en masse fede funktioner og muligheder (du kan læse mere om dem i bekendtgørelse).

I dag viser vi dig, hvordan Quarkus kombinerer imperative og reaktive programmeringsmodeller til en enkelt reaktiv kerne. Vi starter med en kort historie og går derefter i detaljer om, hvad Quarkus' reaktive kernedualisme er, og hvordan Java-Udviklere kan drage fordel af disse fordele.

Mikrotjenester, begivenhedsdrevne arkitekturer и serverless-funktioner – alt dette er, som man siger, i fremgang i dag. For nylig er skabelsen af ​​sky-centrerede arkitekturer blevet meget nemmere og mere tilgængelige, men der er stadig problemer - især for Java-udviklere. For eksempel, i tilfælde af serverløse funktioner og mikrotjenester, er der et presserende behov for at reducere opstartstiden, reducere hukommelsesforbruget og stadig gøre deres udvikling mere bekvem og behagelig. Java har foretaget adskillige forbedringer i de senere år, såsom forbedret ergonomisk funktionalitet til containere og så videre. Det er dog stadig en udfordring at få Java til at fungere korrekt i en container. Så vi starter med at se på nogle af Javas iboende kompleksiteter, som er særligt akutte, når man udvikler containerorienterede Java-applikationer.

Lad os først se på historien.

Hvordan Quarkus kombinerer imperativ og reaktiv programmering

Vandløb og beholdere

Startende med version 8u131 begyndte Java mere eller mindre at understøtte containere på grund af forbedringer i ergonomisk funktionalitet. Især ved JVM'en nu, hvor mange processorkerner den kører på, og kan konfigurere trådpuljer - typisk fork/join-puljer - i overensstemmelse hermed. Det er selvfølgelig fantastisk, men lad os sige, at vi har en traditionel webapplikation, der bruger HTTP-servlets og kører i Tomcat, Jetty osv. Som et resultat vil denne applikation give hver anmodning en separat tråd og tillade den at blokere denne tråd, mens den venter på I/O-operationer, for eksempel når man får adgang til databasen, filerne eller andre tjenester. Det vil sige, at størrelsen af ​​en sådan applikation ikke afhænger af antallet af tilgængelige kerner, men af ​​antallet af samtidige anmodninger. Derudover betyder det, at kvoter eller begrænsninger i Kubernetes på antallet af kerner ikke vil være til stor hjælp her, og sagen ender i sidste ende med at drosle.

Hukommelsesudmattelse

Tråde er hukommelse. Og begrænsninger i hukommelsen i beholderen er på ingen måde et vidundermiddel. Bare begynd at øge antallet af applikationer og tråde, og før eller siden vil du støde på en kritisk stigning i omskiftningsfrekvensen og som et resultat forringelse af ydeevnen. Hvis din applikation også bruger traditionelle mikroservice-frameworks, eller opretter forbindelse til en database, eller bruger caching eller på anden måde bruger hukommelse, har du naturligvis brug for et værktøj, der giver dig mulighed for at se inde i JVM'en og se, hvordan den administrerer hukommelsen uden at dræbe den. JVM selv (for eksempel XX:+UseCGroupMemoryLimitForHeap). Og selvom JVM siden Java 9 har lært at acceptere cgroups og tilpasse sig i overensstemmelse hermed, er reservation og håndtering af hukommelse stadig en ret kompleks sag.

Kvoter og grænser

Java 11 introducerede understøttelse af CPU-kvoter (som PreferContainerQuotaForCPUCount). Kubernetes tilbyder også support til grænser og kvoter. Ja, alt dette giver mening, men hvis applikationen igen overskrider den tildelte kvote, ender vi igen med størrelsen - som det er tilfældet med traditionelle Java applikationer - bestemt af antallet af kerner og med tildelingen af ​​en separat tråd for hver anmodning, så er der lidt mening i alt dette.
Derudover, hvis du bruger kvoter og grænser eller udskaleringsfunktionerne på den platform, der ligger til grund for Kubernetes, løser problemet heller ikke sig selv. Vi bruger simpelthen flere ressourcer på at løse det oprindelige problem eller ender med at overforbruge. Og hvis det er et system med høj belastning i en offentlig offentlig sky, ender vi næsten helt sikkert med at bruge flere ressourcer, end vi virkelig har brug for.

Og hvad skal man gøre med alt dette?

For at sige det enkelt, brug asynkrone og ikke-blokerende I/O-biblioteker og rammer som Netty, Vert.x eller Akka. De er meget bedre egnet til at arbejde i containere på grund af deres reaktive natur. Takket være ikke-blokerende I/O kan den samme tråd behandle flere samtidige anmodninger. Mens en anmodning venter på I/O-resultater, frigives tråden, der behandler den, og overtages af en anden anmodning. Og når I/O-resultaterne endelig ankommer, fortsætter behandlingen af ​​den første anmodning. Ved sammenflettet behandling af anmodninger inden for samme tråd kan du reducere det samlede antal tråde og reducere ressourceforbruget til behandling af anmodninger.

Med ikke-blokerende I/O bliver antallet af kerner en nøgleparameter, fordi det bestemmer antallet af I/O-tråde, der kan udføres parallelt. Når det bruges korrekt, giver dette dig mulighed for effektivt at fordele belastningen mellem kerner og håndtere højere arbejdsbelastninger med færre ressourcer.

Hvordan, er det det hele?

Nej, der er noget andet. Reaktiv programmering hjælper med at udnytte ressourcerne bedre, men har også en pris. Især skal koden omskrives i overensstemmelse med principperne om ikke-blokering og undgå blokering af I/O-tråde. Og dette er en helt anden model for udvikling og udførelse. Og selvom der er mange brugbare biblioteker her, er det stadig en radikal ændring i den sædvanlige tankegang.

Først skal du lære at skrive kode, der kører asynkront. Når du begynder at bruge ikke-blokerende I/O, skal du udtrykkeligt angive, hvad der skal ske, når et svar på en anmodning modtages. Blot at blokere og vente virker ikke længere. I stedet kan du sende tilbagekald, bruge reaktiv programmering eller fortsættelse. Men det er ikke alt: For at bruge ikke-blokerende I/O har du brug for både ikke-blokerende servere og klienter, helst overalt. I tilfældet med HTTP er alt simpelt, men der er også databaser, filsystemer og meget mere.

Og selvom total ende-til-ende-reaktivitet maksimerer effektiviteten, kan et sådant skift være svært at tåle i praksis. Derfor bliver evnen til at kombinere reaktiv og imperativ kode en forudsætning for at:

  1. Brug ressourcer effektivt i de mest belastede områder af softwaresystemet;
  2. Brug en enklere stilkode i de resterende dele.

Vi præsenterer Quarkus

Faktisk er dette essensen af ​​Quarkus - at kombinere reaktive og imperative modeller i et enkelt runtime-miljø.

Quarkus er baseret på Vert.x og Netty, med en række reaktive rammer og udvidelser på toppen for at hjælpe udvikleren. Quarkus er designet til at bygge ikke kun HTTP-mikrotjenester, men også begivenhedsdrevne arkitekturer. På grund af dets reaktive karakter fungerer det meget effektivt med beskedsystemer (Apache Kafka, AMQP osv.).

Tricket er, hvordan man bruger den samme reaktive motor til både imperativ og reaktiv kode.

Hvordan Quarkus kombinerer imperativ og reaktiv programmering

Quarkus gør dette glimrende. Valget mellem imperativ og reaktiv er indlysende - brug en reaktiv kerne til begge. Det, det virkelig hjælper med, er hurtig, ikke-blokerende kode, der håndterer næsten alt, der passerer gennem event-loop-tråden, også kendt som IO-tråden. Men hvis du har klassiske REST- eller klientside-applikationer, har Quarkus en imperativ programmeringsmodel klar. Eksempelvis er HTTP-understøttelse i Quarkus baseret på brugen af ​​en ikke-blokerende og reaktiv motor (Eclipse Vert.x og Netty). Alle HTTP-anmodninger modtaget af din applikation sendes først gennem en hændelsesløkke (IO Thread) og sendes derefter til den del af koden, der administrerer anmodningerne. Afhængigt af destinationen kan anmodningsstyringskoden kaldes inden for en separat tråd (den såkaldte arbejdstråd, der bruges i tilfælde af servlets og Jax-RS) eller bruge kilde-I/O-tråden (reaktiv rute).

Hvordan Quarkus kombinerer imperativ og reaktiv programmering

Messaging-systemforbindelser bruger ikke-blokerende klienter, der kører oven på Vert.x-motoren. Derfor kan du effektivt sende, modtage og behandle beskeder fra meddelelsesmiddleware-systemer.

Webstedet Quarkus.io Her er nogle gode selvstudier, der hjælper dig med at komme i gang med Quarkus:

Vi har også lavet online hands-on tutorials for at lære dig forskellige aspekter af reaktiv programmering i blot en browser, ingen IDE påkrævet og ingen computer påkrævet. Du kan finde disse lektioner her.

Nyttige ressourcer

10 videolektioner om Quarkus for at blive fortrolig med emnet

Som de siger på hjemmesiden Quarkus.io, kvarkus - er Kubernetes-orienteret Java-stak, skræddersyet til GraalVM og OpenJDK HotSpot og samlet fra de bedste Java-biblioteker og -standarder.

For at hjælpe dig med at forstå emnet har vi udvalgt 10 videotutorials, der dækker forskellige aspekter af Quarkus og eksempler på dets brug:

1. Introduktion af Quarkus: The Next Generation Java Framework for Kubernetes

Af Thomas Qvarnstrom og Jason Greene
Målet med Quarkus-projektet er at skabe en Java-platform til Kubernetes og serverløse miljøer og at kombinere reaktive og imperative programmeringsmodeller i et enkelt runtime-miljø, så udviklere fleksibelt kan variere deres tilgang, når de arbejder med en bred vifte af distribuerede applikationsarkitekturer. Få mere at vide i det indledende foredrag nedenfor.

2. Quarkus: Superhurtig subatomisk Java

Af: Burr Sutter
Denne videotutorial fra DevNation Live demonstrerer, hvordan du bruger Quarkus til at optimere Java-applikationer, API'er, mikrotjenester og serverløse funktioner i et Kubernetes/OpenShift-miljø, hvilket gør dem meget mindre, hurtigere og mere skalerbare.

3. Quarkus og GraalVM: accelererer Hibernate til superhastigheder og krymper den til subatomære størrelser

Forfatter: Sanne Grinovero
Fra præsentationen vil du lære, hvordan Quarkus blev til, hvordan det virker, og hvordan det giver dig mulighed for at gøre komplekse biblioteker, som Hibernate ORM, kompatible med indbyggede GraalVM-billeder.

4. Lær at udvikle serverløse applikationer

Forfatter: Martin Luther
Videoen nedenfor viser, hvordan du opretter en simpel Java-applikation ved hjælp af Quarkus og implementerer den som en serverløs applikation på Knative.

5. Quarkus: God fornøjelse med at kode

Forfatter: Edson Yanaga
En videoguide til at skabe dit første Quarkus-projekt, der giver dig mulighed for at forstå, hvorfor Quarkus vinder udviklernes hjerter.

6. Java og containere - hvad deres fremtid sammen bliver

Indsendt af Mark Little
Denne præsentation introducerer Javas historie og forklarer, hvorfor Quarkus er Javas fremtid.

7. Quarkus: Superhurtig subatomisk Java

Forfatter: Dimitris Andreadis
En oversigt over fordelene ved Quarkus, der har modtaget anerkendelse fra udviklere: enkelhed, ultrahøje hastigheder, de bedste biblioteker og standarder.

8. Quarkus og subatomare raketsystemer

Forfatter: Clement Escoffier
Gennem integration med GraalVM giver Quarkus en ultrahurtig udviklingsoplevelse og et subatomisk runtime-miljø. Forfatteren fortæller om den reaktive side af Quarkus, og hvordan man bruger den til at bygge reaktive og streaming-applikationer.

9. Quarkus og hurtig applikationsudvikling i Eclipse MicroProfile

Forfatter: John Clingan
Ved at kombinere Eclipse MicroProfile og Quarkus kan udviklere skabe fuldt udstyrede containeriserede MicroProfile-applikationer, der starter på titusvis af millisekunder. Videoen går i detaljer om, hvordan man koder en containeriseret MicroProfile-applikation til implementering på Kubernetes-platformen.

10. Java, "Turbo" version

Forfatter: Marcus Biel
Forfatteren viser, hvordan man bruger Quarkus til at skabe supersmå, superhurtige Java-containere, der muliggør reelle gennembrud, især i serverløse miljøer.



Kilde: www.habr.com

Tilføj en kommentar