Akka Ask 是否在当前线程上阻塞

Is Akka Ask Blocking on the Current Thread

我有一个场景,我必须通过他的 ID 获取用户的详细信息。这是一个进入我的 HTTP 处理程序层的 HTTP 请求,我使用从请求中获取的 id,向 actor 发送消息,然后 actor 与数据库服务对话以获取用户。

既然这是一个 HTTP 请求,我需要通过发回响应来满足请求。所以我想到了使用Akka ask模式,但是我有以下问题:

  1. 这会阻塞我当前的线程吗?

  2. 在我这里使用询问模式来获取用户是一个可扩展的解决方案吗?我的意思是,我可能有几百到一百万用户在任何给定时间点调用此端点。使用询问模式来获取用户是个好主意吗?

在代码中,它在我的 HTTP 控制器中看起来像这样

val result: Future[Any] = userActor ? FetchUser(id)

在我的演员中,我会做以下事情:

case fetchUser: FetchUser => sender ! myService.getUser(fetchUser.id)

按照您提出问题的相同顺序回答您的问题:

  1. 不,使用?不会阻塞当前线程。马上就returns一个Future。但是,Future 中的结果可能不会立即可用。
  2. 如果您需要 "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