Programavimas

„Spring framework 5“ įvaldymas, 2 dalis: „Spring WebFlux“

„Spring WebFlux“ pristato reaktyvią interneto plėtrą pavasario ekosistemoje. Šis straipsnis padės jums pradėti naudoti reaktyvias sistemas ir reaguoti į „Spring“ programavimą. Pirmiausia sužinosite, kodėl reaktyviosios sistemos yra svarbios ir kaip jos įdiegtos „Spring Framework 5“, tada gausite praktinę įvadą į reaktyviųjų paslaugų kūrimą naudojant „Spring WebFlux“. Pirmąją reaktyvią programą sukursime naudodami anotacijas. Aš taip pat parodysiu, kaip sukurti panašią programą naudojant naujesnes „Spring“ funkcines savybes.

Pavasarinės „JavaWorld“ pamokos

Jei dar nesinaudojote „Spring“ programa, rekomenduoju pradėti nuo vienos iš ankstesnių šios serijos vadovėlių:

  • Kas yra pavasaris? Komponentais pagrįstas „Java“ kūrimas
  • „Spring framework 5“ įvaldymas: pavasario MVC

Reaktyviosios sistemos ir „Spring WebFlux“

Terminas reaktyvus šiuo metu yra populiarus tarp kūrėjų ir IT vadybininkų, tačiau pastebėjau tam tikrų neaiškumų, ką tai iš tikrųjų reiškia. Norint sužinoti aiškiau, kokios yra reaktyviosios sistemos, naudinga suprasti pagrindinę problemą, kurią jie turi išspręsti. Šiame skyriuje kalbėsime apie reaktyvias sistemas apskritai ir pristatysiu „Java“ programoms skirtą „Reactive Streams“ API.

Mastelio dydis pavasario MVC

Pavasario MVC užsitarnavo vietą tarp geriausių „Java“ žiniatinklio programų ir žiniatinklio paslaugų kūrimo pasirinkimų. Kaip atradome „Mastering Spring framework 5“ 1 dalyje, „Spring MVC“ sklandžiai integruoja anotacijas į tvirtą „Spring“ pagrindu sukurtos programos architektūrą. Tai leidžia kūrėjams, žinantiems „Spring“, greitai sukurti patenkinamas, labai funkcionalias žiniatinklio programas. Mastelis yra iššūkis pavasario MVC programoms. Tai yra problema, kurią siekia išspręsti „Spring WebFlux“.

Blokuojančios ir neužblokuojančios žiniatinklio sistemos

Tradicinėse žiniatinklio programose, kai žiniatinklio serveris gauna kliento užklausą, jis priima tą užklausą ir įtraukia į vykdymo eilę. Tada vykdymo eilės gijų grupėje esanti gija gauna užklausą, nuskaito jos įvesties parametrus ir sugeneruoja atsakymą. Be to, jei vykdymo gijai reikia iškviesti blokavimo šaltinį, pvz., Duomenų bazę, failų sistemą ar kitą žiniatinklio paslaugą, ši gija vykdo blokavimo užklausą ir laukia atsakymo. Šioje paradigmoje gija yra veiksmingai užblokuota, kol išorinis šaltinis neatsako, o tai sukelia našumo problemų ir riboja mastelį. Norėdami kovoti su šiomis problemomis, kūrėjai sukuria gausaus dydžio gijų grupes, kad nors viena gija būtų užblokuota, kita gija galėtų toliau apdoroti užklausas. 1 paveiksle parodytas tradicinės, blokuojančios žiniatinklio programos vykdymo eiga.

Stevenas Hainesas

Neblokuojančios žiniatinklio sistemos, tokios kaip „NodeJS“ ir „Play“, laikosi kitokio požiūrio. Užuot vykdę blokavimo užklausą ir laukdami, kol ji bus baigta, jie naudoja neužblokuojantį įvestį / išvestį. Šioje paradigmoje programa vykdo užklausą, pateikia kodą, kurį reikia vykdyti, kai grąžinamas atsakymas, ir tada grąžina jo giją serveriui. Kai išorinis šaltinis pateikia atsakymą, pateiktas kodas bus vykdomas. Viduje neužblokuojančios sistemos veikia naudojant įvykių kilpą. Kontūre programos kodas suteikia arba atgalinį skambutį, arba būsimą kodą, kurį reikia atlikti, kai asinchroninė kilpa bus baigta.

Iš prigimties neužblokuojančios sistemos yra įvykių varomas. Tam reikia kitokios programavimo paradigmos ir naujo požiūrio į tai, kaip jūsų kodas bus vykdomas. Apsiviję galvą, reaktyvus programavimas gali sukelti labai keičiamo dydžio programas.

Atšaukimas, pažadai ir ateities sandoriai

Pirmosiomis dienomis „JavaScript“ tvarkė visas asinchronines funkcijas per atgaliniai skambučiai. Tokiu atveju įvykus įvykiui (pavyzdžiui, kai gaunamas atsakymas iš tarnybinio skambučio), įvykdomas atgalinis ryšys. Nors atgaliniai skambučiai vis dar paplitę, „JavaScript“ asinchroninė funkcija neseniai perkelta į pažadus. Su pažadais funkcinis iškvietimas grąžinamas iškart, grąžinant pažadą pateikti rezultatus ateityje. Užuot žadėjusi, „Java“ įgyvendina panašią paradigmą naudodama ateities. Taikant šį metodą, metodas grąžina ateitį, kuri tam tikrą laiką turės vertę.

Reaktyvus programavimas

Galbūt girdėjote šį terminą reaktyvus programavimas susijusios su interneto kūrimo sistemomis ir įrankiais, bet ką tai iš tikrųjų reiškia? Terminas, kurį mes sužinojome, kilo iš reaktyvaus manifesto, kuriame reaktyviosios sistemos apibrėžiamos kaip keturios pagrindinės savybės:

  1. Reaktyviosios sistemos yra reaguojantis, tai reiškia, kad jie reaguoja laiku ir visomis įmanomomis aplinkybėmis. Jie sutelkia dėmesį į greitą ir nuoseklų reagavimo laiką, nustatydami patikimas viršutines ribas, kad užtikrintų pastovią paslaugų kokybę.
  2. Reaktyviosios sistemos yra atsparus, tai reiškia, kad nesėkmės atveju jie išlieka jautrūs. Atsparumas pasiekiamas taikant replikacijos, izoliavimo, izoliacijos ir delegavimo metodus. Izoliuodami programos komponentus vienas nuo kito, galite pašalinti gedimus ir apsaugoti visą sistemą.
  3. Reaktyviosios sistemos yra elastinga, tai reiškia, kad jie išlieka jautrūs esant skirtingam darbo krūviui. Tai pasiekiama elastingai pritaikius taikymo komponentus, kad būtų patenkinta dabartinė paklausa.
  4. Reaktyviosios sistemos yra vadovaujamasi pranešimais, tai reiškia, kad jie remiasi asinchroniniu pranešimo perdavimu tarp komponentų. Tai leidžia jums sukurti laisvą sujungimą, izoliaciją ir vietos skaidrumą.

2 paveiksle parodyta, kaip šios savybės teka kartu reaktyvioje sistemoje.

Stevenas Hainesas

Reaktyviosios sistemos charakteristikos

Reaktyviosios sistemos sukurtos kuriant izoliuotus komponentus, kurie asinchroniškai bendrauja tarpusavyje ir gali greitai mastelį atitikti dabartinę apkrovą. Komponentai vis dar neveikia reaktyviose sistemose, tačiau yra tam tikri veiksmai, kuriuos reikia atlikti dėl to gedimo, kuris visą sistemą palaiko funkcionalia ir reaguojančia.

Reaktyvus manifestas yra abstraktus, tačiau reaktyviesiems pritaikymams paprastai būdingi šie komponentai ar metodai:

  • Duomenų srautai: A srautas yra laiku užsakytų įvykių seka, pvz., vartotojo sąveika, REST paslaugų skambučiai, JMS pranešimai ir rezultatai iš duomenų bazės.
  • Asinchroninis: Duomenų srauto įvykiai fiksuojami asinchroniškai, o jūsų kodas nurodo, ką daryti, kai įvykis išleidžiamas, įvyksta klaida ir kai įvykių srautas baigiasi.
  • Neužblokuojantis: Kai apdorojate įvykius, jūsų kodas neturėtų užblokuoti ir atlikti sinchroninių skambučių; Vietoj to, ji turėtų atlikti asinchroninius skambučius ir atsakyti, kai tų skambučių rezultatai bus grąžinti.
  • Nugaros spaudimas: Komponentai kontroliuoja įvykių skaičių ir jų skleidimo dažnumą. Reaktyviai jūsų komponentas vadinamas abonentas o įvykius skleidžia a leidėjas. Tai svarbu, nes abonentas pats kontroliuoja, kiek duomenų gauna, taigi pats savęs neapkraus.
  • Pranešimai apie gedimą: Užuot komponentams metant išimtis, gedimai siunčiami kaip pranešimai tvarkytojo funkcijai. Išmetimo išimtys pertraukia srautą, o apibrėžti funkciją, kaip valdyti gedimus, kai jie atsiranda.

„Reactive Streams“ API

Naująją „Reactive Streams“ API sukūrė, be kitų, „Netflix“, „Pivotal“, „Lightbend“, „RedHat“, „Twitter“ ir „Oracle“ inžinieriai. 2015 m. Paskelbta „Reactive Streams“ API dabar yra „Java 9“ dalis. Ji apibrėžia keturias sąsajas:

  • Leidėjas: Išleidžia abonentams įvykių seką.
  • Abonentas: Gauna ir apdoroja leidėjo išleistus įvykius.
  • Prenumerata: Apibrėžia „vienas su vienu“ santykį tarp leidėjo ir abonento.
  • Procesorius: Atstovauja duomenų apdorojimo etapui, kurį sudaro abonentas ir leidėjas, ir laikosi abiejų sutarčių.

3 paveiksle parodytas santykis tarp leidėjo, abonento ir prenumeratos.

Stevenas Hainesas

Iš esmės abonentas sukuria leidėjo prenumeratą ir, kai leidėjas turi duomenų, jis siunčia abonentui įvykį su elementų srautu. Atkreipkite dėmesį, kad abonentas valdo savo priešinį spaudimą prenumeruodamas leidėją.

Dabar, kai šiek tiek žinote apie reaktyvias sistemas ir „Reactive Streams“ API, atkreipkime dėmesį į „Spring“ naudojamas priemones reaktyvioms sistemoms įgyvendinti: „Spring WebFlux“ ir „Reactor“ biblioteką.

Projekto reaktorius

„Project Reactor“ yra trečiosios šalies sistema, pagrįsta „Java“ reaktyviųjų srautų specifikacija, naudojama kuriant neužblokuojančias žiniatinklio programas. „Project Reactor“ pateikia du leidėjus, kurie yra plačiai naudojami „Spring WebFlux“:

  • Mono: Pateikia 0 arba 1 elementą.
  • Srautas: Pateikia 0 ar daugiau elementų. „Flux“ gali būti begalinis, o tai reiškia, kad jis gali amžinai skleisti elementus, arba gali grąžinti elementų seką ir tada išsiųsti pranešimą apie užbaigimą, kai grąžins visus savo elementus.

Monos ir srautai konceptualiai panašūs į ateities sandorius, tačiau galingesni. Kai iškviečiate funkciją, kuri grąžina monofoninį arba srautą, ji grįš iškart. Funkcijos iškvietimo rezultatai jums bus pristatyti per monofoninį arba srautinį, kai jie taps prieinami.

Pavasario „WebFlux“ skambinsite į reaktyviąsias bibliotekas, kurios grąžins monos ir srautus, o jūsų valdikliai grąžins monos ir srautus. Kadangi jie nedelsdami grįžta, jūsų valdikliai veiksmingai atsisakys savo gijų ir leis „Reactor“ atsakymus valdyti asinchroniškai. Svarbu pažymėti, kad tik naudodamiesi reaktyviomis bibliotekomis, „WebFlux“ paslaugos gali išlikti reaktyvios. Jei naudojate nereaguojančias bibliotekas, pvz., JDBC skambučius, jūsų kodas užblokuos ir laukia, kol šie skambučiai bus baigti, kol grįšite.

Reaktyvus programavimas su MongoDB

Šiuo metu nėra daug reaktyvių duomenų bazių bibliotekų, todėl jums gali kilti klausimas, ar praktiška rašyti reaktyvias paslaugas. Geros naujienos yra tai, kad „MongoDB“ palaiko reaktyvųjį palaikymą ir yra keletas trečiųjų šalių reaktyvių „MySQL“ ir „Postgres“ duomenų bazių tvarkyklių. Visais kitais naudojimo atvejais „WebFlux“ suteikia JDBC skambučių vykdymo reaktyviu būdu mechanizmą, nors ir naudojant antrinių gijų rinkinį, kuris blokuoja JDBC skambučius.

Pradėkite naudoti „Spring WebFlux“

Savo pirmajam pavyzdžiui sukursime paprastą knygų paslaugą, kuri išlieka knygos į MongoDB ir iš jos.

Pirmiausia eikite į „Spring Initializr“ pagrindinį puslapį, kuriame pasirinksite a Mavenas projektas su „Java“ ir pasirinkite naujausią „Spring Boot“ leidimą (2.0.3 šio rašymo metu). Suteikite savo projektui grupės pavadinimą, pvz., „Com.javaworld.webflux“, ir dirbinio pavadinimą, pvz., „Knygų tarnyba“. Išskleiskite Perjunkite į pilną versiją nuoroda, kad būtų rodomas visas priklausomybių sąrašas. Pasirinkite šias programos pavyzdžio priklausomybes:

  • Žiniatinklis -> Reaktyvusis internetas: Ši priklausomybė apima „Spring WebFlux“.
  • NoSQL -> Reaktyvusis MongoDB: Ši priklausomybė apima reaktyvius MongoDB tvarkykles.
  • NoSQL -> Įterptasis „MongoDB“: Ši priklausomybė leidžia mums paleisti įterptąją „MongoDB“ versiją, todėl nereikia įdiegti atskiro egzemplioriaus. Paprastai tai naudojama bandymams, tačiau mes įtrauksime ją į savo išleidimo kodą, kad išvengtume „MongoDB“ diegimo.
  • Šerdis -> Lombokas: „Lombok“ naudoti neprivaloma, nes to nereikia norint sukurti „Spring WebFlux“ programą. „Project Lombok“ naudojimo pranašumas yra tas, kad jis leidžia jums pridėti anotacijas į klases, kurios automatiškai generuos getters ir seterius, konstruktorius, hashCode (), lygi (), ir dar.

Baigę turėtumėte pamatyti kažką panašaus į 4 paveikslą.

Stevenas Hainesas

Spaudimas Generuoti projektą paskatins atsisiųsti ZIP failą, kuriame yra jūsų projekto šaltinio kodas. Išpakuokite atsisiųstą failą ir atidarykite jį savo mėgstamiausiame IDE. Jei naudojate „IntelliJ“, pasirinkite Failas ir tada Atvirasir eikite į katalogą, kuriame atsisiųstas ZIP failas buvo išspaustas.

Rasite, kad „Spring Initializr“ sukūrė du svarbius failus:

  1. A Mavenas pom.xml failą, kuriame yra visos reikalingos programos priklausomybės.
  2. BookserviceApplication.java, kuri yra programos „Spring Boot“ starterio klasė.

1 sąraše rodomas sugeneruoto failo pom.xml turinys.