Spring WebClient vs. RestTemplate

REST Top

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

>> LIHAT KURSUSnya

1. Perkenalan

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

2. Klien Pemblokiran vs. Non-Pemblokiran

Ini adalah persyaratan umum dalam aplikasi web untuk membuat panggilan HTTP ke layanan lain. Oleh karena itu, diperlukan alat klien web.

2.1. RestTemplate Blocking Client

Untuk waktu yang lama, Spring telah menawarkan RestTemplate sebagai abstraksi klien web. Di balik terpal , RestTemplate menggunakan Java Servlet API, yang didasarkan pada model thread-per-request .

Ini berarti bahwa utas akan memblokir hingga klien web menerima respons. Masalah dengan kode pemblokiran ini karena setiap utas memakan sejumlah memori dan siklus CPU.

Mari pertimbangkan untuk memiliki banyak permintaan masuk, yang menunggu beberapa layanan lambat yang diperlukan untuk memberikan hasil.

Cepat atau lambat, permintaan menunggu hasil akan menumpuk. Akibatnya, aplikasi akan membuat banyak utas, yang akan menghabiskan kumpulan utas atau menempati semua memori yang tersedia . Kami juga dapat mengalami penurunan kinerja karena seringnya peralihan konteks CPU (utas).

2.2. WebClient Non-Blocking Client

Di sisi lain, WebClient menggunakan solusi asinkron, non-pemblokiran yang disediakan oleh framework Spring Reactive .

Sementara RestTemplate menggunakan utas pemanggil untuk setiap peristiwa (panggilan HTTP), WebClient akan membuat sesuatu seperti "tugas" untuk setiap peristiwa. Di balik layar, kerangka kerja Reaktif akan mengantrekan "tugas" tersebut dan menjalankannya hanya jika respons yang sesuai tersedia.

Kerangka kerja Reaktif menggunakan arsitektur berbasis peristiwa. Ini menyediakan sarana untuk menulis logika asynchronous melalui Reactive Streams API. Hasilnya, pendekatan reaktif dapat memproses lebih banyak logika sambil menggunakan lebih sedikit utas dan sumber daya sistem, dibandingkan dengan metode sinkron / pemblokiran.

WebClient adalah bagian dari pustaka Spring WebFlux. Oleh karena itu, kami juga dapat menulis kode klien menggunakan API yang berfungsi dan lancar dengan tipe reaktif ( Mono dan Flux ) sebagai komposisi deklaratif .

3. Contoh Perbandingan

Untuk mendemonstrasikan perbedaan antara kedua pendekatan ini, kita perlu menjalankan tes kinerja dengan banyak permintaan klien yang bersamaan. Kami akan melihat penurunan kinerja yang signifikan dengan metode pemblokiran setelah sejumlah permintaan klien paralel tertentu.

Di sisi lain, metode reaktif / non-pemblokiran harus memberikan kinerja yang konstan, terlepas dari jumlah permintaan.

Untuk keperluan artikel ini, mari mengimplementasikan dua titik akhir REST, satu menggunakan RestTemplate dan yang lainnya menggunakan WebClient . Tugas mereka adalah memanggil layanan web REST lambat lainnya, yang mengembalikan daftar tweet.

Sebagai permulaan, kita memerlukan ketergantungan starter WebFlux Boot Spring:

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

Selanjutnya, inilah titik akhir REST layanan 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 Layanan Lambat

Sekarang mari menerapkan titik akhir REST lain yang akan memanggil layanan lambat kita melalui klien 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; }
     
    

Ketika kami memanggil titik akhir ini, karena sifat sinkron dari RestTemplate , kode akan memblokir menunggu respons dari layanan kami yang lambat. Hanya ketika respon telah diterima, sisa kode dalam metode ini akan dieksekusi. Di 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 Layanan Lambat

Kedua, mari gunakan WebClient untuk memanggil layanan lambat:

@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 kasus ini, WebClient mengembalikan penerbit Flux dan eksekusi metode diselesaikan. Setelah hasilnya tersedia, penerbit akan mulai mengirimkan tweet ke pelanggannya. Perhatikan bahwa klien (dalam hal ini, browser web) yang memanggil titik akhir / tweets-non-blocking ini juga akan berlangganan objek Flux yang dikembalikan .

Mari kita amati 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 bahwa metode titik akhir ini selesai sebelum respons diterima.

4. Kesimpulan

Pada artikel ini, kami menjelajahi dua cara berbeda dalam menggunakan klien web di Spring.

RestTemplate menggunakan Java Servlet API dan oleh karena itu sinkron dan memblokir. Sebaliknya, WebClient adalah asynchronous dan tidak akan memblokir thread yang mengeksekusi sambil menunggu respon kembali. Hanya jika tanggapan sudah siap, pemberitahuan akan dibuat.

RestTemplate akan tetap digunakan. Dalam beberapa kasus, pendekatan non-pemblokiran menggunakan sumber daya sistem yang jauh lebih sedikit dibandingkan dengan pendekatan pemblokiran. Karenanya, dalam kasus tersebut, WebClient adalah pilihan yang lebih disukai.

Semua potongan kode, yang disebutkan dalam artikel, dapat ditemukan di GitHub.

REST bawah

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

>> LIHAT KURSUSnya