Reactor Bismuth 发布火车第一个里程碑可用

发布 | Simon Baslé | 2017 年 5 月 16 日 | ...

我谨代表 Reactor 团队,很高兴地宣布 Reactor 上周**达到了一个重要的里程碑**,发布了 Bismuth-M1 发布火车。

这个第一个里程碑支持新发布的 Spring Framework 5 RC1。它特别包含了 reactor-corereactor-testreactor-extra3.1.0.M1 版本。

由于 3.1.x 版本系列是长期支持分支(正如支持 Spring framework 的版本一样),因此重点放在稳定和打磨 API 上。因此,预计与 3.0.x 版本相比会有一些重大更改 [1]。

从 3.0.x 迁移

如果您在 3.0.x 版本阶段一直保持 Reactor 依赖项的更新(这意味着您使用的是 reactor-core 3.0.7),那么您会注意到最近几个版本中出现了一些被弃用的方法。

我们已尽力为 3.1.0 版本做好准备,提前提供新 API,并在方法重命名的情况下,在新方法引入时弃用旧方法。

在 3.0.x 版本中被弃用的方法,在 3.1.0.M1 版本中大多已被移除,因此在更新您的依赖项之前,请务必遵循本快速迁移指南!

在极少数情况下,此策略无法应用,我们将在下面详细介绍这些迁移模式。

查找被弃用的方法

大部分 API 更改在 3.0.7 中都有弃用说明,因此开始迁移的最简单方法是查找代码中被弃用的 API 用法,并根据 javadoc 中的建议进行修复。

大多数 API 更改属于以下 2 类:

  1. 重命名方法以更好地对齐 FluxMono 之间的 API消除 lambda 使用中的歧义:新别名将在 3.0.7 中引入,旧方法将被弃用并附带使用新别名的提示。

  2. 移除操作符的冗余变体,例如所有 xxxMillis 变体(这些变体已被移除,以支持仅使用基于 Duration 的替代方法):方法将被弃用,并附带使用保留的变体的提示。

但也存在一个更棘手的情况

迁移 Mono.then(Function)Mono.flatMap

与其他 then 变体不同,它们的效果是忽略 Mono 的数据,然后在完成时用另一个 Publisher 继续执行,Mono.then(Function) 会在 onNext 事件上做出反应。

这违反了最小惊喜原则,并且在链式调用多个 then 时可能导致意外行为。请看这个例子:

Mono.just(someObject)
 	 .thenEmpty(Mono.fromRunnable(AsyncUtils::runDiagnostics))
 	 .then(v -> AsyncUtils.toJson(v));

这段代码永远不会调用 runCleanupFor,因为前面的 thenEmpty 返回一个 Mono<Void>。但是,如果 Function 中使用的代码能够使用 Void 泛型类型进行编译,那么您将不会收到任何警告。

进一步查看签名以及该操作符不像其其他变体那样完全忽略 onNext 信号的事实,我们注意到这实际上更接近经典的 flatMap

Mono<V> then(Function<T, Mono<V>> thenFunction);

但是 flatMap 已经在 Mono 中存在,签名如下:

Flux<V> flatMap(Function<T, Flux<V>> mapFunction)

由于 flatMap 通常返回与封闭类型相同的类型,因此then(Function) 重命名为 flatMap,并将旧的 flatMap 改为 flatMapMany(遵循已建立的后缀约定,该约定指示 Mono 被此类操作符转换为 Flux)似乎更正确。

由于不能在 3.0.x 中引入仅通过返回类型不同的新 flatMap 签名(当时我们只想弃用旧的 flatMap),因此此迁移更难预料。

因此,最佳迁移“秘诀”是:

  1. 首先将所有 Mono.flatMap 的用法替换为 flatMapMany

  2. 完成其他重构和迁移。

  3. 切换到 3.1.0.M1

  4. 然后将所有 Mono.then(Function) 的用法(现在无法编译)替换为 flatMap

注意

请注意,如果您不执行步骤 1,可能会遇到误导性的编译错误:包含 flatMap 的序列以前会继续作为 Flux,而现在会继续作为 Mono
如果在操作符链的下游,您依赖于处于 Flux 状态(例如,使用仅在此类型上可用的操作符,如 reduce()),编译错误将在稍后出现。
与其从表面上修复编译错误,您需要注意到代码期望的是 Flux,而这是由于上游没有使用 flatMapMany……

调度器、时间与虚拟时间测试

Schedulers.timer() 调度器已被移除,所有默认调度器现在都能提交带有延迟/周期性的任务。因此,对于 delay() 等操作符,默认的 Scheduler 现在是 Schedulers.parallel()。请注意,线程名称现在将遵循 "parallel-`x`" 模式,其中 x 在工作线程数之间变化,而不是单个 "timed-`n`"

另一个变化是 reactor-test 中的 VirtualTimeScheduler 现在可以替换任何调度器。最值得注意的是,当通过 StepVerifier#withVirtualTime 使用时,VTS 将替换所有默认调度器

这意味着,如果您正在测试之前隔离在例如 Schedulers.elastic() 中的阻塞代码,现在您需要在 StepVerifier之前创建的专用 Scheduler 中执行此操作(例如 Schedulers.newSingle())。

处理器更改

处理器已重构。特别是,您不再需要显式连接到某些处理器,而是应始终使用新的 sink() 方法。这统一了所有处理器的 API,并序列化了那些尚未固有序列化的调用。整个 Processor 系列的使用现在更接近 Flux.create

新功能

Scannable

Scannable 接口取代了主要是内部使用的省去内省接口,这些接口已被移除(LoopbackMultiProducerMultiReceiverProducerReceiverTrackable)。

目标是使用单个接口支持序列的内省,包括通过遍历操作符。从现在到 GA 发布,将增加对此机制的支持。

Mono.delayUntil

delayUntildelayUntilOther 操作符已添加到 Mono 中,以延迟 Mono 的发射,直到一个伴随的 Publisher 完成。对于 delayUntil,该伴随由源 Mono 发射的值生成。但是,延迟 Publisher 的触发是在源完成时进行的。这非常接近最近添加的 untilOther,除了后者在 onNext 时触发其伴随,而不是在 onComplete 时触发。

关于 untilOther 是否应该被弃用,目前仍在等待决定,因为我们认为其名称和依赖于 onNext 的行为都不够清晰和有用。

结论

最后,我要特别感谢参与最新的 3.0.x 版本和 M1 版本社区贡献者(GitHub 用户名按字母顺序排列):@bdavisx @Dmitriusan @garyrussell @lebannen @lhotari @madhead @nebhale @rajinisivaram @RunninglVlan @sdeleuze @schauder

再次感谢大家!

要获取此版本,请使用 BOM 和 Spring Milestone 存储库(请参阅 此处的参考指南)。

最后,一个行动呼吁:

如果您对这个里程碑有任何疑问,或者更重要的是任何意见或建议,请随时在 Gitter 上加入实时讨论 Gitter打开一个 issue

祝您编程愉快!


1. 提醒一下,Reactor 3 并非完全符合语义化版本控制的 MAJOR.MINOR.PATCH 方案,而是遵循 X.MAJOR.MINOR 版本方案X 的递增意味着重大的架构和 API 重做,MAJOR 可以包含重要的功能和破坏性更改,而 MINOR 在同一个 MAJOR 内是二进制和 API 兼容的(尽管它们可以包含内部更改和新功能以及错误修复)。

获取 Spring 新闻通讯

通过 Spring 新闻通讯保持联系

订阅

领先一步

VMware 提供培训和认证,助您加速进步。

了解更多

获得支持

Tanzu Spring 提供 OpenJDK™、Spring 和 Apache Tomcat® 的支持和二进制文件,只需一份简单的订阅。

了解更多

即将举行的活动

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

查看所有