webClient和restTemplate对比

通过一个小案例 将webClientrestTemplate 做一个简单的比较。

详细的WebFlux/WebClient 和 Spring MVC/RestTemplate 性能对比请参考:https://github.com/bigbirditedu/webclient

引入SpringBoot依赖

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

单独起一个springboot工程,编写一个服务端http接口

/**
 * 服务提供方接口
 */
@RestController
public class ServerController {

    @GetMapping("products")
    public List<Product> getAllProducts(String type) throws InterruptedException {
        List<Product> products = new ArrayList<>();
        products.add(new Product(type + "A", "1", 52.67));
        products.add(new Product(type + "B", "2", 86.21));
        products.add(new Product(type + "C", "3", 27.94));
        Thread.sleep(5000);
        return products;
    }
}

再编写一个客户端来调用上述http接口,分别使用restTemplate和webclient,对比耗时。

@RestController
public class ProductController {

    @GetMapping("rest")
    public List<Product> getProductsRestTemplate() {
        RestTemplate restTemplate = new RestTemplate();
        long start = System.currentTimeMillis();
        ResponseEntity<Product[]> resEntity = restTemplate.getForEntity("http://127.0.0.1:8081/products?type=rest", Product[].class);
        long end = System.currentTimeMillis();
        System.out.println(Thread.currentThread().getName() + " restTemplate cost:" + (end - start));
        List<Product> products = Arrays.asList(resEntity.getBody());
        return products;
    }

    @GetMapping("webclient")
    public Flux<Product> getProductsWebclient() {
        long start = System.currentTimeMillis();
        Flux<Product> productFlux = WebClient.create("http://127.0.0.1:8081/products?type=webc").get().retrieve().bodyToFlux(Product.class);
        long end = System.currentTimeMillis();
        System.out.println(Thread.currentThread().getName() + " webclient cost:" + (end - start));
        return productFlux;
    }
}
public class Product {
    private String name;
    private String id;
    private double price;

    public Product() {

    }
    public Product(String name, String id, double price) {
        this.name = name;
        this.id = id;
        this.price = price;
    }
    //省略getter、setter方法
}

注意启动时换个端口application.properties:

server.port=8081

运行结果:

reactor-http-nio-6 webclient cost:0
reactor-http-nio-4 restTemplate cost:5004
reactor-http-nio-4 webclient cost:0
reactor-http-nio-3 restTemplate cost:5002

由此可见,使用webClient在等待响应的同时不会阻塞正在执行的线程 ;这种异步编程的方式避免了线程阻塞,线程处理完一个请求紧接着可以处理下一个,能够提高系统的吞吐量;而restTemplate 这种方式是阻塞的,会一直占用当前线程资源,直到http返回响应。如果等待的请求发生了堆积,应用程序将创建大量线程,直至耗尽线程池和所有可用内存。同时伴随着频繁的CPU上下文切换,可能导致性能下降。

但是作为上述两种方式的调用者(消费者)而言,其最终获得http响应结果的耗时并未减少。比如浏览器访问上述ProductController 的两个接口时,返回数据的耗时相同。最终获取(消费)数据的地方还会等待。

使用webclient替代restTemplate的好处是可以异步等待http响应,使得线程不需要阻塞;单位时间内有限资源下支持更高的并发量。

异步非阻塞的、响应式的HTTP客户端请认准webclient !

webclient 详细讲解》推荐 https://gitbook.cn/gitchat/activity/61ad7905aef4835642ab78f9
上文会详细讲解 webclient http 请求、与resttemplate对比等。
详细代码地址:https://github.com/bigbirditedu/webclient

webclient 官方教程:
https://www.baeldung.com/spring-5-webclient
https://projectreactor.io/docs/netty/snapshot/reference/index.html#_connection_pool_2
https://docs.spring.io/spring-framework/docs/current/reference/html/web-reactive.html#webflux-client-builder-reactor-resources

  • 2
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 3
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

程猿薇茑

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值