Programování

Mastering Spring framework 5, Part 2: Spring WebFlux

Spring WebFlux zavádí reaktivní vývoj webu do jarního ekosystému. Tento článek vás seznámí s reaktivními systémy a reaktivním programováním pomocí Spring. Nejprve zjistíte, proč jsou reaktivní systémy důležité a jak jsou implementovány v jarním rámci 5, poté získáte praktický úvod do budování reaktivních služeb pomocí Spring WebFlux. Vytvoříme naši první reaktivní aplikaci pomocí anotací. Ukážu vám také, jak vytvořit podobnou aplikaci pomocí novějších funkčních funkcí Spring.

Jarní výukové programy o prostředí JavaWorld

Pokud jste v jarním rámci noví, doporučuji začít s jedním z dřívějších tutoriálů v této sérii:

  • Co je jaro? Vývoj komponent pro Javu
  • Mastering Spring framework 5: Spring MVC

Reaktivní systémy a Spring WebFlux

Termín reaktivní je v současné době oblíbený u vývojářů a IT manažerů, ale všiml jsem si určité nejistoty ohledně toho, co to vlastně znamená. Abyste získali jasnější představu o tom, co jsou reaktivní systémy, je užitečné pochopit základní problém, který mají řešit. V této části budeme hovořit o reaktivních systémech obecně a představím API Reactive Streams pro aplikace Java.

Škálovatelnost na jaře MVC

Jarní MVC si vydobylo místo mezi nejlepšími volbami pro vytváření webových aplikací a webových služeb Java. Jak jsme zjistili v Mastering Spring Framework 5, část 1, Spring MVC bezproblémově integruje anotace do robustní architektury aplikace založené na Spring. To umožňuje vývojářům obeznámeným s Springem rychle vytvářet uspokojivé a vysoce funkční webové aplikace. Škálovatelnost je pro aplikace Spring MVC výzvou. To je problém, který se Spring WebFlux snaží řešit.

Blokování vs neblokující webové rámce

Když v tradičních webových aplikacích webový server obdrží požadavek od klienta, přijme tento požadavek a umístí jej do exekuční fronty. Vlákno ve fondu podprocesů prováděcí fronty poté obdrží požadavek, načte jeho vstupní parametry a vygeneruje odpověď. Na cestě, pokud vykonávací vlákno potřebuje zavolat blokovací prostředek - například databázi, souborový systém nebo jinou webovou službu - toto vlákno provede požadavek blokování a čeká na odpověď. V tomto paradigmatu je vlákno účinně blokováno, dokud externí prostředek neodpoví, což způsobí problémy s výkonem a omezí škálovatelnost. V boji proti těmto problémům vývojáři vytvářejí velkoryse dimenzované fondy vláken, takže zatímco jedno vlákno je blokováno, jiné vlákno může pokračovat ve zpracování požadavků. Obrázek 1 ukazuje průběh provádění pro tradiční blokující webovou aplikaci.

Steven Haines

Neblokující webové rámce, jako je NodeJS a Play, používají jiný přístup. Namísto provedení požadavku na blokování a čekání na jeho dokončení používají neblokující I / O. V tomto paradigmatu aplikace provede požadavek, poskytne kód, který se provede při vrácení odpovědi, a poté vrátí své vlákno zpět na server. Když externí prostředek vrátí odpověď, bude spuštěn zadaný kód. Neblokující rámce interně fungují pomocí smyčky událostí. V rámci smyčky poskytuje kód aplikace buď zpětné volání, nebo budoucnost obsahující kód, který se má provést po dokončení asynchronní smyčky.

Neblokující rámce přirozeně jsou událost-řízený. To vyžaduje jiné paradigma programování a nový přístup k uvažování o tom, jak bude váš kód spuštěn. Jakmile to omotáte hlavou, reaktivní programování může vést k velmi škálovatelným aplikacím.

Zpětná volání, sliby a futures

V prvních dnech JavaScript zpracovával všechny asynchronní funkce prostřednictvím zpětná volání. V tomto scénáři, když dojde k události (například když bude k dispozici odpověď od volání služby), je provedeno zpětné volání. Zatímco zpětná volání stále převládají, asynchronní funkce JavaScriptu se nedávno přesunula do sliby. U slibů se volání funkce vrátí okamžitě a vrátí slib, že výsledky budou doručeny v budoucnu. Spíše než sliby implementuje Java podobné paradigma pomocí futures. V tomto použití metoda vrátí budoucnost, která bude mít hodnotu někdy v budoucnosti.

Reaktivní programování

Možná jste ten výraz už slyšeli reaktivní programování související s vývojovými rámci a nástroji pro web, ale co to ve skutečnosti znamená? Termín, jak jsme ho poznali, pochází z Reaktivního manifestu, který definuje reaktivní systémy jako čtyři základní rysy:

  1. Reaktivní systémy jsou citlivý, což znamená, že reagují včas a za všech možných okolností. Zaměřují se na poskytování rychlých a konzistentních dob odezvy, stanovení spolehlivých horních mezí, aby poskytovali konzistentní kvalitu služeb.
  2. Reaktivní systémy jsou pružný, což znamená, že zůstávají pohotové tváří v tvář neúspěchu. Odolnosti je dosaženo technikami replikace, omezení, izolace a delegování. Izolováním komponent aplikace od sebe navzájem můžete obsahovat chyby a chránit systém jako celek.
  3. Reaktivní systémy jsou elastický, což znamená, že zůstávají pohotové při různých pracovních zátěžích. Toho je dosaženo elastickým škálováním komponent aplikace, aby byla uspokojena aktuální poptávka.
  4. Reaktivní systémy jsou řízeno zprávami, což znamená, že se spoléhají na asynchronní předávání zpráv mezi komponentami. To vám umožní vytvořit volné propojení, izolaci a průhlednost umístění.

Obrázek 2 ukazuje, jak tyto vlastnosti proudí společně v reaktivním systému.

Steven Haines

Vlastnosti reaktivního systému

Reaktivní systémy jsou vytvářeny vytvářením izolovaných komponent, které navzájem komunikují asynchronně a mohou rychle škálovat, aby vyhověly aktuální zátěži. Komponenty stále selhávají v reaktivních systémech, ale existují definované akce, které je třeba provést v důsledku tohoto selhání, což udržuje systém jako celek funkční a citlivý.

The Reaktivní manifest je abstraktní, ale reaktivní aplikace se obvykle vyznačují následujícími komponentami nebo technikami:

  • Datové toky: A proud je posloupnost událostí seřazených v čase, jako jsou interakce uživatelů, volání služby REST, zprávy JMS a výsledky z databáze.
  • Asynchronní: Události datového proudu jsou zachyceny asynchronně a váš kód definuje, co dělat, když je vydána událost, když dojde k chybě a když je proud událostí dokončen.
  • Neblokující: Při zpracování událostí by váš kód neměl blokovat a provádět synchronní volání; místo toho by měl provádět asynchronní volání a reagovat, jakmile budou výsledky těchto hovorů vráceny.
  • Zpětný tlak: Komponenty řídí počet událostí a frekvenci jejich vysílání. Reaktivně řečeno, vaše součást je označována jako odběratel a události jsou emitovány a vydavatel. To je důležité, protože předplatitel má kontrolu nad tím, kolik dat dostává, a tím se sám nepřetíží.
  • Zprávy o selhání: Namísto komponent vyvolávajících výjimky se selhání odesílají jako zprávy do funkce obslužné rutiny. Vzhledem k tomu, že vyvolání výjimek přeruší stream, definování funkce pro zpracování selhání při jejich výskytu není.

Reaktivní proudy API

Nové rozhraní Reactive Streams API vytvořili mimo jiné inženýři ze společností Netflix, Pivotal, Lightbend, RedHat, Twitter a Oracle. Publikováno v roce 2015, rozhraní Reactive Streams API je nyní součástí Java 9. Definuje čtyři rozhraní:

  • Vydavatel: Vydává sled událostí předplatitelům.
  • Odběratel: Přijímá a zpracovává události emitované vydavatelem.
  • Předplatné: Definuje vztah 1: 1 mezi vydavatelem a předplatitelem.
  • Procesor: Představuje fázi zpracování skládající se jak z předplatitele, tak z vydavatele a řídí se smlouvami obou.

Obrázek 3 ukazuje vztah mezi vydavatelem, předplatitelem a předplatným.

Steven Haines

V zásadě Subscriber vytvoří předplatné Publisherovi a když má Publisher k dispozici data, odešle událost Subscriberu s proudem prvků. Všimněte si, že předplatitel spravuje svůj protitlak uvnitř svého předplatného vydavateli.

Nyní, když víte něco o reaktivních systémech a rozhraní Reactive Streams API, zaměřme naši pozornost na nástroje, které Spring používá k implementaci reaktivních systémů: Spring WebFlux a knihovna Reactor.

Projektový reaktor

Project Reactor je rámec třetí strany založený na specifikaci Java Reactive Streams, která se používá k vytváření neblokujících webových aplikací. Project Reactor poskytuje dva vydavatele, kteří se v jarním WebFluxu hodně používají:

  • Mono: Vrátí 0 nebo 1 prvek.
  • Flux: Vrátí 0 nebo více prvků. Flux může být nekonečný, což znamená, že může emitovat prvky navždy, nebo může vrátit posloupnost prvků a poté odeslat oznámení o dokončení, když vrátí všechny své prvky.

Monos a toky jsou koncepčně podobné futures, ale silnější. Když vyvoláte funkci, která vrací mono nebo tok, vrátí se okamžitě. Výsledky volání funkce vám budou doručeny prostřednictvím mono nebo toku, jakmile budou k dispozici.

Na jaře WebFlux zavoláte reaktivní knihovny, které vracejí monos a toky a vaše ovladače vrátí monos a toky. Protože se tyto vrátí okamžitě, vaše řadiče se efektivně vzdají svých vláken a umožní Reactoru zpracovat odpovědi asynchronně. Je důležité si uvědomit, že pouze pomocí reaktivních knihoven mohou vaše služby WebFlux zůstat reaktivní. Pokud používáte nereaktivní knihovny, například volání JDBC, váš kód se zablokuje a před návratem počká na dokončení těchto hovorů.

Reaktivní programování s MongoDB

V současné době není mnoho reaktivních databázových knihoven, takže vás možná zajímá, jestli je praktické psát reaktivní služby. Dobrou zprávou je, že MongoDB má reaktivní podporu a pro MySQL a Postgres existuje několik reaktivních databázových ovladačů třetích stran. Pro všechny ostatní případy použití poskytuje WebFlux mechanismus pro reaktivní provádění hovorů JDBC, i když používá fond sekundárních vláken, který blokuje volání JDBC.

Začněte s Spring WebFlux

Pro náš první příklad postupu vytvoříme jednoduchou knižní službu, která reaktivně uchová knihy do a z MongoDB.

Začněte tím, že přejdete na domovskou stránku Spring Initializr, kde vyberete a Maven projekt s Jáva a vyberte nejaktuálnější verzi Spring Boot (2.0.3 v době tohoto psaní). Pojmenujte svůj projekt názvem skupiny, například „com.javaworld.webflux“ a názvem artefaktu, například „bookservice“. Rozbalte Přepněte na plnou verzi odkaz pro zobrazení úplného seznamu závislostí. Vyberte následující závislosti pro příklad aplikace:

  • Web -> Reaktivní web: Tato závislost zahrnuje Spring WebFlux.
  • NoSQL -> Reaktivní MongoDB: Tato závislost zahrnuje reaktivní ovladače pro MongoDB.
  • NoSQL -> Embedded MongoDB: Tato závislost nám umožňuje spustit vloženou verzi MongoDB, takže není nutné instalovat samostatnou instanci. Obvykle se to používá pro testování, ale zahrneme to do našeho kódu vydání, abychom se vyhnuli instalaci MongoDB.
  • Jádro -> Lombok: Používání Lomboku je volitelné, protože ho nepotřebujete k vytváření aplikace Spring WebFlux. Výhodou použití Project Lombok je, že umožňuje přidávat poznámky do tříd, které budou automaticky generovat getry a settery, konstruktory, hashCode (), se rovná(), a více.

Po dokončení byste měli vidět něco podobného obrázku 4.

Steven Haines

Lisování Vytvořit projekt spustí stahování souboru zip obsahujícího zdrojový kód projektu. Stažený soubor rozbalte a otevřete ve svém oblíbeném IDE. Pokud používáte IntelliJ, zvolte Soubor a pak Otevřenoa přejděte do adresáře, kde byl stažený soubor ZIP dekomprimován.

Zjistíte, že Spring Initializr vygeneroval dva důležité soubory:

  1. Maven pom.xml soubor, který obsahuje všechny nezbytné závislosti pro aplikaci.
  2. BookserviceApplication.java, což je spouštěcí třída Spring Boot pro aplikaci.

Výpis 1 zobrazuje obsah vygenerovaného souboru pom.xml.

$config[zx-auto] not found$config[zx-overlay] not found