Paano pinagsasama ng Quarkus ang imperative at reactive na programming

Sa taong ito plano naming seryosong bumuo ng mga tema ng lalagyan, Cloud-Native Java ΠΈ Kubernetes. Ang isang lohikal na pagpapatuloy ng mga paksang ito ay magiging isang kuwento tungkol sa balangkas ng Quarkus, na isinasaalang-alang kay HabrΓ©. Ang artikulo sa araw na ito ay hindi gaanong tungkol sa disenyo ng "subatomic superfast Java" at higit pa tungkol sa pangako na ibinibigay ng Quarkus sa Enterprise.

Paano pinagsasama ng Quarkus ang imperative at reactive na programming

Ang Java at ang JVM ay napakapopular pa rin, ngunit kapag nagtatrabaho sa mga teknolohiyang walang server at mga cloud-native na microservice, ang Java at iba pang mga wika ng JVM ay ginagamit nang mas kaunti dahil kumukuha sila ng masyadong maraming espasyo sa memorya at masyadong mabagal sa pag-load, na ginagawa itong hindi angkop para sa paggamit sa mga panandaliang lalagyan. Sa kabutihang palad, ang sitwasyong ito ay nagsisimula na ngayong magbago salamat sa Quarkus.

Ang napakabilis na subatomic Java ay umabot na sa isang bagong antas!

42 release, 8 buwan ng gawaing pangkomunidad at 177 kahanga-hangang developer - ang resulta ng lahat ng ito ay ang paglabas noong Nobyembre 2019 Quarkus 1.0, isang release na nagmamarka ng mahalagang milestone sa pagbuo ng proyekto at nag-aalok ng maraming cool na feature at kakayahan (maaari kang magbasa nang higit pa tungkol sa mga ito sa anunsyo).

Ngayon ay ipapakita namin sa iyo kung paano pinagsasama ng Quarkus ang mga modelo ng imperative at reaktibong programming sa isang solong reaktibong core. Magsisimula tayo sa isang maikling kasaysayan at pagkatapos ay talakayin ang tungkol sa kung ano ang reaktibong core dualism ng Quarkus at kung paano Java-Maaaring samantalahin ng mga developer ang mga benepisyong ito.

Mga microservice, mga arkitektura na hinimok ng kaganapan ΠΈ walang server-functions - lahat ng ito ay, tulad ng sinasabi nila, sa pagtaas ngayon. Kamakailan, ang paglikha ng mga cloud-centric na arkitektura ay naging mas madali at mas madaling ma-access, ngunit nananatili ang mga problema - lalo na para sa mga developer ng Java. Halimbawa, sa kaso ng walang server na mga function at microservice, mayroong isang agarang pangangailangan na bawasan ang oras ng pagsisimula, bawasan ang pagkonsumo ng memorya, at gawin pa rin ang kanilang pag-unlad na mas maginhawa at kasiya-siya. Ang Java ay gumawa ng ilang mga pagpapabuti sa mga nakaraang taon, tulad ng pinahusay na paggana ng ergonomya para sa mga lalagyan at iba pa. Gayunpaman, ang pagkuha ng Java upang gumana nang maayos sa isang lalagyan ay mahirap pa rin. Kaya magsisimula tayo sa pamamagitan ng pagtingin sa ilan sa mga likas na kumplikado ng Java, na partikular na talamak kapag bumubuo ng mga application na Java na nakatuon sa lalagyan.

Una, tingnan natin ang kasaysayan.

Paano pinagsasama ng Quarkus ang imperative at reactive na programming

Mga stream at lalagyan

Simula sa bersyon 8u131, nagsimula ang Java sa mas marami o mas kaunting suporta sa mga container dahil sa mga pagpapahusay sa functionality ng ergonomics. Sa partikular, alam na ngayon ng JVM kung gaano karaming mga core ng processor ang pinapatakbo nito at maaaring i-configure ang mga thread poolβ€”karaniwang fork/join poolβ€”ayon. Siyempre, ito ay mahusay, ngunit sabihin nating mayroon kaming tradisyonal na web application na gumagamit ng mga HTTP servlet at tumatakbo sa Tomcat, Jetty, atbp. Bilang resulta, ang application na ito ay magbibigay sa bawat kahilingan ng isang hiwalay na thread at pahihintulutan itong harangan ang thread na ito habang naghihintay para sa mga operasyon ng I/O, halimbawa, kapag ina-access ang database, mga file o iba pang mga serbisyo. Iyon ay, ang laki ng naturang application ay hindi nakasalalay sa bilang ng mga magagamit na core, ngunit sa bilang ng mga sabay-sabay na kahilingan. Bilang karagdagan, nangangahulugan ito na ang mga quota o limitasyon sa Kubernetes sa bilang ng mga core ay hindi makakatulong dito, at ang usapin ay magtatapos sa throttling.

Pagkaubos ng memorya

Ang mga thread ay memorya. At ang mga limitasyon sa memorya ng intra-container ay hindi nangangahulugang isang panlunas sa lahat. Simulan lang ang pagtaas ng bilang ng mga application at thread, at sa malao't madali ay makakatagpo ka ng kritikal na pagtaas sa dalas ng paglipat at, bilang resulta, pagkasira ng pagganap. Gayundin, kung ang iyong application ay gumagamit ng tradisyonal na microservice frameworks, o kumokonekta sa isang database, o gumagamit ng caching, o kung hindi man ay gumagamit ng memorya, malinaw na kailangan mo ng isang tool na nagbibigay-daan sa iyo upang tumingin sa loob ng JVM at makita kung paano ito namamahala ng memorya nang hindi ito pinapatay. Ang JVM mismo (halimbawa, XX:+UseCGroupMemoryLimitForHeap). At kahit na, mula noong Java 9, natutunan ng JVM na tumanggap ng mga cgroup at umangkop nang naaayon, ang pagreserba at pamamahala ng memorya ay nananatiling isang medyo kumplikadong bagay.

Mga quota at limitasyon

Ipinakilala ng Java 11 ang suporta para sa mga quota ng CPU (tulad ng PreferContainerQuotaForCPUCount). Nag-aalok din ang Kubernetes ng suporta para sa mga limitasyon at quota. Oo, lahat ito ay may katuturan, ngunit kung ang application ay muling lumampas sa inilalaan na quota, muli tayong mapupunta sa laki - tulad ng kaso sa mga tradisyunal na Java application - tinutukoy ng bilang ng mga core at sa paglalaan ng isang hiwalay na thread para sa bawat isa. kahilingan, kung gayon walang kaunting kahulugan sa lahat ng ito.
Bilang karagdagan, kung gagamit ka ng mga quota at limitasyon o ang mga function ng scale-out ng platform na pinagbabatayan ng Kubernetes, hindi rin malulutas ng problema ang sarili nito. Gumastos lang kami ng mas maraming mapagkukunan sa paglutas ng orihinal na problema o nauuwi sa sobrang paggastos. At kung ito ay isang high-load system sa isang pampublikong pampublikong ulap, halos tiyak na gagamitin natin ang mas maraming mapagkukunan kaysa sa talagang kailangan natin.

At ano ang gagawin sa lahat ng ito?

Upang ilagay ito nang simple, gumamit ng asynchronous at non-blocking I/O library at frameworks tulad ng Netty, Vert.x o Akka. Ang mga ito ay mas angkop na magtrabaho sa mga lalagyan dahil sa kanilang pagiging reaktibo. Salamat sa hindi pagharang sa I/O, ang parehong thread ay maaaring magproseso ng maraming sabay-sabay na kahilingan. Habang naghihintay ang isang kahilingan para sa mga resulta ng I/O, ang pagpoproseso nito sa thread ay inilabas at kinuha ng isa pang kahilingan. At kapag dumating na ang mga resulta ng I/O, magpapatuloy ang pagproseso ng unang kahilingan. Sa pamamagitan ng interleaved na pagproseso ng mga kahilingan sa loob ng parehong thread, maaari mong bawasan ang kabuuang bilang ng mga thread at bawasan ang pagkonsumo ng mapagkukunan para sa pagpoproseso ng mga kahilingan.

Sa hindi nakaharang na I/O, ang bilang ng mga core ay nagiging pangunahing parameter dahil tinutukoy nito ang bilang ng mga I/O na thread na maaaring isagawa nang magkatulad. Kapag ginamit nang tama, binibigyang-daan ka nitong epektibong ipamahagi ang load sa pagitan ng mga core at pangasiwaan ang mas matataas na workload na may mas kaunting mapagkukunan.

Paano, yun lang ba?

Hindi, may iba pa. Nakakatulong ang reactive programming na mas mahusay na gumamit ng mga mapagkukunan, ngunit may presyo din. Sa partikular, ang code ay kailangang muling isulat ayon sa mga prinsipyo ng hindi pagharang at maiwasan ang pagharang sa mga I/O na thread. At ito ay isang ganap na naiibang modelo ng pag-unlad at pagpapatupad. At kahit na maraming kapaki-pakinabang na mga aklatan dito, ito ay isang radikal na pagbabago sa karaniwang paraan ng pag-iisip.

Una, kailangan mong matutunan kung paano magsulat ng code na tumatakbo nang asynchronously. Kapag nagsimula ka nang gumamit ng hindi naka-block na I/O, kailangan mong tahasang tukuyin kung ano ang dapat mangyari kapag natanggap ang isang tugon sa isang kahilingan. Ang simpleng pagharang at paghihintay ay hindi na gagana. Sa halip, maaari kang magpasa ng mga callback, gumamit ng reaktibong programming o pagpapatuloy. Ngunit hindi lang iyon: para gumamit ng hindi naka-block na I/O, kailangan mo ng parehong hindi naka-block na mga server at kliyente, mas mabuti sa lahat ng dako. Sa kaso ng HTTP, ang lahat ay simple, ngunit mayroon ding mga database, file system, at marami pang iba.

At bagama't ang kabuuang end-to-end na reaktibidad ay nagpapalaki ng kahusayan, ang gayong pagbabago ay maaaring maging mahirap sa tiyan sa pagsasanay. Samakatuwid, ang kakayahang pagsamahin ang reaktibo at imperative na code ay nagiging isang kinakailangan upang:

  1. Mabisang gumamit ng mga mapagkukunan sa mga pinaka-load na lugar ng software system;
  2. Gumamit ng mas simpleng style code sa mga natitirang bahagi nito.

Pagpapakilala kay Quarkus

Sa totoo lang, ito ang esensya ng Quarkus - upang pagsamahin ang mga reaktibo at imperative na mga modelo sa loob ng isang runtime na kapaligiran.

Ang Quarkus ay batay sa Vert.x at Netty, na may hanay ng mga reaktibong framework at extension sa itaas upang matulungan ang developer. Idinisenyo ang Quarkus para sa pagbuo hindi lamang ng mga HTTP microservice, kundi pati na rin ng mga arkitektura na hinimok ng kaganapan. Dahil sa pagiging reaktibo nito, napakabisa nitong gumagana sa mga sistema ng pagmemensahe (Apache Kafka, AMQP, atbp.).

Ang trick ay kung paano gamitin ang parehong reactive engine para sa parehong imperative at reactive code.

Paano pinagsasama ng Quarkus ang imperative at reactive na programming

Mahusay na ginagawa ito ni Quarkus. Ang pagpili sa pagitan ng imperative at reactive ay halata - gumamit ng reactive kernel para sa pareho. Ang talagang nakakatulong ay ang mabilis, hindi naka-block na code na humahawak sa halos lahat ng bagay na dumadaan sa event-loop thread, aka IO thread. Ngunit kung mayroon kang klasikong REST o mga application sa panig ng kliyente, ang Quarkus ay may isang kinakailangang modelo ng programming na handa na. Halimbawa, ang suporta sa HTTP sa Quarkus ay nakabatay sa paggamit ng isang hindi naka-block at reaktibong engine (Eclipse Vert.x at Netty). Ang lahat ng mga kahilingan sa HTTP na natanggap ng iyong aplikasyon ay unang ipinapasa sa isang loop ng kaganapan (IO Thread) at pagkatapos ay ipinadala sa bahagi ng code na namamahala sa mga kahilingan. Depende sa patutunguhan, maaaring tawagan ang code ng pamamahala ng kahilingan sa loob ng isang hiwalay na thread (ang tinatawag na worker thread, na ginagamit sa kaso ng mga servlet at Jax-RS) o gamitin ang source na I/O thread (reaktibong ruta).

Paano pinagsasama ng Quarkus ang imperative at reactive na programming

Gumagamit ang mga connector ng system ng pagmemensahe ng mga hindi nakaharang na kliyente na tumatakbo sa ibabaw ng Vert.x engine. Samakatuwid, maaari mong epektibong magpadala, tumanggap at magproseso ng mga mensahe mula sa mga middleware system ng pagmemensahe.

Ang site Quarkus.io Narito ang ilang magagandang tutorial upang matulungan kang makapagsimula sa Quarkus:

Gumawa din kami ng mga online na hands-on na tutorial para ituro sa iyo ang iba't ibang aspeto ng reaktibong programming sa isang browser lang, walang IDE na kailangan, at walang computer na kailangan. Mahahanap mo ang mga araling ito dito.

Kapaki-pakinabang na mapagkukunan

10 mga aralin sa video sa Quarkus upang maging pamilyar sa paksa

Tulad ng sinasabi nila sa website Quarkus.io, quarkus - Ay Kubernetes-oriented na Java stack, na iniakma para sa GraalVM at OpenJDK HotSpot at binuo mula sa pinakamahusay na mga library at pamantayan ng Java.

Upang matulungan kang maunawaan ang paksa, pumili kami ng 10 video tutorial na sumasaklaw sa iba't ibang aspeto ng Quarkus at mga halimbawa ng paggamit nito:

1. Ipinapakilala ang Quarkus: Ang Susunod na Henerasyong Java Framework para sa Kubernetes

Ni Thomas Qvarnstrom at Jason Greene
Ang layunin ng proyekto ng Quarkus ay lumikha ng isang Java platform para sa mga Kubernetes at serverless na kapaligiran, at upang pagsamahin ang mga reaktibo at imperative na mga modelo ng programming sa isang solong runtime na kapaligiran upang ang mga developer ay maaaring madaling mag-iba-iba ng kanilang diskarte kapag nagtatrabaho sa isang malawak na hanay ng mga distributed application architecture. Alamin ang higit pa sa panimulang panayam sa ibaba.

2. Quarkus: Superfast Subatomic Java

Ni: Burr Sutter
Ipinapakita ng video tutorial na ito mula sa DevNation Live kung paano gamitin ang Quarkus para i-optimize ang mga enterprise Java application, API, microservice, at serverless na function sa isang Kubernetes/OpenShift na kapaligiran, na ginagawang mas maliit, mas mabilis, at mas nasusukat ang mga ito.

3. Quarkus at GraalVM: pinapabilis ang Hibernate sa sobrang bilis at pinaliit ito sa mga subatomic na laki

May-akda: Sanne Grinovo
Mula sa pagtatanghal matututunan mo kung paano nabuo ang Quarkus, kung paano ito gumagana, at kung paano ito nagbibigay-daan sa iyong gumawa ng mga kumplikadong library, tulad ng Hibernate ORM, na tugma sa mga katutubong larawan ng GraalVM.

4. Matutong bumuo ng mga serverless na application

May-akda: Martin Luther
Ipinapakita ng video sa ibaba kung paano lumikha ng isang simpleng Java application gamit ang Quarkus at i-deploy ito bilang isang serverless na application sa Knative.

5. Quarkus: Magsaya sa coding

May-akda: Edson Yanaga
Isang gabay sa video sa paggawa ng iyong unang proyekto sa Quarkus, na nagbibigay-daan sa iyong maunawaan kung bakit napagtagumpayan ng Quarkus ang mga puso ng mga developer.

6. Java at mga lalagyan - kung ano ang kanilang hinaharap na magkasama

Nai-post ni Mark Little
Ipinakikilala ng presentasyong ito ang kasaysayan ng Java at ipinapaliwanag kung bakit ang Quarkus ang kinabukasan ng Java.

7. Quarkus: Superfast Subatomic Java

May-akda: Dimitris Andreadis
Isang pangkalahatang-ideya ng mga pakinabang ng Quarkus na nakatanggap ng pagkilala mula sa mga developer: pagiging simple, napakabilis na bilis, ang pinakamahusay na mga aklatan at pamantayan.

8. Quarkus at subatomic rocket system

May-akda: Clement Escoffier
Sa pamamagitan ng pagsasama sa GraalVM, nagbibigay ang Quarkus ng napakabilis na karanasan sa pag-unlad at isang subatomic na runtime na kapaligiran. Pinag-uusapan ng may-akda ang tungkol sa reaktibong bahagi ng Quarkus at kung paano ito gamitin upang bumuo ng mga reaktibo at streaming na application.

9. Quarkus at mabilis na pagbuo ng application sa Eclipse MicroProfile

May-akda: John Clingan
Sa pamamagitan ng pagsasama-sama ng Eclipse MicroProfile at Quarkus, makakagawa ang mga developer ng buong tampok na containerized na MicroProfile na mga application na ilulunsad sa sampu-sampung millisecond. Detalyado ang video kung paano mag-code ng containerized na MicroProfile application para sa pag-deploy sa platform ng Kubernetes.

10. Java, "Turbo" na bersyon

May-akda: Marcus Biel
Ipinapakita ng may-akda kung paano gamitin ang Quarkus upang lumikha ng napakaliit, napakabilis na mga container ng Java na nagbibigay-daan sa mga tunay na tagumpay, lalo na sa mga walang server na kapaligiran.



Pinagmulan: www.habr.com

Magdagdag ng komento