在创建多个期货时,播放框架操作响应延迟

时间:2018-03-08 10:22:35

标签: scala playframework

在以下操作中,它应该在命中URL后立即返回响应,而是等待直到所有Future块都启动,然后才发送响应。等到"开始第10组"即使"从行动中返回"也会在控制台中登录在点击URL后立即记录。

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

3 个答案:

答案 0 :(得分:0)

您的操作不是异步。您有一个同步端点,这就是您在控制台上看到立即打印的返回操作的原因。您应该使用Action.async作为处理类型。使用异步操作可以极大地提高应用程序的整体性能,强烈建议在构建高吞吐量和响应式Web应用程序时使用。

答案 1 :(得分:0)

代码中的两点需要更改

  1. 异步操作:由于您使用的是Future,因此操作应该是异步的:Action.async{...}

  2. 无阻塞代码:使用Future和异步编程的全部意义不是要有一个代码来阻止"阻塞"执行。所以我建议删除代码的Thread.sleep(1000)部分。

  3. 请注意,如果您以非阻塞的方式编写代码;每当action方法得到结果;它将执行所需的操作,例如记录或提供视图。

答案 2 :(得分:-1)

这是因为您的期货存在竞争条件。

您需要确保返回单个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中的并发编程。