I år planlægger vi at fokusere på emner omkring containere, og . En logisk fortsættelse af disse emner vil være en fortælling om frameworket Quarkus, som allerede på Habr. Dagens artikel handler ikke så meget om det, der kaldes "subatomar superhurtig Java", men om de muligheder, som Quarkus bringer til Enterprise.

Java og JVM er fortsat ekstremt populære, men i arbejdet med serverless teknologier og cloud-orienterede mikrotjenester bliver Java og andre sprog til JVM anvendt mindre og mindre, da de optager for meget plads i hukommelsen og indlæses for langsomt, hvilket gør dem utilstrækkelige til brug med kortvarige containere. Heldigvis begynder denne situation at ændre sig takket være Quarkus.
Superhurtig subatomar Java er nået til et nyt niveau!
42 udgivelser, 8 måneders samarbejde fra fællesskabet og 177 fantastiske udviklere – resultatet af dette var udgivelsen i november 2019 , en udgivelse, der markerer en vigtig milepæl i projektets udvikling og tilbyder en masse fantastiske funktioner og muligheder (læs mere om dem i ).
I dag vil vi fortælle, hvordan Quarkus kombinerer modellerne for imperativ og reaktiv programmering baseret på et enkelt reaktivt kerne. Vi vil starte med et kort tilbageblik på historien og derefter grundigt analysere, hvad dualismen i Quarkus' reaktive kerne indebærer, og hvordan -udviklere kan drage fordel af disse fordele.
, og -funktioner – alt dette er i øjeblikket, hvad man kalder en opadgående tendens. For nylig er det blevet meget lettere og mere tilgængeligt at skabe cloud-orienterede arkitekturer, men der er stadig problemer - især for Java-udviklere. For eksempel, i tilfælde af serverless-funktioner og mikrotjenester er der et presserende behov for at reducere opstartstiden, mindske hukommelsesforbruget og gøre deres udvikling mere praktisk og behagelig. Java har i de senere år indført adskillige forbedringer, såsom ergonomisk støtte til containere m.m. Men det er stadig en udfordring at få Java til at fungere ordentligt i en container. Derfor vil vi starte med at se på nogle af de indre kompleksiteter i Java, som viser sig særlig tydeligt i udviklingen af containerbaserede Java-applikationer.
Lad os først se på historien.

Tråde og containere
Fra version 8u131 begyndte Java mere eller mindre at understøtte containere ved hjælp af forbedringer inden for ergonomik. Især ved JVM i dag ved, hvor mange CPU-kerner den kører på, og kan derfor tilpasse trådpoolerne – typisk fork/join pooler. Uden tvivl er det fantastisk, men lad os antage, at vi har en traditionel webapplikation, der bruger HTTP-servlets og kører i Tomcat, Jetty osv. Som følge heraf 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 ved adgang til databaser, filer eller andre tjenester. Det betyder, at størrelsen på sådan en applikation ikke afhænger af antallet af tilgængelige kerner, men af antallet af samtidige anmodninger. Desuden betyder det, at kvoter eller grænser i Kubernetes for antallet af kerner ikke vil hjælpe meget, og det hele ender med throttling.
Hukommelsesudtømning
Tråde er hukommelse. Og begrænsninger på hukommelse inde i containere er bestemt ikke en panacea. Bare begynd at øge antallet af applikationer og tråde, og før eller senere vil du støde på en kritisk stigning i skiftfrekvenserne og som følge heraf en degradation af ydeevnen. Derudover, hvis applikationen bruger traditionelle mikrotjenestearkitekturer eller tilslutter sig en database, eller aktiverer caching, eller på anden måde bruger mere hukommelse, så har du helt sikkert brug for et værktøj, der lader dig kigge ind i JVM og se, hvordan den håndterer hukommelse, og samtidig ikke dræber selve JVM'en (for eksempel XX:+UseCGroupMemoryLimitForHeap). Og selvom JVM siden Java 9 har lært at opfatte cgroups og tilpasse sig derefter, er reservation og håndtering af hukommelse stadig en ret kompleks opgave.
Kvoter og grænser
Java 11 introducerede understøttelse af CPU-kvoter (som PreferContainerQuotaForCPUCount). Kubernetes tilbyder også støtte for grænser og kvoter. Ja, alt dette giver mening, men hvis applikationen endnu en gang overskrider den tildelte kvote, kommer vi tilbage til, at størrelsen – som med traditionelle Java-applikationer – bestemmes af antallet af kerner og tildelingen af en separat tråd til hver anmodning, hvilket betyder, at det hele kun har lidt værdi.
Desuden, hvis man bruger kvoter og grænser eller funktioner til horisontal (scale-out) skalering af platformen, der ligger til grund for Kubernetes, løser problemet sig ikke af sig selv. Vi bruger blot flere ressourcer på at løse det oprindelige problem, eller vi ender med at overskride ressourcerne. Og hvis dette er et højt belastet system i et offentligt tilgængeligt cloud-miljø, begynder vi næsten med sikkerhed at bruge flere ressourcer, end der faktisk er nødvendigt.
Og hvad skal man gøre med alt dette?
Hvis vi siger det enkelt, så brug asynkrone og ikke-blokerende input-output biblioteker og frameworks som Netty, eller Akka. De er meget bedre egnet til at arbejde i containere på grund af deres reaktive natur. Takket være ikke-blokerende input-output kan den samme tråd håndtere flere samtidige forespørgsler samtidigt. Mens én forespørgsel venter på input-output-resultater, frigøres den tråd, der behandler den, og går i gang med en anden forespørgsel. Og når input-output-resultaterne endelig kommer, fortsætter behandlingen af den første forespørgsel. Ved at skifte mellem behandling af forespørgsler inden for den samme tråd kan det samlede antal tråde reduceres, og ressourceforbruget til behandling af forespørgslerne mindskes.
Ved ikke-blokerende input-output bliver antallet af kerner en nøgleværdi, da det bestemmer antallet af input-output tråde, der kan udføres parallelt. Ved korrekt brug gør dette det muligt effektivt at fordele belastningen mellem kernerne og håndtere højere belastninger med færre ressourcer.
Hvordan, er det hele?
Nej, der er mere. Reaktiv programmering hjælper med at udnytte ressourcerne bedre, men det har også sin pris. Især skal koden skrives om i henhold til principperne for ikke-blokering og undgå blokerende input-output tråde. Og det er en helt anden model for udvikling og udførelse. Selvom der er mange nyttige biblioteker her, er det stadig en radikal ændring i den sædvanlige tankegang.
For det første skal du lære at skrive kode, der udføres asynkront. Når du begynder at bruge ikke-blokerende input-output, skal du eksplicit angive, hvad der skal ske, når et svar modtages. At blokere og vente fungerer 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 input-output har du brug for ikke-blokerende servere og klienter, gerne overalt. I tilfælde af HTTP er det enkelt, men der er også databaser, filsystemer og meget mere.
Og selvom total skalerbar reaktivitet giver maksimal effektivitet, kan det være svært at fordøje denne ændring i praksis. Derfor bliver muligheden for at kombinere reaktiv og imperativ kode en nødvendighed for at:
- Effektivt udnytte ressourcerne i de mest belastede retninger i software-systemet;
- Brug en enklere stil i resten af koden.
Præsenterer Quarkus
Og det er essensen af Quarkus – at kombinere reaktive og imperative modeller inden for én køreplatform.
Quarkus er bygget på Vert.x og Netty, der oven på det understøtter en række reaktive rammer og udvidelser for at hjælpe udvikleren. Quarkus er designet til at bygge ikke kun HTTP-mikrotjenester, men også event-drevne arkitekturer. Takket være sin reaktive natur fungerer det meget effektivt med beskedsystemer (Apache Kafka, AMQP osv.).
Fintippet ligger i, hvordan man bruger den samme reaktive motor til både imperativ og reaktiv kode.

Quarkus håndterer dette fremragende. Valget mellem imperativt og reaktivt er indlysende – at bruge reaktorkernen til begge dele. Det, det hjælper meget med, er hurtig ikke-blokerende kode, der håndterer næsten alt, hvad der passerer gennem event-loop-tråden (event-loop thread, også kendt som IO-tråden). Men hvis du har klassiske REST-applikationer eller klient-side applikationer, er der en imperativ programmeringsmodel klar til Quarkus. For eksempel er HTTP-understøttelse i Quarkus bygget på brugen af en ikke-blokerende og reaktiv motor (Eclipse Vert.x og Netty). Alle HTTP-anmodninger, der modtages af din applikation, sendes først gennem event-loop (IO-tråden), før de sendes til den del af koden, der håndterer anmodninger. Afhængigt af destinationen kan anmodningsstyringskoden kaldes inden for en separat tråd (den såkaldte worker thread, der bruges i tilfælde af servlets og Jax-RS) eller bruge den oprindelige input-output-strøm (den reaktive rute).

For connectorer til beskedoverførselsystemer anvendes ikke-blokerende klienter, der kører oven på Vert.x-motoren. Derfor kan du effektivt sende, modtage og behandle beskeder fra messaging middleware-systemer.
På hjemmesiden vi har samlet flere gode vejledninger, der kan hjælpe dig med at komme i gang med Quarkus:
Derudover har vi forberedt online praktiske lektioner for at gøre dig bekendt med forskellige aspekter af reaktiv programmering, og alt hvad du behøver for at deltage er en browser – ingen IDE er påkrævet, og en computer er heller ikke nødvendig. Du kan finde disse lektioner .
Nyttige ressourcer
- Quarkus-projektets hjemmeside –
- Quarkus-projektet på GitHub –
- Quarkus-projektets Twitter –
- Quarkus-projektets chat –
- Quarkus-projektets fora – !forum/quarkus-dev
10 videolektioner om Quarkus, for at få styr på emnet
Som det skrives på hjemmesiden , – er -orienteret Java-stak, designet 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 videolektioner, der dækker forskellige aspekter af Quarkus og eksempler på brug:
1. Præsenterer Quarkus: En ny generation Java-ramme for Kubernetes
Forfattere: Thomas Qvarnstrom og Jason Greene
Målet med Quarkus-projektet er at skabe en Java-platform til Kubernetes og serverless-miljøer samt at kombinere reaktive og imperativ programmeringsmodeller inden for et enkelt runtime-miljø, så udviklere kan variere deres tilgang fleksibelt, når de arbejder med en bred vifte af distribuerede applikationsarkitekturer. Læs mere i introduktionseforedraget nedenfor.

2. Quarkus: ultr hurtig subatomær Java
Forfatter: Burr Sutter
Videokurset fra onlineforedraget DevNation Live viser, hvordan man bruger Quarkus til at optimere enterprise Java-applikationer, API'er, mikrotjenester og serverless-funktioner i Kubernetes/OpenShift-miljøet, hvilket gør dem meget mindre, hurtigere og mere skalerbare.

3. Quarkus og GraalVM: booster Hibernate til superhastigheder og komprimerer til subatomære størrelser
Forfatter: Sanne Grinovero
Fra præsentationen vil du lære, hvordan Quarkus opstod, hvordan det fungerer, og hvordan det gør komplekse biblioteker som Hibernate ORM kompatible med native-billeder fra GraalVM.

4. Lær at udvikle serverless-applikationer
Forfatter: Marthen Luther
I videoen nedenfor vises, hvordan man opretter en simpel Java-applikation med Quarkus og implementerer den som en serverless-applikation på Knative.

5. Quarkus: kodning med glæde
Forfatter: Edson Yanaga
Videoguiden til at skabe dit første Quarkus-projekt, der hjælper dig med at forstå, hvorfor Quarkus vinder udvikleres hjerter.

6. Java og containere – hvordan vil fremtiden se ud for dem sammen?
Forfatter: Mark Little
Denne præsentation introducerer historien om Java og forklarer, hvorfor Quarkus er fremtiden for Java.

7. Quarkus: ultr hurtig subatomær Java
Forfatter: Dimitris Andreadis
Oversigt over fordelene ved Quarkus, som udviklerne anerkender: enkelhed, super høje hastigheder, bedre biblioteker og standarder.

8. Quarkus og subatomære reaktive systemer
Forfatter: Clement Escoffier
Takket være integrationen med GraalVM giver Quarkus en ultrahurtig udviklingsoplevelse og et subatomært runtime-miljø. Forfatteren taler om den reaktive side af Quarkus og hvordan man bruger det, når man skaber reaktive applikationer og applikationer med streaming data.

9. Quarkus og hurtig applikationsudvikling i Eclipse MicroProfile
Forfatter: John Clingan
Ved at kombinere Eclipse MicroProfile og Quarkus kan udviklere skabe fuldt funktionelle MicroProfile containerapplikationer, der starter på blot få millisekunder. Videoen gennemgår i detaljer, hvordan man koder en MicroProfile containerapplikation til implementering på Kubernetes-platformen.

10. Java, version "Turbo"
Forfatter: Markus Biel (Marcus Biel)
Forfatteren viser, hvordan man bruger Quarkus til at skabe super små og super hurtige Java-containere, hvilket muliggør en reel breakthrough, især i serverless miljøer.

Kilde: habr.com
