真实的国产乱ⅩXXX66竹夫人,五月香六月婷婷激情综合,亚洲日本VA一区二区三区,亚洲精品一区二区三区麻豆

成都創(chuàng)新互聯(lián)網(wǎng)站制作重慶分公司

SpringWebClientvs.RestTemplate

1. 簡介

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

創(chuàng)新互聯(lián)公司專注于企業(yè)成都營銷網(wǎng)站建設(shè)、網(wǎng)站重做改版、臺(tái)江網(wǎng)站定制設(shè)計(jì)、自適應(yīng)品牌網(wǎng)站建設(shè)、HTML5建站、商城開發(fā)、集團(tuán)公司官網(wǎng)建設(shè)、外貿(mào)營銷網(wǎng)站建設(shè)、高端網(wǎng)站制作、響應(yīng)式網(wǎng)頁設(shè)計(jì)等建站業(yè)務(wù),價(jià)格優(yōu)惠性價(jià)比高,為臺(tái)江等各大城市提供網(wǎng)站開發(fā)制作服務(wù)。

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

Web 應(yīng)用中,對其他服務(wù)進(jìn)行 HTTP 調(diào)用是一個(gè)很常見的需求。因此,我們需要一個(gè) Web 客戶端工具。

2.1. RestTemplate 阻塞式客戶端

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

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

讓我們考慮下有很多傳入請求,它們正在等待產(chǎn)生結(jié)果所需的一些慢服務(wù)。

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

2.2. WebClient 非阻塞式客戶端

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

當(dāng) RestTemplate 為每個(gè)事件(HTTP 請求)創(chuàng)建一個(gè)新的 線程 時(shí),WebClient 將為每個(gè)事件創(chuàng)建類似于“任務(wù)”的東東。幕后,Reactive 框架將對這些 “任務(wù)” 進(jìn)行排隊(duì),并僅在適當(dāng)?shù)捻憫?yīng)可用時(shí)執(zhí)行它們。

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

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

3. 案例對比

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

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

就本文而言,讓我們實(shí)現(xiàn)兩個(gè) REST 端點(diǎn),一個(gè)使用 RestTemplate,另一個(gè)使用 WebClient。他們的任務(wù)是調(diào)用另一個(gè)響應(yīng)慢的 REST Web 服務(wù),該服務(wù)返回一個(gè) Tweet List。

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


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

接下來,這是我們的慢服務(wù) REST 端點(diǎn):

@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. 使用 RestTemplate 調(diào)用慢服務(wù)

現(xiàn)在,讓我們來實(shí)現(xiàn)另一個(gè) REST 端點(diǎn),它將通過 Web 客戶端調(diào)用我們的慢服務(wù)。

首先,我們來使用 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;
}

當(dāng)我們調(diào)用這個(gè)端點(diǎn)時(shí),由于 RestTemplate 的同步特性,代碼將會(huì)阻塞以等待來自慢服務(wù)的響應(yīng)。只有當(dāng)收到響應(yīng)后,才會(huì)執(zhí)行此方法中的其余代碼。通過日志,我們可以看到:

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 調(diào)用慢服務(wù)

其次,讓我們使用 WebClient 來調(diào)用慢服務(wù):

@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;
}

本例中,WebClient 返回一個(gè) Flux 生產(chǎn)者后完成方法的執(zhí)行。一旦結(jié)果可用,發(fā)布者將開始向其訂閱者發(fā)送 tweets。注意,調(diào)用 /tweets-non-blocking 這個(gè)端點(diǎn)的客戶端(本例中的 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)

注意,此端點(diǎn)的方法在收到響應(yīng)之前就已完成。

4. 結(jié)論

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

RestTemplate 使用 Java Servlet API,因此是同步和阻塞的。相反,WebClient 是異步的,在等待響應(yīng)返回時(shí)不會(huì)阻塞正在執(zhí)行的線程。只有當(dāng)程序就緒時(shí),才會(huì)產(chǎn)生通知。

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

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

原文:

作者:Drazen Nikolic

譯者:萬想


當(dāng)前題目:SpringWebClientvs.RestTemplate
網(wǎng)頁網(wǎng)址:http://weahome.cn/article/pcpepd.html

其他資訊

在線咨詢

微信咨詢

電話咨詢

028-86922220(工作日)

18980820575(7×24)

提交需求

返回頂部