【发布时间】:2022-12-17 00:32:39
【问题描述】:
我有一个 Spring Boot 应用程序,在处理给定请求时,我需要并行调用上游服务并等待结果完成,然后再在我自己的响应中返回它们。
在现有的代码库中,我注意到为了这样做,模式是使用runBlocking(IO) { ... }
@Service
class MyUpstreamService {
fun getSomething() = 1
}
@RestController
class MyController(
val upstream: MyUpstreamService
) {
@GetMapping("/foo")
fun foo() =
runBlocking(Dispatchers.IO) {
val a = async { upstream.getSomething() }
val b = async { upstream.getSomething() }
a.await() + b.await()
}
}
这按预期工作。
现在由于某些原因,我需要将 MyUpstreamService 的范围设置为 @RequestScope,如果我这样做,一旦我从 runBlocking(IO) { ... } 块中访问 MyUpstreamService,就会出现以下异常:
Caused by: java.lang.IllegalStateException: No thread-bound request found: Are you referring to request attributes outside of an actual web request, or processing a request outside of the originally receiving thread? If you are actually operating within a web request and still receive this message, your code is probably running outside of DispatcherServlet: In this case, use RequestContextListener or RequestContextFilter to expose the current request.
at org.springframework.web.context.request.RequestContextHolder.currentRequestAttributes(RequestContextHolder.java:131) ~[spring-web-5.3.22.jar:5.3.22]
如果我不使用 Dispatchers.IO 上下文,那么一切正常。
所以问题是为什么在等待多个异步调用完成时会使用 runBlocking(Dispatchers.IO) { .. } 而不是仅使用 runBlocking { .. }?
为了完整起见,这里是演示问题的整个 sn-p。
-
GET /bar作品 -
GET /foo抛出异常
@RequestScope
@Service
class MyUpstreamService(
// val currentUser: CurrentUser
) {
fun getSomething() = 1
}
@RestController
class MyController(
val upstream: MyUpstreamService
) {
@GetMapping("/foo")
fun foo() =
runBlocking(Dispatchers.IO) {
val a = async { upstream.getSomething() }
val b = async { upstream.getSomething() }
a.await() + b.await()
}
@GetMapping("/bar")
fun bar() =
runBlocking {
val a = async { upstream.getSomething() }
val b = async { upstream.getSomething() }
a.await() + b.await()
}
}
【问题讨论】:
标签: spring kotlin kotlin-coroutines