Programovanie

Mastering Spring framework 5, Part 2: Spring WebFlux

Spring WebFlux predstavuje reaktívny vývoj webu v jarnom ekosystéme. V tomto článku vás zoznámime s reaktívnymi systémami a reaktívnym programovaním s programom Spring. Najskôr zistíte, prečo sú reaktívne systémy dôležité a ako sú implementované v jarnom rámci 5, potom získate praktický úvod do budovania reaktívnych služieb pomocou Spring WebFlux. Prvú reaktívnu aplikáciu zostavíme pomocou anotácií. Ukážem vám tiež, ako vytvoriť podobnú aplikáciu pomocou novších funkčných funkcií Spring.

Jarné výukové programy o prostredí JavaWorld

Ak ste v jarnom rámci nováčikom, odporúčam vám začať jedným z predchádzajúcich návodov v tejto sérii:

  • Čo je jar? Vývoj komponentov pre Javu
  • Mastering Spring framework 5: Spring MVC

Reaktívne systémy a Spring WebFlux

Termín reaktívny je v súčasnosti obľúbený u vývojárov a IT manažérov, ale všimol som si určitú neistotu, čo to vlastne znamená. Aby ste si ujasnili, čo sú reaktívne systémy, je užitočné pochopiť základný problém, ktorý majú vyriešiť. V tejto časti si povieme všeobecne o reaktívnych systémoch a predstavím API Reactive Streams pre aplikácie Java.

Škálovateľnosť na jar MVC

Spoločnosť Spring MVC si získala miesto medzi najlepšími voľbami v oblasti vytvárania webových aplikácií a webových služieb Java. Ako sme objavili v Mastering Spring framework 5, časť 1, Spring MVC bezproblémovo integruje anotácie do robustnej architektúry aplikácie založenej na Spring. To umožňuje vývojárom oboznámeným s Springom rýchlo vytvárať uspokojivé a vysoko funkčné webové aplikácie. Škálovateľnosť je však výzvou pre jarné aplikácie MVC. To je problém, ktorý sa snaží vyriešiť Spring WebFlux.

Blokovanie vs neblokujúce webové rámce

Keď v tradičných webových aplikáciách webový server prijme požiadavku od klienta, prijme túto požiadavku a umiestni ju do fronty na vykonanie. Vlákno vo fonde vlákien vykonávacieho frontu potom prijme požiadavku, načíta svoje vstupné parametre a vygeneruje odpoveď. Na ceste, ak vykonávacie vlákno musí volať blokujúci prostriedok - napríklad databázu, súborový systém alebo inú webovú službu - toto vlákno vykoná požiadavku na blokovanie a čaká na odpoveď. V tejto paradigme je vlákno účinne blokované, kým neodpovie externý zdroj, čo spôsobí problémy s výkonom a obmedzí škálovateľnosť. Aby sa zabránilo týmto problémom, vývojári vytvárajú veľkoryso veľké fondy vlákien, takže zatiaľ čo je jedno vlákno blokované, iné vlákno môže pokračovať v spracovávaní požiadaviek. Obrázok 1 zobrazuje priebeh vykonávania tradičnej blokujúcej webovej aplikácie.

Steven Haines

Neblokujúce webové rámce ako NodeJS a Play používajú iný prístup. Namiesto vykonania žiadosti o blokovanie a čakania na jej dokončenie používajú neblokujúce I / O. V tejto paradigme aplikácia vykoná požiadavku, poskytne kód, ktorý sa má vykonať po vrátení odpovede, a potom vráti svoje vlákno späť na server. Keď externý zdroj vráti odpoveď, vykoná sa poskytnutý kód. Neblokujúce rámce interne fungujú pomocou slučky udalostí. V rámci slučky poskytuje kód aplikácie buď spätné volanie, alebo budúcnosť obsahujúcu kód, ktorý sa má vykonať po dokončení asynchrónnej slučky.

Neblokujúce rámce sú svojou povahou udalosťami riadené. To si vyžaduje inú paradigmu programovania a nový prístup k úvahám o tom, ako bude váš kód vykonaný. Keď si to omotáte hlavou, reaktívne programovanie môže viesť k veľmi škálovateľným aplikáciám.

Spätné volania, sľuby a futures

V prvých dňoch JavaScript spracovával všetky asynchrónne funkcie prostredníctvom spätné volania. V tomto scenári, keď dôjde k udalosti (napríklad keď bude k dispozícii odpoveď zo servisného volania), vykoná sa spätné volanie. Aj keď spätné volania stále prevládajú, asynchrónna funkčnosť JavaScriptu sa nedávno presunula na sľuby. Vďaka prísľubom sa volanie funkcie vráti okamžite a vráti prísľub, že výsledky prinesie v budúcnosti. Namiesto sľubov implementuje Java podobnú paradigmu pomocou futures. Pri tomto použití metóda vracia budúcnosť, ktorá bude mať niekedy v budúcnosti hodnotu.

Reaktívne programovanie

Možno ste tento výraz už počuli reaktívne programovanie týkajúce sa rámcov a nástrojov na vývoj webu, ale čo to v skutočnosti znamená? Termín, ako sme ho poznali, pochádza z Reaktívneho manifestu, ktorý definuje reaktívne systémy ako štyri základné znaky:

  1. Reaktívne systémy sú responzívny, čo znamená, že reagujú včas a za každých možných okolností. Zameriavajú sa na poskytovanie rýchlych a konzistentných časov odozvy, stanovenie spoľahlivých horných hraníc, aby poskytovali konzistentnú kvalitu služieb.
  2. Reaktívne systémy sú odolný, čo znamená, že zostávajú pohotové aj v prípade zlyhania. Odolnosť sa dosahuje technikami replikácie, zadržiavania, izolácie a delegovania. Ak budete navzájom izolovať komponenty aplikácie, môžete obmedziť zlyhania a chrániť systém ako celok.
  3. Reaktívne systémy sú elastické, čo znamená, že zostávajú pohotovo reagujúci pri rôznych pracovných zaťaženiach. To sa dosiahne elastickým škálovaním komponentov aplikácie, aby sa uspokojil súčasný dopyt.
  4. Reaktívne systémy sú riadené správami, čo znamená, že sa spoliehajú na asynchrónne posielanie správ medzi komponentmi. To vám umožní vytvoriť voľné spojenie, izoláciu a priehľadnosť umiestnenia.

Obrázok 2 ukazuje, ako tieto vlastnosti prúdia spolu v reaktívnom systéme.

Steven Haines

Vlastnosti reaktívneho systému

Reaktívne systémy sú vytvárané vytváraním izolovaných komponentov, ktoré navzájom komunikujú asynchrónne a dajú sa rýchlo škálovať tak, aby vyhovovali aktuálnemu zaťaženiu. Komponenty stále zlyhávajú v reaktívnych systémoch, ale sú definované akcie, ktoré sa majú vykonať v dôsledku tejto poruchy, ktorá udržuje celý systém funkčný a pohotový.

The Reaktívny manifest je abstraktné, ale reaktívne aplikácie sa zvyčajne vyznačujú nasledujúcimi komponentmi alebo technikami:

  • Dátové toky: A Prúd je postupnosť udalostí zoradených v čase, ako sú interakcie používateľov, volania služieb REST, správy JMS a výsledky z databázy.
  • Asynchrónne: Udalosti toku údajov sa zachytávajú asynchrónne a váš kód definuje, čo robiť, keď sa vyskytne udalosť, dôjde k chybe a keď sa prúd udalostí dokončí.
  • Neblokujúce: Pri spracovávaní udalostí by váš kód nemal blokovať a vykonávať synchrónne volania; namiesto toho by malo uskutočňovať asynchrónne hovory a reagovať, keď sa výsledky týchto hovorov vrátia.
  • Protitlak: Komponenty riadia počet udalostí a frekvenciu ich vysielania. Reaktívne znamená, že váš komponent sa označuje ako predplatiteľ a udalosti emituje a vydavateľ. To je dôležité, pretože predplatiteľ má kontrolu nad tým, koľko dát dostane, a teda sám seba príliš nezaťaží.
  • Správy o zlyhaní: Namiesto komponentov vyvolávajúcich výnimky sa zlyhania odosielajú ako správy funkcii obslužnej rutiny. Zatiaľ čo vyhadzovanie výnimiek prerušuje prúd, definovanie funkcie na zvládanie zlyhaní, keď sa vyskytnú, nie.

Rozhranie Reactive Streams API

Nové rozhranie Reactive Streams API vytvorili okrem iného inžinieri zo spoločností Netflix, Pivotal, Lightbend, RedHat, Twitter a Oracle. Publikované v roku 2015, API Reactive Streams je teraz súčasťou Java 9. Definuje štyri rozhrania:

  • Vydavateľ: Vydáva sled udalostí predplatiteľom.
  • Predplatiteľ: Prijíma a spracováva udalosti emitované vydavateľom.
  • Predplatné: Definuje vzájomný vzťah medzi vydavateľom a predplatiteľom.
  • procesor: Predstavuje fázu spracovania pozostávajúcu tak z predplatiteľa, ako aj z vydavateľa a riadi sa zmluvami oboch.

Obrázok 3 zobrazuje vzťah medzi vydavateľom, predplatiteľom a predplatným.

Steven Haines

Predplatiteľ v podstate vytvorí predplatné vydavateľovi a keď má vydavateľ k dispozícii údaje, odošle udalosť predplatiteľovi s prúdom prvkov. Upozorňujeme, že predplatiteľ spravuje spätný tlak v rámci svojho predplatného vydavateľovi.

Teraz, keď už viete niečo o reaktívnych systémoch a API Reactive Streams, obráťme našu pozornosť na nástroje, ktoré Spring používa na implementáciu reaktívnych systémov: Spring WebFlux a knižnica Reactor.

Projektový reaktor

Project Reactor je rámec tretích strán založený na špecifikácii Java Reactive Streams, ktorý sa používa na vytváranie neblokujúcich webových aplikácií. Project Reactor poskytuje dvoch vydavateľov, ktorí sa vo Spring WebFlux veľmi používajú:

  • Mono: Vráti 0 alebo 1 prvok.
  • Flux: Vráti 0 alebo viac prvkov. Tok môže byť nekonečný, čo znamená, že môže emitovať prvky navždy, alebo môže vrátiť postupnosť prvkov a potom poslať oznámenie o dokončení, keď vráti všetky svoje prvky.

Monos a toky sú koncepčne podobné futures, ale sú silnejšie. Keď vyvoláte funkciu, ktorá vráti mono alebo tok, vráti sa okamžite. Výsledky volania funkcií vám budú doručené prostredníctvom mono alebo toku, keď budú k dispozícii.

Na jar WebFlux zavoláte reaktívne knižnice, ktoré vracajú monos a toky a vaše ovládače vracajú monos a toky. Pretože sa tieto vracajú okamžite, vaše ovládače sa efektívne vzdajú svojich vlákien a umožnia reaktoru asynchrónne spracovávať odpovede. Je dôležité si uvedomiť, že iba pomocou reaktívnych knižníc môžu vaše služby WebFlux zostať reaktívne. Ak používate nereaktívne knižnice, napríklad hovory JDBC, váš kód sa zablokuje a pred návratom počká na dokončenie týchto hovorov.

Reaktívne programovanie s MongoDB

V súčasnosti nie je veľa reaktívnych databázových knižníc, takže by vás mohlo zaujímať, či je praktické písať reaktívne služby. Dobrou správou je, že MongoDB má reaktívnu podporu a existuje niekoľko reaktívnych databázových ovládačov tretích strán pre MySQL a Postgres. Pre všetky ostatné prípady použitia poskytuje WebFlux mechanizmus na reaktívne uskutočňovanie hovorov JDBC, aj keď využíva fond sekundárnych vlákien, ktorý blokuje hovory JDBC.

Začnite s jarným WebFluxom

Pre náš prvý príklad príkladu vytvoríme jednoduchú knižnú službu, ktorá reaktívnym spôsobom uchová knihy do a z MongoDB.

Začnite tým, že prejdete na domovskú stránku Spring Initializr, kde si vyberiete a Maven projekt s Java a vyberte najaktuálnejšie vydanie Spring Boot (2.0.3 v čase písania tohto článku). Priraďte svojmu projektu názov skupiny, napríklad „com.javaworld.webflux“, a názov artefaktu, napríklad „bookservice“. Rozbaľte Prepnúť na plnú verziu odkaz na zobrazenie úplného zoznamu závislostí. Vyberte nasledujúce závislosti pre vzorovú aplikáciu:

  • Web -> Reaktívny web: Táto závislosť zahŕňa jarný WebFlux.
  • NoSQL -> Reaktívny MongoDB: Táto závislosť zahŕňa reaktívne ovládače pre MongoDB.
  • NoSQL -> Vstavaný MongoDB: Táto závislosť nám umožňuje spustiť vloženú verziu MongoDB, takže nie je potrebné inštalovať samostatnú inštanciu. Zvyčajne sa to používa na testovanie, ale zahrnieme to do nášho kódu vydania, aby sme sa vyhli inštalácii MongoDB.
  • Jadro -> Lombok: Používanie Lomboku je voliteľné, pretože ho nepotrebujete na zostavenie jarnej aplikácie WebFlux. Výhodou použitia Project Lombok je, že vám umožňuje pridávať anotácie do tried, ktoré budú automaticky generovať getry a settery, konštruktory, hashCode (), rovná sa (), a viac.

Po dokončení by ste mali vidieť niečo podobné ako na obrázku 4.

Steven Haines

Lisovanie Vytvoriť projekt spustí stiahnutie zip súboru obsahujúceho váš zdrojový kód projektu. Rozbaľte stiahnutý súbor a otvorte ho vo svojom obľúbenom IDE. Ak používate IntelliJ, vyberte si Súbor a potom Otvorenéa prejdite do adresára, kde bol stiahnutý súbor ZIP dekomprimovaný.

Uvidíte, že Spring Initializr vygeneroval dva dôležité súbory:

  1. Maven pom.xml súbor, ktorý obsahuje všetky potrebné závislosti pre aplikáciu.
  2. BookserviceApplication.java, čo je pre aplikáciu spúšťacia trieda Spring Boot.

Výpis 1 zobrazuje obsah vygenerovaného súboru pom.xml.