Playframework非阻塞动作

时间:2014-11-27 02:41:01

标签: scala playframework akka

遇到问题我还没找到答案。

使用Scala在playframework 2上运行。

需要编写执行多个Future调用的Action方法。 我的问题: 1)附加的代码是否是非阻塞的,因此看起来应该如何? 2)是否保证在任何给定时间都捕获两个DAO结果?

def index = Action.async {

  val t2:Future[Tuple2[List[PlayerCol],List[CreatureCol]]] = for {
    p <- PlayerDAO.findAll()
    c <- CreatureDAO.findAlive()
  }yield(p,c)

  t2.map(t => Ok(views.html.index(t._1, t._2)))
}

感谢您的反馈。

1 个答案:

答案 0 :(得分:6)

  

附加的代码是非阻塞的,因此看起来应该是这样吗?

这取决于一些事情。首先,我假设PlayerDAO.findAll()CreatureDAO.findAlive()分别返回Future[List[PlayerCol]]Future[List[CreatureCol]]。最重要的是这些功能实际上是自称的。他们是在进行JDBC调用,还是使用异步数据库驱动程序?

如果答案是JDBC(或其他一些同步数据库驱动程序),那么你仍然在阻塞,并且没有办法让它完全“非阻塞”。为什么?因为JDBC调用阻止了它们当前的线程,并且将它们包装在Future中将无法解决这个问题。在这种情况下,您可以做的最多就是让它们阻止与Play用于处理请求的ExecutionContext不同的ExecutionContext。这通常是个好主意,因为如果你有几个并发运行的db请求,它们可以阻止用于处理HTTP请求的Play内部线程池,突然你的服务器必须等待处理其他请求(即使它们不需要)数据库调用)。

有关不同index的更多信息,请参阅thread pools documentationthis answer

如果你的回答是一个异步数据库驱动程序,比如反应性mongo(还有scalike-jdbc,也许还有其他一些),那么你的状态很好,我可能会让你阅读的内容比你不得不多了。在这种情况下,您的CreatureDAO.findAlive()控制器功能将完全无阻塞。

  

是否可以保证在任何给定时间都捕获两个DAO结果?

我不太清楚你的意思。在您当前的代码中,您实际上是按顺序进行这些调用。在PlayerDAO.findAll()返回之前,Future不会执行。由于它们不相互依赖,似乎这不是故意的。要使它们并行运行,您应该在将它们映射到for-comprehension之前实例化def index = Action.async { val players: Future[List[PlayerCol]] = PlayerDAO.findAll() val creatures: Future[List[CreatureCol]] = CreatureDAO.findAlive() val t2: Future[(List[PlayerCol], List[CreatureCol])] = for { p <- players c <- creatures } yield (p, c) t2.map(t => Ok(views.html.index(t._1, t._2))) }

yield

唯一可以保证两个结果都完成的事情是Futuret2.map(...)完成之前(或者永远不会,如果失败的话)不执行,同样也是<{1}}完成后才会执行t2


进一步阅读:

Are there any benefits in using non-async actions in Play Framework 2.2?

Understanding the Difference Between Non-Blocking Web Service Calls vs Non-Blocking JDBC