Spring WebClient vs. RestTemplate

OSTALO Vrh

Upravo sam najavio novo Uči proljeće tečaj, usredotočen na osnove Spring 5 i Spring Boot 2:

>> PROVJERITE TEČAJ

1. Uvod

U ovom uputstvu usporedit ćemo dvije implementacije Spring web klijenta - RestTemplate i nova reaktivna alternativa Spring 5 WebClient.

2. Blokiranje u odnosu na klijenta koji ne blokira

Uobičajeni je zahtjev u web aplikacijama upućivanje HTTP poziva drugim uslugama. Stoga nam je potreban alat web klijenta.

2.1. RestTemplate Blokiranje klijenta

Već dugo nudi proljeće RestTemplate kao apstrakcija web klijenta. Ispod haube, RestTemplate koristi Java Servlet API, koji se temelji na modelu nit po zahtjevu.

To znači da će se nit blokirati sve dok web klijent ne primi odgovor. Problem s kodom za blokiranje posljedica je što svaka nit troši određenu količinu memorije i CPU ciklusa.

Razmotrimo da imamo puno dolaznih zahtjeva koji čekaju na neku polaganu uslugu potrebnu za postizanje rezultata.

Prije ili kasnije, zahtjevi koji čekaju rezultate gomilat će se. Slijedom toga, aplikacija će stvoriti mnogo niti, što će iscrpiti spremište niti ili zauzeti svu dostupnu memoriju. Također možemo doživjeti pogoršanje performansi zbog čestog prebacivanja konteksta CPU-a (niti).

2.2. WebClient Klijent koji ne blokira

Na drugoj strani, WebClient koristi asinkrono, neblokirajuće rješenje koje pruža okvir Spring Reactive.

Dok RestTemplate koristi nit pozivatelja za svaki događaj (HTTP poziv), WebClient stvorit će nešto poput "zadatka" za svaki događaj. Iza kulisa, reaktivni će okvir staviti te "zadatke" u red i izvršiti ih samo kada bude dostupan odgovarajući odgovor.

Reactive framework koristi arhitekturu vođenu događajima. Pruža sredstva za sastavljanje asinkrone logike putem API-ja Reactive Streams. Kao rezultat, reaktivni pristup može obraditi više logike uz korištenje manje niti i sistemskih resursa, u usporedbi s metodom sinkronog / blokiranja.

WebClient dio je Spring WebFlux knjižnice. Stoga, možemo dodatno pisati klijentski kod pomoću funkcionalnog, fluidnog API-ja s reaktivnim vrstama (Mono i Fluks) kao deklarativni sastav.

3. Primjer usporedbe

Da bismo demonstrirali razlike između ova dva pristupa, trebali bismo pokrenuti testove izvedbe s mnogo istodobnih zahtjeva klijenta. Vidjeli bismo značajnu pogoršanje performansi s metodom blokiranja nakon određenog broja paralelnih zahtjeva klijenta.

S druge strane, reaktivna / neblokirajuća metoda treba davati stalne performanse, bez obzira na broj zahtjeva.

U svrhu ovog članka, implementiramo dvije REST krajnje točke, jednu pomoću RestTemplate a drugi pomoću WebClient. Njihov je zadatak nazvati još jednu sporu REST web uslugu koja vraća popis tweetova.

Za početak će nam trebati ovisnost o pokretaču Spring Boot WebFlux:

 org.springframework.boot spring-boot-starter-webflux 

Nadalje, evo krajnje točke REST usluge za sporo:

@GetMapping ("/ slow-service-tweets") privatni popis getAllTweets () {Thread.sleep (2000L); // odgoditi povratak Arrays.asList (novi Tweet ("RestTemplate rules", "@ user1"), novi Tweet ("WebClient je bolji", "@ user2"), novi Tweet ("U redu, oba su korisna", "@ korisnik1 ")); }

3.1. Koristeći RestTemplate nazvati sporu službu

Primijenimo sada još jednu REST krajnju točku koja će nazvati našu usporenu uslugu putem web klijenta.

Prvo ćemo upotrijebiti RestTemplate:

@GetMapping ("/ tweets-blocking") javni popis getTweetsBlocking () {log.info ("Pokretanje BLOCKING Controller!"); završni niz uri = getSlowServiceUri (); RestTemplate restTemplate = novi RestTemplate (); ResponseEntity response = restTemplate.exchange (uri, HttpMethod.GET, null, nova ParameterizedTypeReference() {}); Rezultat popisa = response.getBody (); result.forEach (tweet -> log.info (tweet.toString ())); log.info ("Izlaz iz kontrolera BLOKIRANJA!"); povratni rezultat; }

Kada zovemo ovu krajnju točku, zbog sinkrone prirode RestTemplate, kod će blokirati čekanje odgovora naše spore usluge. Tek kad je primljen odgovor, izvršit će se ostatak koda u ovoj metodi. U zapisnicima ćemo vidjeti:

Pokretanje programa BLOCKING Controller! Tweet (tekst = pravila za RestTemplate, [zaštićen e-poštom]) Tweet (tekst = WebClient je bolji, [zaštićen e-poštom]) Tweet (tekst = U redu, oba su korisna, [zaštićena e-poštom]) Izlaz iz BLOCKING Controllera!

3.2. Koristeći WebClient nazvati sporu službu

Drugo, poslužimo se WebClient da pozovete spor servis:

@GetMapping (value = "/ tweets-non-blocking", produce = MediaType.TEXT_EVENT_STREAM_VALUE) public Flux getTweetsNonBlocking () {log.info ("Start NON-BLOCKING Controller!"); Flux tweetFlux = WebClient.create () .get () .uri (getSlowServiceUri ()) .retrieve () .bodyToFlux (Tweet.class); tweetFlux.subscribe (tweet -> log.info (tweet.toString ())); log.info ("Izlaz iz NON-BLOCKING Controllera!"); povratak tweetFlux; }

U ovom slučaju, WebClient vraća a Fluks izdavač i izvršenje metode se dovršava. Nakon što rezultat bude dostupan, izdavač će početi emitirati tweetove svojim pretplatnicima. Imajte na umu da klijent (u ovom slučaju web preglednik) ovo zove / tweetovi-ne-blokiraju krajnja točka također će biti pretplaćena na vraćeni Fluks objekt.

Promotrimo zapisnik ovaj put:

Pokretanje NON-BLOCKING Controllera! Izlaz iz NON-BLOCKING Controllera! Tweet (tekst = pravila za RestTemplate, [zaštićena e-poštom]) Tweet (tekst = WebClient je bolji, [zaštićen e-poštom]) Tweet (tekst = U redu, oba su korisna, [zaštićena e-poštom])

Imajte na umu da je ova metoda krajnje točke dovršena prije nego što je primljen odgovor.

4. Zaključak

U ovom smo članku istražili dva različita načina korištenja web klijenata u proljeće.

RestTemplate koristi Java Servlet API i stoga je sinkron i blokira. Suprotno tome, WebClient je asinkrono i neće blokirati izvršnu nit dok čeka povratak odgovora. Obavijest će se dostaviti tek kada je odgovor spreman.

RestTemplate i dalje će se koristiti. U nekim slučajevima, pristup koji ne blokira koristi mnogo manje sistemskih resursa u odnosu na onaj koji blokira. Dakle, u tim slučajevima, WebClient je poželjniji izbor.

Svi isječci koda, spomenuti u članku, mogu se naći na GitHubu.

OSTALO dno

Upravo sam najavio novo Uči proljeće tečaj, usredotočen na osnove Spring 5 i Spring Boot 2:

>> PROVJERITE TEČAJ