【问题标题】:Blocking calls in Reactive Stream阻塞响应流中的调用
【发布时间】:2021-04-06 10:26:39
【问题描述】:

我想知道普通的 java API 调用(我的意思是没有 I/O 的方法)是否应该作为“迷你阻塞调用”线程化?像这样实现 Reactive Streams 是否可以接受(在返回 Publisher 之前调用方法):

  public Mono<String> doSomething(Object anyObject){
      validator.validate(anyObject); // it returns void so in this case it cannot be in filter
      return Mono.just(anyObject)
          .flatmap(service::process);
  }

而不是(在流中调用它)

  public Mono<String> doSomething(Object anyObject){
      return Mono.just(anyObject)
          .doOnNext(validator::validate)
          .flatmap(service::process);
  }

此验证器仅作为示例。这种方法是否有任何缺点,或者在返回语句之前的这些方法应该始终包含在流中?

【问题讨论】:

  • 如果将其置于反应器上下文之外,系统将无法利用根据需要切换线程的能力来优化线程使用。

标签: spring-webflux project-reactor reactive


【解决方案1】:

我想知道普通的 java API 调用(我的意思是没有 I/O 的方法)是否应该作为“迷你阻塞调用”线程化?

我不太清楚你在这里所说的小阻塞调用是什么意思 - 方法阻塞或不阻塞。如果它因为不需要而没有阻塞(该方法不涉及任何 IO 或其他阻塞操作),那么它只是一个标准的同步操作。

在这种情况下,我希望尽可能遵守两个相关原则:

  • 将所有内容都保留在响应式链中(这样可以使代码更清晰,并意味着下游工作的运算符具有适当的效果);
  • 避免在所有无关紧要的情况下使用Mono.just()(否则,您看起来像是在处理一个值的“承诺”,而不是一个立即可用的值。)

因此,我倾向于第二种方法,因为那里的所有内容都显然是反应链的一部分,这使得代码更易于阅读恕我直言 - 您不会在反应和非反应代码之间来回切换。

但是,请记住,您会将此方法用作更大的反应链的一部分(很可能通过 flatMap() 调用),如果可能的话,实际上我更喜欢另一种方法 - 即使用 @ 987654323@ 代替,这意味着您可以提供一个方法,该方法既接受 Mono 作为其参数,又返回一个:

public Mono<String> doSomething(Mono<String> mono){
  return mono
      .doOnNext(validator::validate)
      .flatmap(service::process);
}

这会将所有内容都保留为反应链的一部分,并具有避免使用 Mono.just() 的额外优势。

【讨论】:

  • 感谢您的回答。这个“迷你阻塞电话”的名字真的很糟糕——现在我明白了。我的意思是耗时的方法,例如假设前面提到的方法“验证”需要 5 秒来处理。当它不在任何 Publisher 中时,它不会提供并发问题吗?
  • @destro1 这 5 秒只是 CPU 时间吗?如果是这样,那么您可能希望将其放在 parallel() 调度程序或类似的调度程序上,以避免长时间占用事件循环 - 但如果您有很多非常密集的任务,您可能会很快耗尽 CPU 资源!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-06-21
  • 2013-11-16
  • 2019-03-28
  • 1970-01-01
相关资源
最近更新 更多