Multithreading 请求-响应内并发的协同路由
假设我正在运行一个简单的web服务器,它分配100个线程来处理传入的请求。当一个请求到来时,一个线程被分配并被阻塞,直到一个响应可用为止。一旦有响应可用,响应就被发送出去,线程再次空闲 要处理一个请求,我需要进行2次数据库调用,并基本上总结结果:Multithreading 请求-响应内并发的协同路由,multithreading,web-services,kotlin,kotlin-coroutines,Multithreading,Web Services,Kotlin,Kotlin Coroutines,假设我正在运行一个简单的web服务器,它分配100个线程来处理传入的请求。当一个请求到来时,一个线程被分配并被阻塞,直到一个响应可用为止。一旦有响应可用,响应就被发送出去,线程再次空闲 要处理一个请求,我需要进行2次数据库调用,并基本上总结结果: 挂起getUserData(用户名:字符串):字符串={ val firstName=async{database1.findUser(username)}//一个挂起的函数 val lastName=async{database2.findUser
挂起getUserData(用户名:字符串):字符串={
val firstName=async{database1.findUser(username)}//一个挂起的函数
val lastName=async{database2.findUser(username)}//一个挂起的函数
返回firstName.await()+lastName.await();
}
假设我有一个main方法调用上述方法来服务请求:
趣味主站(用户名){
运行阻塞{
返回用户数据(用户名)
}
}
我的理解是getUserData中的异步代码将在
这表明:
- 除了处理请求的100个线程之外,我还有一个(较小的)线程池,由~4-8个线程组成,用于处理数据库调用
- 假设我有4个CPU,并且假设每个db调用需要约750ms:如果我开始每秒接收50个请求,处理co例程的4个线程将被4个请求阻塞,剩下的44个线程将挂起,等待响应
注意:我不是在寻找不同的服务器/框架。相反,考虑到我已经拥有的,我很好奇是否可以利用协同路由来提高并发性。如果没有,我可以按顺序运行查询。你说的
db.findUser
是一个挂起的函数,这意味着它不会阻止调用线程<代码>默认调度程序中的4个线程是否管理事件循环--是<代码>一次执行所有50个请求--是假设db.findUser返回未来或某个东西
——您说它是一个可挂起的函数,所以它不会返回未来,而是返回实际结果。我的理解是getUserData中的异步代码将在默认调度程序上运行
——您不能单独调用异步
,您需要一个CoroutineScope
来调用它,它将确定调度器。如果使用像GlobalScope
这样的空范围,则默认值为default
dispatcher。但是实际上,您应该将getUserData
的主体包含在coroutineScope{…}
块中,否则在两个块中的一个失败的情况下,代码将泄漏coroutines。@MarkoTopolnik不是由调用它的runBlocking
处理的。如果第一个async{…}
失败,那么它将抛出firstName.await()
,第二个基本上继续运行。runBlocking不会得到错误并终止第二个错误吗?它转义方法,但不转义调用(runBlocking
)范围。是的,但这意味着它不包含在函数中,您必须使用外部runBlocking
来修复它。内部coroutineScope
是正确的习惯用法和最佳实践。可以从runBlocking
调用该函数,也可以不调用该函数。另外,如果没有coroutineScope
代码甚至都不会编译,就没有coroutineScope
可以调用async
。您说过db.findUser
是一个挂起的函数,这意味着它不会阻止调用线程<代码>默认调度程序中的4个线程是否管理事件循环--是<代码>一次执行所有50个请求--是假设db.findUser返回未来或某个东西
——您说它是一个可挂起的函数,所以它不会返回未来,而是返回实际结果。我的理解是getUserData中的异步代码将在默认调度程序上运行
——您不能单独调用异步
,您需要一个CoroutineScope
来调用它,它将确定调度器。如果使用像GlobalScope
这样的空范围,则默认值为default
dispatcher。但是实际上,您应该将getUserData
的主体包含在coroutineScope{…}
块中,否则在两个块中的一个失败的情况下,代码将泄漏coroutines。@MarkoTopolnik不是由调用它的runBlocking
处理的。如果第一个async{…}
失败,那么它将抛出firstName.await()
,第二个基本上继续运行。runBlocking不会得到错误并终止第二个错误吗?它转义方法,但不转义调用(runBlocking
)范围。是的,但这意味着它不包含在函数中,您必须使用外部runBlocking
来修复它。内部coroutineScope
是正确的习惯用法和最佳实践。可以从runBlocking
调用该函数,也可以不调用该函数。此外,如果没有coroutineScope
代码甚至无法编译,那么就没有coroutineScope
可以调用async
。