Spring WebClient vs. RestTemplate

REST Top

Jeg har lige annonceret det nye Lær foråret kursus med fokus på det grundlæggende i Spring 5 og Spring Boot 2:

>> KONTROLLER KURSEN

1. Introduktion

I denne vejledning skal vi sammenligne to af Spring's implementeringer af webklienter - RestTemplate og det nye Spring 5s reaktive alternativ Webklient.

2. Blokering mod ikke-blokerende klient

Det er et almindeligt krav i webapplikationer at foretage HTTP-opkald til andre tjenester. Derfor har vi brug for et webklientværktøj.

2.1. RestTemplate Blokerende klient

I lang tid har Spring tilbudt RestTemplate som en webklientabstraktion. Under kølerhjelmen, RestTemplate bruger Java Servlet API, som er baseret på modellen thread-per-request.

Dette betyder, at tråden blokerer, indtil webklienten modtager svaret. Problemet med blokeringskoden skyldes, at hver tråd bruger en vis mængde hukommelse og CPU-cyklusser.

Lad os overveje at have mange indgående anmodninger, som venter på en langsom service, der er nødvendig for at producere resultatet.

Før eller senere vil anmodningerne, der venter på resultaterne, bunke op. Derfor opretter applikationen mange tråde, som udtømmer trådpuljen eller optager al den tilgængelige hukommelse. Vi kan også opleve ydelsesforringelse på grund af den hyppige skift mellem CPU-kontekst (tråd).

2.2. Webklient Ikke-blokerende klient

På den anden side, Webklient bruger en asynkron, ikke-blokerende løsning leveret af Spring Reactive framework.

Mens RestTemplate bruger opkaldstråden til hver begivenhed (HTTP-opkald), Webklient vil skabe noget som en "opgave" for hver begivenhed. Bag kulisserne sætter den reaktive ramme disse “opgaver” i kø og udfører dem kun, når det passende svar er tilgængeligt.

Den reaktive ramme bruger en hændelsesdrevet arkitektur. Det giver midler til at komponere asynkron logik via Reactive Streams API. Som et resultat kan den reaktive tilgang behandle mere logik, mens der bruges færre tråde og systemressourcer sammenlignet med den synkrone / blokerende metode.

Webklient er en del af Spring WebFlux-biblioteket. Derfor, Vi kan desuden skrive klientkode ved hjælp af en funktionel, flydende API med reaktive typer (Mono og Strøm) som en deklarativ sammensætning.

3. Sammenligningseksempel

For at demonstrere forskellene mellem disse to tilgange er vi nødt til at køre præstationstest med mange samtidige klientanmodninger. Vi ville se en betydelig præstationsnedbrydning med blokeringsmetoden efter et bestemt antal parallelle klientanmodninger.

På den anden side skal den reaktive / ikke-blokerende metode give konstant ydeevne, uanset antallet af anmodninger.

Med henblik på denne artikel, lad os implementere to REST-slutpunkter, en ved hjælp af RestTemplate og den anden bruger Webklient. Deres opgave er at ringe til en anden langsom REST-webservice, som returnerer en liste over tweets.

Til at begynde med har vi brug for Spring Boot WebFlux startafhængighed:

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

Herudover er her vores langsomme service REST-slutpunkt:

@GetMapping ("/ slow-service-tweets") privat liste getAllTweets () {Thread.sleep (2000L); // forsinkelse af returnering af Arrays.asList (nyt Tweet ("RestTemplate regler", "@ bruger1"), nyt Tweet ("WebClient er bedre", "@ bruger2"), nyt Tweet ("OK, begge er nyttige", "@ bruger1 ")); }

3.1. Ved brug af RestTemplate at ringe til en langsom service

Lad os nu implementere et andet REST-slutpunkt, som kalder vores langsomme service via webklienten.

For det første bruger vi RestTemplate:

@GetMapping ("/ tweets-blocking") offentlig liste getTweetsBlocking () {log.info ("Starter BLOCKING Controller!"); endelig String uri = getSlowServiceUri (); RestTemplate restTemplate = ny RestTemplate (); SvarEnhed respons = restTemplate.exchange (uri, HttpMethod.GET, null, ny ParameterizedTypeReference() {}); Listeresultat = respons.getBody (); result.forEach (tweet -> log.info (tweet.toString ())); log.info ("Afslut BLOCKING Controller!"); returresultat }

Når vi kalder dette slutpunkt på grund af den synkrone karakter af RestTemplate, koden blokerer for at vente på svaret fra vores langsomme service. Først når svaret er modtaget, udføres resten af ​​koden i denne metode. I logfilerne ser vi:

Start af BLOCKING Controller! Tweet (tekst = RestTemplate-regler, [e-mail-beskyttet]) Tweet (tekst = WebClient er bedre, [e-mail-beskyttet]) Tweet (tekst = OK, begge er nyttige, [e-mail-beskyttet]) Afslut BLOCKING Controller!

3.2. Ved brug af Webklient at ringe til en langsom service

For det andet, lad os bruge Webklient at ringe til den langsomme tjeneste:

@GetMapping (værdi = "/ tweets-ikke-blokering", producerer = MediaType.TEXT_EVENT_STREAM_VALUE) offentlig Flux getTweetsNonBlocking () {log.info ("Start NON-BLOCKING Controller!"); Flux tweetFlux = WebClient.create () .get () .uri (getSlowServiceUri ()). Hent () .bodyToFlux (Tweet.class); tweetFlux.subscribe (tweet -> log.info (tweet.toString ())); log.info ("Afslut NON-BLOCKING Controller!"); returner tweetFlux; }

I dette tilfælde, Webklient returnerer a Strøm udgiver og metodeudførelsen bliver afsluttet. Når resultatet er tilgængeligt, begynder udgiveren at udsende tweets til sine abonnenter. Bemærk, at en klient (i dette tilfælde en webbrowser) kalder på dette / tweets-ikke-blokering slutpunkt abonnerer også på det returnerede Strøm objekt.

Lad os observere loggen denne gang:

Starter NON-BLOCKING Controller! Afslut NON-BLOCKING Controller! Tweet (tekst = RestTemplate-regler, [e-mail-beskyttet]) Tweet (tekst = WebClient er bedre, [e-mail-beskyttet]) Tweet (tekst = OK, begge er nyttige, [e-mail-beskyttet])

Bemærk, at denne slutpunktsmetode er afsluttet, før svaret blev modtaget.

4. Konklusion

I denne artikel udforskede vi to forskellige måder at bruge webklienter på foråret.

RestTemplate bruger Java Servlet API og er derfor synkron og blokerer. I modsætning hertil Webklient er asynkron og blokerer ikke den udførende tråd, mens den venter på, at svaret vender tilbage. Først når svaret er klart, vil meddelelsen blive produceret.

RestTemplate vil stadig blive brugt. I nogle tilfælde bruger den ikke-blokerende tilgang meget færre systemressourcer sammenlignet med den blokerende. Derfor i disse tilfælde Webklient er et foretrukket valg.

Alle kodestykker, der er nævnt i artiklen, kan findes på GitHub.

REST bunden

Jeg har lige annonceret det nye Lær foråret kursus med fokus på det grundlæggende i Spring 5 og Spring Boot 2:

>> KONTROLLER KURSEN

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