反应堆加州锔-M1,今夏的里程碑版本发布列车

工程 | Simon Baslé | 2018年8月7日 | ...

我代表Reactor团队,很荣幸地宣布最新的Reactor里程碑版本Californium-M1??

团队一直在忙于开发Californium,这是Reactor 3的第三个主要版本。我们现在准备好听取您对一些特定问题的反馈,并且我们还有许多增强功能和错误修复等待您的体验。

Californium-M1 物料清单 (BOM)

对于它的第三个发布列车,我们继续沿用元素周期表上按字母顺序递增的元素名称的主题。锔是一种首先在加利福尼亚州合成的元素。

此里程碑版本的物料清单包含:

  • reactor-core 3.2.0.M3
  • reactor-extra 3.2.0.M1(有一些API对齐更改)
  • reactor-netty 0.8.0.M1

今年年初 (M1),有一个reactor-core 的早期预览版本,它只关注“错误模式继续”功能,并且核心在6月份还有一个脱离发布列车的里程碑版本 (M2)。这篇博客文章除了介绍全新的M3中的更改之外,还介绍了后者的更改。

Reactor Netty 0.8.0.M1

这里最重量级的部分是reactor-netty。期待一篇更完整的博客文章,详细介绍API更改和新功能背后的原因,其中包括:

API 重构

团队引入了一个大型的API重构,在构建客户端和服务器时提供更清晰的指导,避免了在0.7.x版本中容易出现的难以预测的配置错误。

新的API也更清晰地概述了生命周期。

HTTP2 支持

是的,**HTTP2支持** ?? 目前它主要是在透明地升级到HTTP2,但我们正在努力在不久的将来将HTTP2单个流作为一等公民添加。

Reactor Core 3.2.0

总的来说,与之前的Bismuth版本相比,M2和M3带来了超过70个更改。

reactor-core中的API更改比reactor-netty中的少,更新注意事项主要与里程碑版本本身之间的差异有关。有关更多详细信息,请参阅M2M3的“更新注意事项”部分。

我们最需要您对以下功能提供反馈:

指标

已添加Micrometer和.metrics()支持(#1183#1123)。只有当Micrometer在类路径上时,新的.metrics()操作符才会执行某些操作。

它记录关于onNext计时、订阅到完成计时、信号计数等的指标——所有这些都是从直接上游操作符产生的信号的角度来看的。

它在M2中引入,但在M3中得到了改进,以及一些标签名称的(破坏性)更改(#1245)。

请注意,一个重要的目标是避免在公共Reactor API中公开Micrometer的内容。我们不想强制依赖Micrometer,并且我们努力将其使用限制在只有在我们检测到它在类路径上时才会加载的内部类中。

**接下来:**在GA之前,还应该对Schedulers(或者更确切地说是支持一些SchedulersExecutorServices)提供基本的检测支持。我们还在研究一种方法来为Reactor全局选择一个特定的MeterRegistry,同样无需公开引用MeterRegistry接口的公共API。

高级重试

我们添加了一个预配置的retryWhen替代方案,该方案具有指数退避和抖动 (retryBackoff())。请参见 #1122

此重试版本反映了我们认为的行业最佳实践。它是过于简单的retry(n)、复杂的retryWhen(Function)reactor-addons中更可配置的RetryFunction之间的一个很好的折中方案。

基于资源的响应式闭包

为了帮助您构建响应式事务块,我们添加了usingWhen。与using一样,它包装一个资源,从中生成一个Flux,并确保在Flux终止时正确清理资源。

主要区别在于:

  • 资源通过Publisher异步提供。
  • 清理也是异步的 (Function<Resource, Publisher>),并且只延迟终端信号的传播,而不是onNext信号。
  • 该操作符可以对完成、错误和取消终止具有单独的异步“清理”。

这在M2中引入,但在M3中略有更改,以修复Context传播并支持取消Publisher<Resource>。通过在Resource发出之前取消此操作符返回的主Flux<T>,您的取消指令将传播到Publisher<Resource>

onDiscard钩子

这个全局钩子采用Consumer<Object>的形式,旨在作为处理需要特殊清理的堆外对象的进阶用户的最后一个缺失部分。

通常,Netty的ByteBuf或Spring 5的DataBuffer属于此类别:它们是池化的、堆外的,并且需要一个release()调用,除非它们不再使用,否则可能会发生内存泄漏。

此类元素可能在响应式序列之间出现裂缝,并且在三种主要情况下永远不会到达用户代码:

  1. 操作符的源代码格式错误,并且不遵守RS规范(例如,它在发出onComplete之后发出ByteBuf)。
  2. 操作符将其作为语义的一部分过滤一些元素(例如filter)。
  3. 操作符为了反压优化目的而预取,并被取消,丢弃其预取队列。

情况(1)已由onNextDropped钩子涵盖,但情况(3)肯定没有。情况(2)(过滤语义)有点介于两者之间,例如,可以在过滤Predicate内部进行清理。但这很麻烦,而且很容易被遗忘。

因此,我们向我们的 `Hooks` 库中添加了 `onDiscard` 来处理 (2) 和 (3)。需要注意的是,与“错误继续”功能不同,目前尚无公共 API 可用于在特定的 `Flux` 实例上设置此 hook。可以使用 `Context` 实现一个不受支持的变通方案,官方 API 可能会在 GA 版本或后续的维护版本中出现。

`onDiscard` hook 具有以下**特性和要求**

  • 它是累加的,这意味着两次调用 `Hooks.onDiscard(Consumer)` 将使用 `Consumer#andThen` 组合这两个消费者。
  • 它是非键控的,这意味着虽然多次调用是累加的,但只能完全重置(不能按每个 `Consumer` 为单位重置)。
  • `Consumer` **必须**在进行类型转换之前执行 `instanceof` 检查,因为它**将**用于不同类型的对象。
  • `Consumer` **禁止**抛出异常,并应根据需要包含 `try catch` 块。
  • `Consumer` **必须**是幂等的,因为它可能在同一实例上被多次调用(例如,在缓冲区重叠的情况下)。

顺便一提,`errorStrategyContinue()` **在 M3 版本中已重命名为 `onErrorContinue()`**。

Reactor Extra 3.2.0.M1

最后,`reactor-extra` 在重试/重复实用程序方面进行了一些较小的 API 更改。它与 `core` 运算符保持一致,使用相同的默认值和 `Long` 而不是 `Integer` 索引。

后续步骤

`reactor-core` 的下一步是重新设计 `Processor` 对象的公开方式。当前的 `FluxProcessor` 有点臃肿,因为它扩展并公开了整个 `Flux` API。

此外,`FluxProcessor#sink()` 和相关的 `FluxSink` 非常容易被误用,尤其是在想要将 `Processor` 订阅到 `Publisher` 源并通过 `sink()` 手动向其推送数据时,目前并不真正支持这种方式。`sink()` 应该只调用一次,并且返回的 `FluxSink` 实例应该重复使用,这一点也不清晰。

因此,我们正在考虑创建一个 `Processor` 的外观,它直接实现 `FluxSink`(而不是 `Flux`),在同时用作订阅者和接收器时都能正常工作,并且具有 `asFlux()` 视图方法,可以可选地在其之上构建 `Flux` 运算符链。

`MonoProcessor` 可能也会遵循这些步骤,成为一个(更简单的)接口,具体的实现将重命名为 `MonoNextProcessor`。我们还在考虑提供一个独立的 `MonoSink` 实现,用户可以直接操作它,而无需使用 `Mono.create()`。

结论

酷的人不会等待 GA 版本发布!快去试用这个闪亮的里程碑版本吧,并且一如既往地欢迎反馈!:)

祝您反应式编程愉快!

获取 Spring 新闻通讯

通过 Spring 新闻通讯保持联系

订阅

领先一步

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

了解更多

获得支持

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

了解更多

即将举行的活动

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

查看全部