91超碰碰碰碰久久久久久综合_超碰av人澡人澡人澡人澡人掠_国产黄大片在线观看画质优化_txt小说免费全本

溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

Spring WebClient vs. RestTemplate

發布時間:2020-07-21 21:21:14 來源:網絡 閱讀:624 作者:sq5d428a5a0584a 欄目:編程語言

1. 簡介

本教程中,我們將對比 Spring 的兩種 Web 客戶端實現 —— RestTemplate 和 Spring 5 中全新的 Reactive 替代方案 WebClient

2. 阻塞式 vs 非阻塞式客戶端

Web 應用中,對其他服務進行 HTTP 調用是一個很常見的需求。因此,我們需要一個 Web 客戶端工具。

2.1. RestTemplate 阻塞式客戶端

很長一段時間以來,Spring 一直提供 RestTemplate 作為 Web 客戶端抽象。在底層,RestTemplate 使用了基于每個請求對應一個線程模型(thread-per-request)的 Java Servlet API。

這意味著,直到 Web 客戶端收到響應之前,線程都將一直被阻塞下去。而阻塞代碼帶來的問題則是,每個線程都消耗了一定的內存和 CPU 周期。

讓我們考慮下有很多傳入請求,它們正在等待產生結果所需的一些慢服務。

等待結果的請求遲早都會堆積起來。因此,程序將創建很多線程,這些線程將耗盡線程池或占用所有可用內存。由于頻繁的 CPU 上下文(線程)切換,我們還會遇到性能下降的問題。

2.2. WebClient 非阻塞式客戶端

另一方面,WebClient 使用 Spring Reactive Framework 所提供的異步非阻塞解決方案。

RestTemplate 為每個事件(HTTP 請求)創建一個新的 線程 時,WebClient 將為每個事件創建類似于“任務”的東東。幕后,Reactive 框架將對這些 “任務” 進行排隊,并僅在適當的響應可用時執行它們。

Reactive 框架使用事件驅動的體系結構。它提供了通過 Reactive Streams API 組合異步邏輯的方法。因此,與同步/阻塞方法相比,Reactive 可以使用更少的線程和系統資源來處理更多的邏輯。

WebClient 是 Spring WebFlux 庫的一部分。因此,我們還可以使用流暢的函數式 API 編寫客戶端代碼,并將響應類型(Mono 和 Flux)作為聲明來進行組合。

3. 案例對比

為了演示兩種方法間的差異,我們需要使用許多并發客戶端請求來運行性能測試。在一定數量的并發請求后,我們將看到阻塞方法性能的顯著下降。

另一方面,無論請求數量如何,反應式/非阻塞方法都可以提供恒定的性能。

就本文而言,讓我們實現兩個 REST 端點,一個使用 RestTemplate,另一個使用 WebClient。他們的任務是調用另一個響應慢的 REST Web 服務,該服務返回一個 Tweet List。

首先,我們需要引入 Spring Boot WebFlux starter 依賴:

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-webflux</artifactId>
</dependency>

接下來,這是我們的慢服務 REST 端點:

@GetMapping("/slow-service-tweets")
private List<Tweet> 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. 使用 RestTemplate 調用慢服務

現在,讓我們來實現另一個 REST 端點,它將通過 Web 客戶端調用我們的慢服務。

首先,我們來使用 RestTemplate

@GetMapping("/tweets-blocking")
public List<Tweet> getTweetsBlocking() {
    log.info("Starting BLOCKING Controller!");
    final String uri = getSlowServiceUri();

    RestTemplate restTemplate = new RestTemplate();
    ResponseEntity<List<Tweet>> response = restTemplate.exchange(
      uri, HttpMethod.GET, null,
      new ParameterizedTypeReference<List<Tweet>>(){});

    List<Tweet> result = response.getBody();
    result.forEach(tweet -> log.info(tweet.toString()));
    log.info("Exiting BLOCKING Controller!");
    return result;
}

當我們調用這個端點時,由于 RestTemplate 的同步特性,代碼將會阻塞以等待來自慢服務的響應。只有當收到響應后,才會執行此方法中的其余代碼。通過日志,我們可以看到:

Starting BLOCKING Controller!
Tweet(text=RestTemplate rules, username=@user1)
Tweet(text=WebClient is better, username=@user2)
Tweet(text=OK, both are useful, username=@user1)
Exiting BLOCKING Controller!

3.2. 使用 WebClient 調用慢服務

其次,讓我們使用 WebClient 來調用慢服務:

@GetMapping(value = "/tweets-non-blocking", 
            produces = MediaType.TEXT_EVENT_STREAM_VALUE)
public Flux<Tweet> getTweetsNonBlocking() {
    log.info("Starting NON-BLOCKING Controller!");
    Flux<Tweet> 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;
}

本例中,WebClient 返回一個 Flux 生產者后完成方法的執行。一旦結果可用,發布者將開始向其訂閱者發送 tweets。注意,調用 /tweets-non-blocking 這個端點的客戶端(本例中的 Web 瀏覽器)也將訂閱返回的 Flux 對象。

讓我們來觀察這次的日志:

Starting NON-BLOCKING Controller!
Exiting NON-BLOCKING Controller!
Tweet(text=RestTemplate rules, username=@user1)
Tweet(text=WebClient is better, username=@user2)
Tweet(text=OK, both are useful, username=@user1)

注意,此端點的方法在收到響應之前就已完成。

4. 結論

本文中,我們探討了在 Spring 中使用 Web 客戶端的兩種不同方式。

RestTemplate 使用 Java Servlet API,因此是同步和阻塞的。相反,WebClient 是異步的,在等待響應返回時不會阻塞正在執行的線程。只有當程序就緒時,才會產生通知。

RestTemplate 仍將會被使用。但在某些情況下,與阻塞方法相比,非阻塞方法使用的系統資源要少得多。因此,在這些情況下,WebClient 不失為是更好的選擇。

文中提到的所有代碼片段,均可在 GitHub 上找到。

原文:<https://www.baeldung.com/spring-webclient-resttemplate>

作者:Drazen Nikolic

譯者:萬想

向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

AI

恩施市| 伊春市| 万盛区| 昌都县| 安宁市| 舒兰市| 黔西县| 鞍山市| 富源县| 永年县| 定南县| 陕西省| 西乌| 江都市| 翁源县| 台东县| 福清市| 襄樊市| 清远市| 恩平市| 石门县| 钟祥市| 伊金霍洛旗| 洮南市| 鹿邑县| 汤阴县| 普陀区| 托克逊县| 甘谷县| 宜君县| 临海市| 方山县| 正宁县| 兰西县| 浪卡子县| 全椒县| 宽甸| 福建省| 江津市| 北川| 昭苏县|