简体   繁体   English

创建多个期货时,Play框架动作响应被延迟

[英]Play framework action response delayed when creating multiple futures

In the following action it should return response immediately after hitting URL but instead it waits till all the Future blocks are started and then only sends response. 在以下操作中,它应该在击中URL后立即返回响应,但要等到所有Future模块启动后才发送响应。 It waits till "Starting for group 10" is logged in console even though "Returning from action" is logged immediately after hitting URL. 即使点击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"))
}

I am not able to understand reason behind this delay and how can i make this action send response immediately. 我无法理解此延迟背后的原因,如何使该操作立即发送响应。

Play framework version 2.5.9 播放框架版本2.5.9

Your Action is not Async. 您的操作不是异步的。 You have a synchronous endpoint which is why you see the Returning from action printed immediately on the console. 您有一个同步端点,这就是为什么您立即在控制台上看到“ Returning from action”的原因。 You should probably use the Action.async as your processing type. 您可能应该使用Action.async作为处理类型。 Using async Actions will drastically improve the overall performance of your application and is highly recommended when building high throughput and responsive web applications. 使用异步操作将大大提高应用程序的整体性能,强烈建议在构建高吞吐量和响应式Web应用程序时使用。

Two points in your code needs to change 代码中的两点需要更改

  1. Asynchronous Action : Because you are using Future, the action should be asynchronous: Action.async{...} . 异步动作 :因为您使用的是Future,所以该动作应该是异步的: Action.async{...}

  2. No Blocking Code : The whole point of using Future and asynchronous programming is not to have a code that "blocks" the execution. 无阻塞代码 :使用Future和异步编程的全部目的是不要拥有“阻塞”执行的代码。 So I suggest to remove the Thread.sleep(1000) part of the code. 因此,我建议删除代码的Thread.sleep(1000)部分。

Note that if you write your code non-blocking way; 请注意,如果您以非阻塞方式编写代码; whenever the action method get the result; 每当动作方法得到结果时; it will perform the required action(s), such as logging or providing the view. 它将执行所需的操作,例如记录日志或提供视图。

This is because there are race conditions in your Futures. 这是因为您的期货中存在竞争条件。

You need to ensure that you are returning a single Future[T] and not a Future[Future[T]] (or any layered variances). 您需要确保返回的是单个Future[T]而不是Future[Future[T]] (或任何分层的方差)。

If the Futures are independent of each other, use Future.sequence 如果期货彼此独立,请使用Future.sequence

example: 例:

 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
 }

This will avoid race conditions 这样可以避免比赛条件

FYI, this has nothing to do with the Play framework. 仅供参考,这与Play框架无关。 This is concurrent programming in scala. 这是Scala中的并发编程。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM