`kotlinx.coroutines.withContext` 与 Spring WebFlux 一起使用是不是安全?
Posted
技术标签:
【中文标题】`kotlinx.coroutines.withContext` 与 Spring WebFlux 一起使用是不是安全?【英文标题】: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 仍然可能发生在这个线程中:这种模式可以安全使用吗?如果没有,我还应该怎么做?
【问题讨论】:
【参考方案1】:是的,它是安全的,你正确理解了withContext
。
您在此处提到的那篇文档仅讨论了在IO
和Default
调度程序之间切换时对Dispatchers.IO
的优化(避免上下文切换)。
使用withContext(Dispatchers.IO)
来自除Default
/IO
线程池之外的其他线程将正确(并且始终)将上下文切换到该 IO 线程池,根据需要启动新线程来处理阻塞 IO,所以这应该是在你的情况下要走的路。
【讨论】:
这让我放心了,谢谢!所以基本上这里的问题只是文档的措辞有点模棱两可。 我想主要的陈述很清楚,但是“所以使用 withContext(Dispatchers.IO) 不会导致......”这部分看起来确实太笼统了。它应该是“所以使用 withContext(Dispatchers.IO)当已经在 DIsptachers.Default 上运行时不会导致......”。 仅供参考,Kotlin 团队接受并合并 my PR 以澄清文档,所以这不再是问题了 :) 整洁!这就是承诺! :-)以上是关于`kotlinx.coroutines.withContext` 与 Spring WebFlux 一起使用是不是安全?的主要内容,如果未能解决你的问题,请参考以下文章