Akka Ask 是否在当前线程上阻塞
Is Akka Ask Blocking on the Current Thread
我有一个场景,我必须通过他的 ID 获取用户的详细信息。这是一个进入我的 HTTP 处理程序层的 HTTP 请求,我使用从请求中获取的 id,向 actor 发送消息,然后 actor 与数据库服务对话以获取用户。
既然这是一个 HTTP 请求,我需要通过发回响应来满足请求。所以我想到了使用Akka ask模式,但是我有以下问题:
这会阻塞我当前的线程吗?
在我这里使用询问模式来获取用户是一个可扩展的解决方案吗?我的意思是,我可能有几百到一百万用户在任何给定时间点调用此端点。使用询问模式来获取用户是个好主意吗?
在代码中,它在我的 HTTP 控制器中看起来像这样
val result: Future[Any] = userActor ? FetchUser(id)
在我的演员中,我会做以下事情:
case fetchUser: FetchUser => sender ! myService.getUser(fetchUser.id)
按照您提出问题的相同顺序回答您的问题:
- 不,使用
?
不会阻塞当前线程。马上就returns一个Future
。但是,Future 中的结果可能不会立即可用。
- 如果您需要 "scalable" 的解决方案,并且您的服务能够进行多个并发查询,那么您可能需要使用 pool 个 Actors,这样您就可以为多个
?
一次,或者查看下面的 Futures only,可扩展的解决方案。
期货独家
如果您的 Actors 没有缓存任何中间值,那么您可以直接使用 Futures 并避免繁琐的 Actors(例如 Props、actorOf、receive、?、...):
import java.util.concurrent.Executors
import scala.concurrent.{ExecutionContext,Future}
object ServicePool {
private val myService = ???
val maxQueries = 11 //should come from a configuration file instead
private val queryExecutionPool =
ExecutionContext.fromExecutor(Executors.newFixedThreadPool(maxQueries))
type ID = ???
/**Will only hit the DB with maxQueries at once.*/
def queryService(id : ID) =
Future { myService getUser id }(queryExecutionPool)
}//end object ServiceQuery
您现在可以随心所欲地调用 ServicePool.queryService
,但一次服务不会被超过 maxQueries
且没有 Actors:
val alotOfIDs : Seq[ID] = (1 to 1000000) map { i => ID(i)}
val results = alotOfIDs map ServicePool.queryService
我有一个场景,我必须通过他的 ID 获取用户的详细信息。这是一个进入我的 HTTP 处理程序层的 HTTP 请求,我使用从请求中获取的 id,向 actor 发送消息,然后 actor 与数据库服务对话以获取用户。
既然这是一个 HTTP 请求,我需要通过发回响应来满足请求。所以我想到了使用Akka ask模式,但是我有以下问题:
这会阻塞我当前的线程吗?
在我这里使用询问模式来获取用户是一个可扩展的解决方案吗?我的意思是,我可能有几百到一百万用户在任何给定时间点调用此端点。使用询问模式来获取用户是个好主意吗?
在代码中,它在我的 HTTP 控制器中看起来像这样
val result: Future[Any] = userActor ? FetchUser(id)
在我的演员中,我会做以下事情:
case fetchUser: FetchUser => sender ! myService.getUser(fetchUser.id)
按照您提出问题的相同顺序回答您的问题:
- 不,使用
?
不会阻塞当前线程。马上就returns一个Future
。但是,Future 中的结果可能不会立即可用。 - 如果您需要 "scalable" 的解决方案,并且您的服务能够进行多个并发查询,那么您可能需要使用 pool 个 Actors,这样您就可以为多个
?
一次,或者查看下面的 Futures only,可扩展的解决方案。
期货独家
如果您的 Actors 没有缓存任何中间值,那么您可以直接使用 Futures 并避免繁琐的 Actors(例如 Props、actorOf、receive、?、...):
import java.util.concurrent.Executors
import scala.concurrent.{ExecutionContext,Future}
object ServicePool {
private val myService = ???
val maxQueries = 11 //should come from a configuration file instead
private val queryExecutionPool =
ExecutionContext.fromExecutor(Executors.newFixedThreadPool(maxQueries))
type ID = ???
/**Will only hit the DB with maxQueries at once.*/
def queryService(id : ID) =
Future { myService getUser id }(queryExecutionPool)
}//end object ServiceQuery
您现在可以随心所欲地调用 ServicePool.queryService
,但一次服务不会被超过 maxQueries
且没有 Actors:
val alotOfIDs : Seq[ID] = (1 to 1000000) map { i => ID(i)}
val results = alotOfIDs map ServicePool.queryService