Spring WebClient vs. RestTemplate

REST Teratas

Saya baru sahaja mengumumkan kursus Learn Spring yang baru , yang berfokus pada asas-asas Spring 5 dan Spring Boot 2:

>> SEMAK KURSUS

1. Pengenalan

Dalam tutorial ini, kita akan membandingkan dua pelaksanaan klien web Spring - RestTemplate dan WebClient alternatif reaktif Spring 5 yang baru .

2. Pelanggan Sekatan vs Tidak Menyekat

Ini adalah syarat biasa dalam aplikasi web untuk membuat panggilan HTTP ke perkhidmatan lain. Oleh itu, kami memerlukan alat pelanggan web.

2.1. Pelanggan Sekatan RestTemplate

Sejak sekian lama, Spring telah menawarkan RestTemplate sebagai abstraksi pelanggan web. Di bawah kerangka , RestTemplate menggunakan Java Servlet API, yang berdasarkan model thread-per-request .

Ini bermaksud bahawa utas akan menyekat sehingga pelanggan web menerima respons. Masalah dengan kod penyekat adalah kerana setiap utas menghabiskan sejumlah memori dan kitaran CPU.

Mari pertimbangkan untuk mempunyai banyak permintaan masuk, yang menunggu beberapa perkhidmatan lambat yang diperlukan untuk menghasilkan hasilnya.

Cepat atau lambat, permintaan yang menunggu hasilnya akan menumpuk. Akibatnya, aplikasi akan membuat banyak utas, yang akan menghabiskan kolam utas atau memenuhi semua memori yang ada . Kami juga dapat mengalami penurunan prestasi kerana peralihan konteks CPU (thread) yang kerap.

2.2. Pelanggan Tanpa Sekatan WebClient

Di sisi lain, WebClient menggunakan penyelesaian tanpa sekatan yang tidak segerak yang disediakan oleh rangka kerja Spring Reactive .

Walaupun RestTemplate menggunakan utas pemanggil untuk setiap acara (panggilan HTTP), WebClient akan membuat sesuatu seperti "tugas" untuk setiap acara. Di sebalik tabir, kerangka Reaktif akan mengantarkan "tugas" tersebut dan melaksanakannya hanya apabila respons yang sesuai tersedia.

Kerangka Reaktif menggunakan seni bina berdasarkan peristiwa. Ini menyediakan kaedah untuk menyusun logik tak segerak melalui Reactive Streams API. Akibatnya, pendekatan reaktif dapat memproses lebih banyak logik sambil menggunakan lebih sedikit utas dan sumber sistem, berbanding dengan kaedah sinkronisasi / penyekat.

WebClient adalah sebahagian daripada perpustakaan Spring WebFlux. Oleh itu, kita juga dapat menulis kod pelanggan menggunakan API yang berfungsi dan lancar dengan jenis reaktif ( Mono dan Flux ) sebagai komposisi deklaratif .

3. Contoh Perbandingan

Untuk menunjukkan perbezaan antara kedua pendekatan ini, kami perlu menjalankan ujian prestasi dengan banyak permintaan pelanggan bersamaan. Kami akan melihat penurunan prestasi yang ketara dengan kaedah penyekat setelah sejumlah permintaan pelanggan selari.

Di sisi lain, kaedah reaktif / tidak menyekat harus memberikan persembahan berterusan, tanpa mengira jumlah permintaan.

Untuk tujuan artikel ini, mari kita laksanakan dua titik akhir REST, satu menggunakan RestTemplate dan yang lain menggunakan WebClient . Tugas mereka adalah memanggil perkhidmatan web REST yang lambat, yang mengembalikan senarai tweet.

Sebagai permulaan, kami memerlukan pergantungan pemula Spring Boot WebFlux:

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

Tambahan pula, inilah titik akhir REST perkhidmatan lambat kami:

@GetMapping("/slow-service-tweets") private List getAllTweets() { Thread.sleep(2000L); // delay return Arrays.asList( new Tweet("RestTemplate rules", "@user1"), new Tweet("WebClient is better", "@user2"), new Tweet("OK, both are useful", "@user1")); }

3.1. Menggunakan RestTemplate untuk Memanggil Perkhidmatan Lambat

Sekarang mari kita melaksanakan titik akhir REST lain yang akan memanggil perkhidmatan perlahan kami melalui pelanggan web.

Pertama, kami akan menggunakan RestTemplate :

@GetMapping("/tweets-blocking") public List getTweetsBlocking() { log.info("Starting BLOCKING Controller!"); final String uri = getSlowServiceUri(); RestTemplate restTemplate = new RestTemplate(); ResponseEntity
    
      response = restTemplate.exchange( uri, HttpMethod.GET, null, new ParameterizedTypeReference
     
      (){}); List result = response.getBody(); result.forEach(tweet -> log.info(tweet.toString())); log.info("Exiting BLOCKING Controller!"); return result; }
     
    

Apabila kita memanggil titik akhir ini, kerana sifat RestTemplate yang segerak , kod akan menyekat menunggu respons daripada perkhidmatan lambat kami. Hanya apabila maklum balas diterima, selebihnya kod dalam kaedah ini akan dilaksanakan. Dalam log, kita akan melihat:

Starting BLOCKING Controller! Tweet(text=RestTemplate rules, [email protected]) Tweet(text=WebClient is better, [email protected]) Tweet(text=OK, both are useful, [email protected]) Exiting BLOCKING Controller!

3.2. Menggunakan WebClient untuk Memanggil Perkhidmatan Lambat

Kedua, mari gunakan WebClient untuk memanggil perkhidmatan perlahan:

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

Dalam kes ini, WebClient mengembalikan penerbit Flux dan pelaksanaan kaedah selesai. Setelah hasilnya tersedia, penerbit akan mula mengeluarkan tweet kepada pelanggannya. Perhatikan bahawa pelanggan (dalam hal ini, penyemak imbas web) yang memanggil ini / tweet-tidak menyekat titik akhir juga akan dilanggan ke objek Flux yang dikembalikan .

Mari perhatikan log kali ini:

Starting NON-BLOCKING Controller! Exiting NON-BLOCKING Controller! Tweet(text=RestTemplate rules, [email protected]) Tweet(text=WebClient is better, [email protected]) Tweet(text=OK, both are useful, [email protected])

Perhatikan bahawa kaedah titik akhir ini selesai sebelum respons diterima.

4. Kesimpulan

Dalam artikel ini, kami meneroka dua cara penggunaan klien web yang berbeza pada musim bunga.

RestTemplate menggunakan Java Servlet API dan oleh itu segerak dan menyekat. Sebaliknya, WebClient tidak segerak dan tidak akan menyekat urutan pelaksanaan sementara menunggu tindak balas kembali. Hanya apabila respons siap, pemberitahuan akan dibuat.

RestTemplate masih akan digunakan. Dalam beberapa kes, pendekatan tidak menyekat menggunakan sumber sistem yang jauh lebih sedikit berbanding dengan pendekatan menyekat. Oleh itu, dalam kes tersebut, WebClient adalah pilihan yang lebih baik.

Semua coretan kod, yang disebutkan dalam artikel, terdapat di GitHub.

REST bawah

Saya baru sahaja mengumumkan kursus Learn Spring yang baru , yang berfokus pada asas-asas Spring 5 dan Spring Boot 2:

>> SEMAK KURSUS