【问题标题】:Is `kotlinx.coroutines.withContext` safe to use with Spring WebFlux?`kotlinx.coroutines.withContext` 与 Spring WebFlux 一起使用是否安全?
【发布时间】:2021-09-05 05:16:46
【问题描述】:

想象一下,我有一个用 Kotlin 实现的 Spring WebFlux 控制器,看起来像这样:

@RestController
@RequestMapping("/api/foo")
class MyController {
  @GetMapping
  suspend fun getFoo(): FooResource {
    return withContext(Dispatchers.IO) {
      // fetch some resource with some expensive blocking IO call
    }
  }
}

我理解 WebFlux 的并发模型的方式,只有一个线程可以处理请求,所以如果我由于某种原因无法避免阻塞 IO 调用,我需要以某种方式将其卸载到另一个线程。 kotlinx.coroutines.withContext 助手应该就是这样做的,IO 调度程序是专门为这种用例设计的。`我在几篇博客文章中看到了这种模式,所以这似乎是常识。

但是,[Dispatchers.IO 上的文档说:

此调度程序与默认调度程序共享线程,因此使用 withContext(Dispatchers.IO) { ... } 不会导致实际切换到另一个线程 - 通常在同一线程中继续执行。由于线程共享,在通过 IO 调度程序进行操作期间可以创建(但不使用)超过 64 个(默认并行度)线程。

所以这让我想知道:如果 WebFlux 只使用一个“主线程”来处理请求,并且即使我使用 withContext(Dispatchers.IO),阻塞 IO 仍然可能发生在这个线程中:这种模式可以安全使用吗?如果没有,我还应该怎么做?

【问题讨论】:

    标签: java spring-boot kotlin spring-webflux kotlin-coroutines


    【解决方案1】:

    是的,它是安全的,你正确理解了withContext

    您在此处提到的那篇文档仅讨论了在IODefault 调度程序之间切换时对Dispatchers.IO 的优化(避免上下文切换)。

    使用withContext(Dispatchers.IO) 来自除Default/IO 线程池之外的其他线程将正确(并且始终)将上下文切换到该 IO 线程池,根据需要启动新线程来处理阻塞 IO,所以这应该是在你的情况下要走的路。

    【讨论】:

    • 这让我放心了,谢谢!所以基本上这里的问题只是文档的措辞有点模棱两可。
    • 我想主要的陈述很清楚,但是“所以使用 withContext(Dispatchers.IO) 不会导致......”这部分看起来确实太笼统了。它应该是“所以使用 withContext(Dispatchers.IO)当已经在 DIsptachers.Default 上运行时不会导致......”。
    • 仅供参考,Kotlin 团队接受并合并 my PR 以澄清文档,所以这不再是问题了 :)
    • 整洁!这就是承诺! :-)
    猜你喜欢
    • 2020-04-10
    • 1970-01-01
    • 2012-07-26
    • 2021-01-15
    • 1970-01-01
    • 1970-01-01
    • 2012-05-18
    • 1970-01-01
    • 2017-11-07
    相关资源
    最近更新 更多