Spring 5.0 M1 的响应式编程

工程 | Rossen Stoyanchev | 2016年7月28日 | ...

正如 Juergen 在他的 Spring Framework 5 M1 发布公告中提到的,我们的 Spring Reactive 倡议已合并到 Spring Framework 主体中,保留了所有贡献及其一年多的完整历史记录。

它是什么?

简而言之,响应式编程是指非阻塞、事件驱动的应用程序,这些应用程序通过少量线程进行扩展,并将背压(backpressure)作为关键组成部分,以确保生产者不会压垮消费者。Reactive Streams 规范(Java 9 也已采用)使得在不同提供商的层和库之间进行需求通信成为可能。例如,一个向客户端写入数据的 HTTP 连接可以将它的写入可用性一路向上游传递给从数据库获取数据的数据存储库,这样如果 HTTP 客户端很慢,存储库也可以放慢速度甚至暂停。有关响应式编程的更广泛介绍,请参阅 Dave Syer 的系列文章“响应式编程笔记”

从命令式逻辑切换到非阻塞方式时,一个实际挑战是如何组合异步逻辑而不会陷入“回调地狱”。我们需要的那种 API 的一个好例子是 Java 8 中的 CompletionStageStream API。然而,Stream 实际上是为集合构建的,不太适合我们非阻塞 I/O 和事件驱动应用程序中经常遇到的无限或延迟敏感序列。Reactor 及其即将发布的 3.0 GA 版本是 Reactive Streams 的一个实现,它通过 FluxMono API 类型扩展了 Reactive Streams Publisher,提供了类似于 Java 8 Stream 的声明式组合 API,但功能更广泛,与 ReactiveX 模式更具可比性。有关此内容的更多信息,请参阅 Sebastien Deleuze 的“理解响应式类型”

内容包括什么?

Spring Framework 5 采用了 Reactive Streams 和 Reactor,用于自身的响应式用途以及许多核心 API。M1 版本提供了 JSON (Jackson) 和 XML (JAXB) 的响应式序列化和反序列化、支持 @Controller 编程模型的响应式 Web 框架以及响应式 WebClient。这使得支持微服务、分散/收集、数据摄取等场景的输入和输出流变得容易。

下面是一个控制器,它以完全非阻塞和响应式的方式从远程服务器获取和流式传输数据

@GetMapping("/accounts/{id}/alerts")
public Flux<Alert> getAccountAlerts(@PathVariable Long id) {

  return this.repository.getAccount(id)
      .flatMap(account ->
          this.webClient
              .perform(get("/alerts/{key}", account.getKey()))
              .extract(bodyStream(Alert.class)));
}

支持它的响应式栈是什么?Spring Web Reactive 位于新的 spring-web-reactive 模块中,与现有的(并且很受欢迎!)位于 spring-webmvc 模块中的 Spring Web MVC 相邻。这两个模块共享许多算法和机制,但实际上不能共享任何代码。这是因为 Spring Web Reactive 运行在 Reactive Streams HTTP 适配器层上,该层从头到尾都是完全非阻塞和响应式的,一直到 HTTP 运行时。因此,虽然 Spring MVC 是为 Servlet 容器构建并运行在其上,但 Spring Web Reactive 也可以在非 Servlet 运行时(例如 Netty 和 Undertow)上运行。

Spring Web Reactive 与 Spring Web MVC 对比

您可能会想,Spring Framework 团队如何看待这两个框架,我们推荐您使用哪个?首先,我们力求在合理范围内实现最大程度的一致性。@Controller 编程模型与响应式方式之间没有根本性的不兼容之处。这一切都取决于底层如何支持该模型,因此表面上没有任何区别,除了完全支持来自 RxJava 的 FluxMono 以及 ObservableSingle 等响应式类型,用于输入和输出。

Spring Web Reactive 比 Spring MVC 更好吗?Spring Framework 响应式支持的最大价值主张和我们的独特之处在于,我们不会抛弃现有应用程序。在 Spring 5 中,传统的 Spring MVC 继续在任何 Servlet 3.1 栈上运行,包括 Java EE 7 服务器。对于 Spring Web Reactive,我们支持 Tomcat、Jetty、Undertow 和 Netty,并且可以适应任何 Servlet 3.1 容器,而不会妥协。我们计划在共享算法和机制方面继续保持 Spring MVC 和 Spring Web Reactive 之间的协同作用,以便在上层支持相同的编程模型。Spring MVC 方面的改进请求或错误报告将使 Spring Web Reactive 受益,反之亦然。

这意味着您作为开发人员可以选择最适合您目的的方式。如果有人告诉您同步或阻塞是邪恶的,请不要理会。它们并非如此,实际上这是一个权衡。命令式逻辑易于编写和调试。当然,它的伸缩性或效率不如响应式,但这正是权衡所在。总有许多情况下,命令式对于手头的任务来说完全没问题,而在另一些情况下,响应式和非阻塞是必需的。在微服务场景中,您甚至可以为每个独立服务选择实现风格,所有这些都在同一个一致的编程模型下进行。

试一试

更多详细信息和入门指南,请参阅 Spring Boot 响应式 Web 启动器和参考文档中的新章节

最后但同样重要的是,我希望您能参加我们的 SpringOne Platform 2016 大会,届时我们将有关于此主题的主题演讲和众多分会。拉斯维加斯见!

获取 Spring 时事通讯

通过 Spring 时事通讯保持联系

订阅

领先一步

VMware 提供培训和认证,助您快速提升。

了解更多

获取支持

Tanzu Spring 通过一个简单的订阅提供 OpenJDK™、Spring 和 Apache Tomcat® 的支持和二进制文件。

了解更多

即将举行的活动

查看 Spring 社区所有即将举行的活动。

查看全部