[英]Play framework action response delayed when creating multiple futures
在以下操作中,它应该在击中URL后立即返回响应,但要等到所有Future模块启动后才发送响应。 即使点击URL后立即记录了“从操作返回”,它也会一直等到“正在启动第10组”被记录在控制台中。
def test = Action { implicit request =>
Future.successful(0 to 150).foreach { items =>
items.grouped(15).zipWithIndex.foreach{ itemGroupWithIndex =>
val (itemGroup, index) = itemGroupWithIndex
Future {
logger.info("************** Starting for group " + index)
itemGroup.foreach { item =>
Thread.sleep(1000)
logger.info("Completed for item " + item)
}
}
}
}
logger.info("************** Returning from action **************")
Ok(views.html.test("test page"))
}
我无法理解此延迟背后的原因,如何使该操作立即发送响应。
播放框架版本2.5.9
您的操作不是异步的。 您有一个同步端点,这就是为什么您立即在控制台上看到“ Returning from action”的原因。 您可能应该使用Action.async作为处理类型。 使用异步操作将大大提高应用程序的整体性能,强烈建议在构建高吞吐量和响应式Web应用程序时使用。
代码中的两点需要更改
异步动作 :因为您使用的是Future,所以该动作应该是异步的: Action.async{...}
。
无阻塞代码 :使用Future和异步编程的全部目的是不要拥有“阻塞”执行的代码。 因此,我建议删除代码的Thread.sleep(1000)
部分。
请注意,如果您以非阻塞方式编写代码; 每当动作方法得到结果时; 它将执行所需的操作,例如记录日志或提供视图。
这是因为您的期货中存在竞争条件。
您需要确保返回的是单个Future[T]
而不是Future[Future[T]]
(或任何分层的方差)。
如果期货彼此独立,请使用Future.sequence
例:
def future: Future[String] = Future.successful("hi")
def action = Action.async { _ =>
val futures: Seq[Future[String]] = (1 to 50).map(_ => future()).toSeq
val oneFuture = Future.sequence(futures)
oneFuture
}
这样可以避免比赛条件
仅供参考,这与Play框架无关。 这是Scala中的并发编程。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.