龙空技术网

Spring 框架里的 HTTP 调用,RestTemplate 还是 WebClient

阿呜的边城 115

前言:

现时看官们对“http 同步 异步”都比较关切,兄弟们都需要学习一些“http 同步 异步”的相关资讯。那么小编同时在网络上收集了一些对于“http 同步 异步””的相关内容,希望看官们能喜欢,小伙伴们一起来了解一下吧!

在 web 应用中,通过 HTTP 调用其他服务的 API 是很常见的操作,所以,我们的 web 应用中常常离不开网络客户端工具。

既然涉及到网络请求,就一定会有阻塞和非阻塞的选择问题。

RestTemplate

Spring 框架本身提供了 RestTemplate 作为 web 客户端抽象。在实现上,RestTemplate 使用了 Java Servlet API,该 AP I基于线程-请求模型。这意味着线程将阻塞,直到 web客户端收到响应为止。阻塞代码的问题是每个线程都会消耗了一定数量的内存和CPU周期。

如果有很多传入的请求,又有一些慢速服务,等待结果的请求迟早会堆积起来。因此,应用程序将创建许多线程,这将耗尽线程池或占用所有可用内存。由于频繁的CPU上下文切换,整个应用的性能就会下降。

WebClient

相对的,WebClient 使用 Spring Reactive 框架提供异步、无阻塞的解决方案。

RestTemplate 为每个 HTTP 调用使用线程,而 WebClient 则为每个事件创建类似于“任务”的东西。在实现中,Reactive 框架将对这些“任务”进行排队,并仅在有适当响应时执行它们。

Reactive 框架使用事件驱动的体系结构。它提供了通过响应流 API 组合异步逻辑的方法。因此,与同步阻塞的方法相比,响应式方法可以处理更多的逻辑,同时使用更少的线程和系统资源。

WebClien t是 Spring WebFlux 库的一部分。因此,我们还可以使用响应式 API 编写客户端代码,并使用响应式类型 Mono 和 Flux。

对比

我们使用代码对比一下二者的差异,先看下使用 RestTemplate:

@GetMapping("/blocking")public List<User> getUserBlocking() {    log.info("Starting BLOCKING Controller!");    final String uri = getSlowServiceUri();    RestTemplate restTemplate = new RestTemplate();    ResponseEntity<List<User>> response = restTemplate.exchange(      uri, HttpMethod.GET, null,      new ParameterizedTypeReference<List<User>>(){});    List<User> result = response.getBody();    result.forEach(user -> log.info(user.toString()));    log.info("Exiting BLOCKING Controller!");    return result;}

再看一下使用 Sping WebFlux 里的 WebClient:

@GetMapping(value = "/non-blocking",             produces = MediaType.TEXT_EVENT_STREAM_VALUE)public Flux<User> getUserNonBlocking() {    log.info("Starting NON-BLOCKING Controller!");    Flux<User> userFlux = WebClient.create()      .get()      .uri(getSlowServiceUri())      .retrieve()      .bodyToFlux(User.class);    userFlux.subscribe(user -> log.info(user.toString()));    log.info("Exiting NON-BLOCKING Controller!");    return tweetFlux;}

可以明显看到,RestTemplate 的使用中,代码是完全阻塞等待响应具体的 List<User>,而 WebClient 则是返回了 Flux<User>。Flux 在响应式框架中代表 1 到多个数据,所以它在异步响应成功后,实际也是获得 Iterable<User>。

小结

通过以上介绍,我们知道 RestTemplate 使用 Java Servlet API,因此是同步和阻塞的。

而 Spring WebFlux 里的 WebClient 是异步的,在等待响应返回时不会阻塞正在执行的线程。只有当响应准备就绪时,才会生成结果通知。

RestTemplate 是一个很常规的使用选择,但在某些情况下,与阻塞方法相比,非阻塞方法使用的系统资源要少得多,这个时候 WebClient 会是一个更好的选择。

标签: #http 同步 异步