Spring WebFlux控制器默认用Dispatchers.Unconfined而非Default的原因咨询
问题:Spring WebFlux中挂起函数为何使用Dispatchers.Unconfined而非默认的Dispatchers.Default?
我在Spring WebFlux应用中编写了如下简单控制器:
@GetMapping("/ping") suspend fun ping(): ResponseEntity<Map<String, Boolean>> { println(coroutineContext) waitforIO() return ResponseEntity(mapOf("success" to true), HttpStatus.OK) } suspend fun waitforIO() { println(coroutineContext) delay(1000) }
运行后输出如下:
[Context1{micrometer.observation={name=http.server.requests(null), error=null, context=name='http.server.requests', contextualName='null', error='null', lowCardinalityKeyValues=[exception='none', method='GET', outcome='SUCCESS', status='200', uri='UNKNOWN'], highCardinalityKeyValues=[http.url='/ping'], map=[class io.micrometer.core.instrument.LongTaskTimer$Sample='SampleImpl{duration(seconds)=0.066692583, duration(nanos)=6.6692583E7, startTimeNanos=475384383429625}', class io.micrometer.core.instrument.Timer$Sample='io.micrometer.core.instrument.Timer$Sample@4b6502a5'], parentObservation=null}}, MonoCoroutine{Active}@33bfeb7d, Dispatchers.Unconfined] [Context1{micrometer.observation={name=http.server.requests(null), error=null, context=name='http.server.requests', contextualName='null', error='null', lowCardinalityKeyValues=[exception='none', method='GET', outcome='SUCCESS', status='200', uri='UNKNOWN'], highCardinalityKeyValues=[http.url='/ping'], map=[class io.micrometer.core.instrument.LongTaskTimer$Sample='SampleImpl{duration(seconds)=0.068251166, duration(nanos)=6.8251166E7, startTimeNanos=475384383429625}', class io.micrometer.core.instrument.Timer$Sample='io.micrometer.core.instrument.Timer$Sample@4b6502a5'], parentObservation=null}}, MonoCoroutine{Active}@33bfeb7d, Dispatchers.Unconfined]
按我理解,默认应该使用Dispatchers.Default,烦请解释为何实际使用的是Dispatchers.Unconfined。我的环境配置如下:
OpenJDK Runtime Environment JBR-17.0.7+7-985.2-nomod (build 17.0.7+7-b985.2) kotlin("jvm") version "1.8.22" kotlin("plugin.spring") version "1.8.22" id("org.springframework.boot") version "3.1.5" id("io.spring.dependency-management") version "1.1.3" springCloudVersion="2022.0.4"
所有依赖由spring-cloud-dependencies - 2022.0.4管理。
原因解释
Spring WebFlux的协程调度策略:Spring WebFlux在处理带
suspend修饰的控制器方法时,默认会用Dispatchers.Unconfined启动协程。这是因为WebFlux基于Reactor异步模型,Unconfined允许协程先在触发请求的Reactor线程上同步执行,直到遇到第一个挂起点(比如示例中的delay(1000)),之后才会切换到对应线程池继续执行,避免了不必要的线程切换开销。Dispatchers.Default的定位:
Dispatchers.Default是为CPU密集型任务设计的线程池,而WebFlux核心是处理异步IO场景,Unconfined的调度方式更贴合WebFlux的非阻塞线程模型,能在同步执行阶段复用当前请求线程,提升效率。手动指定调度器的方式:如果需要强制使用
Dispatchers.Default或Dispatchers.IO,可以通过withContext切换上下文:
@GetMapping("/ping") suspend fun ping(): ResponseEntity<Map<String, Boolean>> { return withContext(Dispatchers.Default) { println(coroutineContext) waitforIO() ResponseEntity(mapOf("success" to true), HttpStatus.OK) } }
内容的提问来源于stack exchange,提问作者Mohamed Anees A
相关产品推荐
相关产品推荐

