Ovladavanje Spring Spring okvirom 5, Dio 2: Spring WebFlux

Spring WebFlux uvodi reaktivni web razvoj u ekosustav Spring. Ovaj će vas članak započeti s reaktivnim sustavima i reaktivnim programiranjem s Springom. Prvo ćete saznati zašto su reaktivni sustavi važni i kako se implementiraju u Spring framework 5, a zatim ćete dobiti praktični uvod u izgradnju reaktivnih usluga pomoću Spring WebFlux-a. Izradit ćemo prvu reaktivnu aplikaciju pomoću bilješki. Također ću vam pokazati kako izraditi sličnu aplikaciju koristeći nove funkcionalne značajke Springa.

Proljetni vodiči o JavaWorldu

Ako ste novi u Spring Springu, preporučujem da započnete s jednim od ranijih vodiča u ovoj seriji:

  • Što je proljeće? Razvoj zasnovan na komponentama za Javu
  • Ovladavanje okvirom opruge 5: Spring MVC

Reaktivni sustavi i Spring WebFlux

Pojam reaktivan trenutno je popularan među programerima i IT menadžerima, ali primijetio sam određenu nesigurnost oko toga što zapravo znači. Da biste jasnije shvatili što su reaktivni sustavi, korisno je razumjeti temeljni problem koji su oni dizajnirani za rješavanje. U ovom ćemo dijelu govoriti o reaktivnim sustavima općenito i predstavit ću Reactive Streams API za Java aplikacije.

Skalabilnost u proljetnom MVC-u

Spring MVC zaslužio je svoje mjesto među najboljim izborima za izgradnju Java web aplikacija i web usluga. Kao što smo otkrili u Mastering Spring framework-u 5, Dio 1, Spring MVC neprimjetno integrira napomene u robusnu arhitekturu aplikacije utemeljene na Spring-u. To omogućava programerima koji su upoznati s Springom da brzo naprave zadovoljavajuće, vrlo funkcionalne web aplikacije. Međutim, skalabilnost je izazov za Spring MVC aplikacije. To je problem koji Spring WebFlux nastoji riješiti.

Blokiranje i neblokiranje web okvira

U tradicionalnim web aplikacijama, kada web poslužitelj primi zahtjev od klijenta, prihvaća taj zahtjev i smješta ga u red izvršavanja. Nit u spremištu niti reda izvršavanja tada prima zahtjev, čita svoje ulazne parametre i generira odgovor. Usput, ako nit izvođenja treba pozvati resurs za blokiranje - poput baze podataka, datotečnog sustava ili druge web usluge - ta nit izvršava zahtjev za blokiranje i čeka odgovor. U ovoj se paradigmi nit učinkovito blokira dok vanjski resurs ne odgovori, što uzrokuje probleme s izvedbom i ograničava skalabilnost. Da bi se borili protiv ovih problema, programeri stvaraju spremišta niti velike veličine, tako da dok je jedna nit blokirana druga nit može nastaviti obrađivati ​​zahtjeve. Slika 1 prikazuje tijek izvršavanja za tradicionalnu web-aplikaciju koja blokira.

Steven Haines

Neblokirajući web okviri poput NodeJS i Play imaju drugačiji pristup. Umjesto izvršavanja zahtjeva za blokiranje i čekanja da se dovrši, oni koriste I / O koji ne blokira. U ovoj paradigmi, aplikacija izvršava zahtjev, pruža kôd koji treba izvršiti kada se odgovor vrati, a zatim vraća svoju nit natrag poslužitelju. Kada vanjski resurs odgovori, izvršit će se navedeni kod. Interno, neblokirajući okviri djeluju pomoću petlje događaja. Unutar petlje, aplikacijski kôd pruža povratni poziv ili budućnost koja sadrži kôd za izvršenje kada se asinkrona petlja dovrši.

Po prirodi su neblokirajući okviri pokretani događajima . To zahtijeva drugačiju programsku paradigmu i novi pristup razmišljanju o tome kako će se vaš kôd izvršiti. Jednom kad glavu omotate, reaktivno programiranje može dovesti do vrlo skalabilnih aplikacija.

Povratni pozivi, obećanja i budućnosti

U ranim danima JavaScript je obrađivao sve asinkrone funkcije putem povratnih poziva . U ovom se scenariju, kada se dogodi događaj (na primjer kada odgovor iz poziva usluge postane dostupan), izvršava se povratni poziv. Iako su povratni pozivi i dalje prisutni, JavaScript sinkrona funkcionalnost nedavno je prešla na obećanja . Uz obećanja, poziv funkcije vraća se odmah, vraćajući obećanje da će rezultate isporučiti u budućnosti. Umjesto obećanja, Java primjenjuje sličnu paradigmu koristeći budućnosti . U ovoj upotrebi metoda vraća budućnost koja će imati vrijednost u nekom trenutku u budućnosti.

Reaktivno programiranje

Možda ste čuli pojam reaktivnog programiranja koji se odnosi na okvire i alate za web razvoj, ali što to zapravo znači? Izraz kakav smo upoznali potječe od reaktivnog manifesta, koji definira reaktivni sustav kao četiri osnovne osobine:

  1. Reaktivni sustavi reagiraju , što znači da odgovaraju pravovremeno, u svim mogućim okolnostima. Usredotočeni su na pružanje brzog i dosljednog vremena odgovora, uspostavljanja pouzdanih gornjih granica kako bi pružili dosljednu kvalitetu usluge.
  2. Reaktivni sustavi su elastični , što znači da ostaju osjetljivi u slučaju kvara. Otpornost se postiže tehnikama replikacije, zadržavanja, izolacije i delegiranja. Izoliranjem komponenata aplikacije jedni od drugih možete spriječiti kvarove i zaštititi sustav u cjelini.
  3. Reaktivni sustavi su elastični , što znači da ostaju reaktivni pod različitim opterećenjima. To se postiže elastičnim skaliranjem komponenata aplikacije kako bi se zadovoljile trenutne potrebe.
  4. Reaktivni sustavi vođeni su porukama , što znači da se oslanjaju na asinkronu poruku koja prolazi između komponenata. To vam omogućuje stvaranje labavog spajanja, izolacije i transparentnosti mjesta.

Na slici 2 prikazano je kako se te osobine teku zajedno u reaktivnom sustavu.

Steven Haines

Karakteristike reaktivnog sustava

Reaktivni sustavi grade se stvaranjem izoliranih komponenata koje asinhrono komuniciraju jedna s drugom i mogu se brzo prilagoditi trenutnom opterećenju. Komponente i dalje ne uspijevaju u reaktivnim sustavima, ali postoje definirane radnje koje treba izvršiti kao rezultat tog kvara, što sustav čini cjelovitim funkcionalnim i osjetljivim.

Reaktivni manifest je sažetak, a reaktivni aplikacije obično karakteriziraju slijedeće komponente ili tehnika:

  • Tokovi podataka : Tok je slijed događaja raspoređenih u vremenu, poput korisničkih interakcija, poziva usluge REST, JMS poruka i rezultata iz baze podataka.
  • Asinkroni : događaji toka podataka snimaju se asinkrono i vaš kôd definira što učiniti kada se događaj emitira, kada se dogodi pogreška i kada se tok događaja dovrši.
  • Neblokiranje : Dok obrađujete događaje, vaš kôd ne bi trebao blokirati i izvoditi sinkrone pozive; umjesto toga, trebao bi upućivati ​​asinkrone pozive i odgovarati kad se vrate rezultati tih poziva.
  • Protutlak : Komponente kontroliraju broj događaja i koliko često se emitiraju. U reakcijskom smislu, vaša se komponenta naziva pretplatnikom, a događaje emitira izdavač . To je važno jer pretplatnik kontrolira koliko podataka prima i time se neće preopteretiti.
  • Poruke kvara : Umjesto komponenata koje bacaju iznimke, kvarovi se šalju kao poruke funkciji rukovatelja. Dok izbacivanje iznimki prekida tok, definiranje funkcije za rukovanje kvarovima kad se pojave ne čini.

API reaktivnih struja

Novi API za reaktivni tok stvorili su, između ostalih, inženjeri iz Netflixa, Pivotala, Lightbenda, RedHata, Twittera i Oraclea. Objavljen 2015., Reactive Streams API sada je dio Jave 9. Definira četiri sučelja:

  • Izdavač : pretplatnicima emitira slijed događaja.
  • Pretplatnik : prima i obrađuje događaje koje emitira izdavač.
  • Pretplata : definira odnos jedan-na-jedan između izdavača i pretplatnika.
  • Obrađivač : Predstavlja fazu obrade koja se sastoji od pretplatnika i izdavača i poštuje ugovore oba.

Slika 3 prikazuje odnos između izdavača, pretplatnika i pretplate.

Steven Haines

U osnovi pretplatnik stvara pretplatu izdavaču i kad izdavač ima dostupne podatke, pretplatniku šalje događaj s nizom elemenata. Imajte na umu da pretplatnik upravlja svojim povratnim pritiskom unutar svoje pretplate na izdavača.

Sad kad znate malo o reaktivnim sustavima i API-ju reaktivnih tokova, usmjerimo pažnju na alate koje Spring koristi za implementaciju reaktivnih sustava: Spring WebFlux i knjižnicu Reactor.

Projektni reaktor

Project Reactor je nezavisni okvir zasnovan na Javinoj specifikaciji reaktivnih tokova, koji se koristi za izgradnju neblokirajućih web aplikacija. Project Reactor nudi dva izdavača koja se intenzivno koriste u Spring WebFluxu:

  • Mono : Vraća 0 ili 1 element.
  • Tok : Vraća 0 ili više elemenata. Flux može biti beskrajan, što znači da može zauvijek emitirati elemente ili može vratiti niz elemenata, a zatim poslati obavijest o dovršenju kada vrati sve svoje elemente.

Monos i fluksi su konceptualno slični futuresima, ali moćniji. Kada pozovete funkciju koja vraća mono ili fluks, ona će se odmah vratiti. Rezultati funkcijskog poziva dostavit će vam se mono ili fluksom kad postanu dostupni.

U proljetnom WebFluxu nazvat ćete reaktivne knjižnice koje vraćaju monos i flukseve, a vaši će kontroleri vraćati monos i flukseve. Budući da se vraćaju odmah, vaši će se kontrolori učinkovito odreći svojih niti i omogućiti Reaktoru da asinkrono obrađuje odgovore. Važno je napomenuti da samo pomoću reaktivnih knjižnica vaše WebFlux usluge mogu ostati reaktivne. Ako koristite nereaktivne knjižnice, poput JDBC poziva, vaš će kôd blokirati i pričekati da se ti pozivi dovrše prije povratka.

Reaktivno programiranje s MongoDB-om

Trenutno nema mnogo knjižnica reaktivne baze podataka, pa se možda pitate je li praktično pisati reaktivne usluge. Dobra vijest je da MongoDB ima reaktivnu podršku i da postoji nekoliko nezavisnih pokretačkih programa baze podataka za MySQL i Postgres. Za sve ostale slučajeve upotrebe, WebFlux pruža mehanizam za izvršavanje JDBC poziva na reaktivan način, iako koristeći sekundarno spremište niti koje čini blokiranje JDBC poziva.

Započnite s Spring WebFluxom

Za naš prvi primjer rada, stvorit ćemo jednostavnu uslugu knjiga koja reaktivno drži knjige do i iz MongoDB-a.

Započnite s navigacijom na početnu stranicu Spring Initializr, gdje ćete odabrati Maven projekt s Javom i odabrati najnovije izdanje Spring Boot (2.0.3 u vrijeme pisanja ovog članka). Dajte projektu naziv grupe, poput "com.javaworld.webflux" i naziv artefakta, poput "bookservice". Proširite vezu Prebaci na punu verziju da biste prikazali cjelovit popis ovisnosti. Odaberite sljedeće ovisnosti za primjer aplikacije:

  • Web -> Reaktivni web : Ova ovisnost uključuje Spring WebFlux.
  • NoSQL -> Reactive MongoDB : Ova ovisnost uključuje reaktivne pokretačke programe za MongoDB.
  • NoSQL -> Ugrađeni MongoDB : Ova ovisnost omogućuje nam pokretanje ugrađene verzije MongoDB, tako da nema potrebe za instaliranjem zasebne instance. Obično se ovo koristi za testiranje, ali mi ćemo ga uključiti u naš kôd izdanja kako bismo izbjegli instaliranje MongoDB-a.
  • Jezgra -> Lombok : Korištenje Lomboka nije obavezno jer vam nije potreban za izradu Spring WebFlux aplikacije. Prednost korištenja Project Lombok je da vam omogućuje da dodate komentare na nastavu koja će automatski generirati getters i setters, graditelja, hashCode(), equals()i još mnogo toga.

Kad završite, trebali biste vidjeti nešto slično slici 4.

Steven Haines

Pritiskom na Generate Project pokrenut će se preuzimanje zip datoteke koja sadrži izvorni kod vašeg projekta. Raspakirajte preuzetu datoteku i otvorite je u svom omiljenom IDE-u. Ako koristite IntelliJ, odaberite File, a zatim Open i prijeđite na direktorij u kojem je preuzeta zip datoteka dekomprimirana.

Otkrićete da je Spring Initializr generirao dvije važne datoteke:

  1. Datoteka Maven pom.xmlkoja uključuje sve potrebne ovisnosti za aplikaciju.
  2. BookserviceApplication.java, što je početna klasa Spring Boot za aplikaciju.

Popis 1 prikazuje sadržaj generirane datoteke pom.xml.