Spring WebClient vs. RestTemplate

REST Topp

Jeg kunngjorde nettopp det nye Lær våren kurs, med fokus på det grunnleggende i vår 5 og vårstøvel 2:

>> KONTROLLER KURSET

1. Introduksjon

I denne opplæringen skal vi sammenligne to av Springs implementeringer av nettklienter - RestTemplate og nye Spring 5s reaktive alternativ WebClient.

2. Blokkering kontra ikke-blokkerende klient

Det er et vanlig krav i webapplikasjoner å foreta HTTP-anrop til andre tjenester. Derfor trenger vi et nettklientverktøy.

2.1. RestTemplate Blokkerer klient

I lang tid har Spring tilbudt RestTemplate som en webklientabstraksjon. Under panseret, RestTemplate bruker Java Servlet API, som er basert på tråden per forespørsel-modellen.

Dette betyr at tråden vil blokkere til nettklienten mottar svaret. Problemet med blokkeringskoden skyldes at hver tråd bruker litt mengde minne og CPU-sykluser.

La oss vurdere å ha mange innkommende forespørsler, som venter på litt treg service som trengs for å produsere resultatet.

Før eller senere vil forespørslene som venter på resultatene, hoper seg opp. Følgelig vil applikasjonen opprette mange tråder, som vil tømme trådrammen eller oppta alt tilgjengelig minne. Vi kan også oppleve ytelsesforringelse på grunn av den hyppige byttingen av CPU-kontekst (tråd).

2.2. WebClient Ikke-blokkerende klient

På den andre siden, WebClient bruker en asynkron, ikke-blokkerende løsning levert av Spring Reactive framework.

Samtidig som RestTemplate bruker innringertråden for hver hendelse (HTTP-samtale), WebClient vil skape noe sånt som en "oppgave" for hvert arrangement. Bak kulissene vil det reaktive rammeverket stille disse "oppgavene" i kø og utføre dem bare når riktig respons er tilgjengelig.

Reactive framework bruker en hendelsesdrevet arkitektur. Det gir midler til å komponere asynkron logikk gjennom Reactive Streams API. Som et resultat kan den reaktive tilnærmingen behandle mer logikk mens du bruker færre tråder og systemressurser, sammenlignet med den synkrone / blokkeringsmetoden.

WebClient er en del av Spring WebFlux-biblioteket. Derfor, Vi kan i tillegg skrive klientkode ved hjelp av en funksjonell, flytende API med reaktive typer (Mono og Flux) som en deklarativ komposisjon.

3. Sammenligningseksempel

For å demonstrere forskjellene mellom disse to tilnærmingene, må vi kjøre ytelsestester med mange samtidige klientforespørsler. Vi ser en betydelig ytelsesforringelse med blokkeringsmetoden etter et visst antall parallelle klientforespørsler.

På den andre siden skal den reaktive / ikke-blokkerende metoden gi konstante ytelser, uavhengig av antall forespørsler.

For formålet med denne artikkelen, la oss implementere to REST-endepunkter, den ene bruker RestTemplate og den andre bruker WebClient. Deres oppgave er å ringe til en annen treg REST-nettjeneste, som returnerer en liste over tweets.

Til å begynne med trenger vi Spring Boot WebFlux startavhengighet:

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

Videre er her vårt tregeste REST-endepunkt:

@GetMapping ("/ slow-service-tweets") privat liste getAllTweets () {Thread.sleep (2000L); // forsinker retur Arrays.asList (ny Tweet ("RestTemplate regler", "@ bruker1"), ny Tweet ("WebClient er bedre", "@ bruker2"), ny Tweet ("OK, begge er nyttige", "@ bruker1 ")); }

3.1. Ved hjelp av RestTemplate å ringe en langsom tjeneste

La oss nå implementere et annet REST-sluttpunkt som vil ringe til treg service via webklienten.

For det første skal vi bruke RestTemplate:

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

Når vi kaller dette endepunktet, på grunn av den synkrone naturen til RestTemplate, koden vil blokkere venter på svaret fra vår treg service. Først når svaret er mottatt, vil resten av koden i denne metoden bli utført. I loggene ser vi:

Starter BLOCKING Controller! Tweet (tekst = RestTemplate regler, [e-postbeskyttet]) Tweet (tekst = WebClient er bedre, [e-postbeskyttet]) Tweet (tekst = OK, begge er nyttige, [e-postbeskyttet]) Avslutter BLOCKING Controller!

3.2. Ved hjelp av WebClient å ringe en langsom tjeneste

For det andre, la oss bruke WebClient å ringe treg service:

@GetMapping (verdi = "/ tweets-ikke-blokkering", produserer = MediaType.TEXT_EVENT_STREAM_VALUE) offentlig Flux getTweetsNonBlocking () {log.info ("Starter IKKE-BLOKKERING-kontroller!"); Flux tweetFlux = WebClient.create () .get () .uri (getSlowServiceUri ()) .hent () .bodyToFlux (Tweet.class); tweetFlux.subscribe (tweet -> log.info (tweet.toString ())); log.info ("Avslutter ikke-blokkerende kontroller!"); returner tweetFlux; }

I dette tilfellet, WebClient returnerer a Flux utgiveren og metodeutførelsen blir fullført. Når resultatet er tilgjengelig, vil utgiveren begynne å sende tweets til sine abonnenter. Merk at en klient (i dette tilfellet en nettleser) kaller dette / tweets-ikke-blokkering endepunkt vil også abonnere på den returnerte Flux gjenstand.

La oss observere loggen denne gangen:

Starter NON-BLOCKING Controller! Gå ut av IKKE-BLOKKERENDE kontroller! Tweet (tekst = RestTemplate regler, [e-postbeskyttet]) Tweet (tekst = WebClient er bedre, [e-postbeskyttet]) Tweet (tekst = OK, begge er nyttige, [e-postbeskyttet])

Merk at denne endepunktmetoden ble fullført før svaret ble mottatt.

4. Konklusjon

I denne artikkelen undersøkte vi to forskjellige måter å bruke webklienter på våren.

RestTemplate bruker Java Servlet API og er derfor synkron og blokkerer. Motsatt, WebClient er asynkron og vil ikke blokkere den utførende tråden mens den venter på at svaret skal komme tilbake. Først når svaret er klart, vil meldingen bli produsert.

RestTemplate vil fortsatt bli brukt. I noen tilfeller bruker den ikke-blokkerende tilnærmingen mye færre systemressurser sammenlignet med den blokkerende. Derfor, i disse tilfellene, WebClient er et foretrukket valg.

Alle kodebitene, nevnt i artikkelen, finner du på GitHub.

HVILLE bunnen

Jeg kunngjorde nettopp det nye Lær våren kurs, med fokus på det grunnleggende i vår 5 og vårstøvel 2:

>> KONTROLLER KURSET

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