Spring 5.0 M1 中的响应式编程

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

正如 Juergen 在他的 Spring Framework 5 M1 发布公告中提到的,我们的 Spring 响应式计划已合并到 Spring Framework 正式版中,保留了所有贡献及其一年多的完整历史记录。

它是什么?

简而言之,响应式编程是关于非阻塞、事件驱动的应用程序,这些应用程序可以通过少量线程进行扩展,并将背压作为关键要素,旨在确保生产者不会压垮消费者。 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 Web MVC(位于 spring-webmvc 模块中)并排。这两个模块共享许多算法和机制,但实际上无法共享任何代码。这是因为 Spring Web Reactive 运行在一个 Reactive Streams HTTP 适配器层上,该层是完全非阻塞的,并且一直到 HTTP 运行时都是响应式的。因此,虽然 Spring MVC 是为 Servlet 容器构建并在其上运行的,但 Spring Web Reactive 也可在非 Servlet 运行时上运行,例如 Netty 和 Undertow。

Spring Web Reactive 与 Spring Web MVC

您可能会想知道 Spring 框架团队如何看待这两个框架,以及我们建议您使用哪个框架?首先,我们的目标是在合理的范围内实现最大的可能一致性。@Controller 编程模型和响应式方式之间没有任何根本上的不兼容性。这一切都取决于支持该模型的底层机制,因此在表面上没有区别,除了完全支持响应式类型(如 FluxMono 以及 RxJava 的 ObservableSingle)作为输入和输出。

Spring Web Reactive 是否优于 Spring MVC?Spring 框架响应式支持的最大价值主张和我们独特的定位在于,我们不会抛弃现有的应用程序。在 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 社区中所有即将举行的活动。

查看全部