zoukankan      html  css  js  c++  java
  • WebClient 非阻塞客户端 RestTemplate 阻塞式客户端

    收到多个客户端请求后,阻塞方法的性能显著下降。

    而 Reactive 非阻塞方法的表现应该与请求数量无关,性能稳定

    添加 Spring Boot WebFlux Starter 依赖

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

    耗时比较

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

    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 是同步调用,调用 Endpoint 时代码将进入阻塞等待被调用的耗时服务响应。只有在收到响应后,才会执行方法中的后续代码,日志如下:

    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!

    接下来 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 publisher 后就执行完成了。结果就绪时,publisher 会向订阅者发送推文列表。注意:客户端(这里指 Web 浏览器)调用/tweets-non-blocking Endpoint 也可以订阅 Flux 对象。 这个 Endpoint 方法在收到响应前就已执行完成。

    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) 

     总结:

    这篇文章讨论了 Spring 中使用 Web Client 的两种不同方式。

    RestTemplate 采用 Java Servlet API,因而是阻塞式同步调用。相反,WebClient 是异步的,等待响应的同时不会阻塞正在执行的线程。只有在响应结果准备就绪时,才会发起通知。

    RestTemplate 仍然有用武之地。非阻塞模式在某些场景下比阻塞方法占用系统资源要少得多,这时 WebClient 是一种更好的选择

  • 相关阅读:
    SmartSql = Dapper + MyBatis + Cache(Memory | Redis) + ZooKeeper + R/W Splitting + ......
    SmartSql For Asp.Net Core 最佳实践
    如何通过本地化事件正确实现微服务内部强一致性,事件总线跨微服务间最终一致性
    Netty入门搭建
    IO同步阻塞与同步非阻塞
    NIO的缓冲区、通道、选择器关系理解
    SpringBoot整合ActiveMQ
    ActiveMQ的介绍及使用
    nginx入门(一)
    垃圾回收器及tomcat调优
  • 原文地址:https://www.cnblogs.com/otways/p/11411652.html
Copyright © 2011-2022 走看看