Play 框架:异步与同步性能

dat*_*ser 2 multithreading asynchronous scala playframework-2.0

我有以下代码:

  def sync = Action {
      val t0 = System.nanoTime()
      Thread.sleep(100)
      val t1 = System.nanoTime()
      Ok("Elapsed time: " + (t1 - t0) / 1000000.0 + "ms") 
  }

  def async = Action {
    val t0 = System.nanoTime()
    Async { 
          Future{
            Thread.sleep(100)
            val t1 = System.nanoTime()
            Ok("Elapsed time: " + (t1 - t0) / 1000000.0 + "ms") 
            }   
    }
  }
Run Code Online (Sandbox Code Playgroud)

上述代码的区别在于,sync 将在接收请求的线程上休眠,而 async 将在单独的线程上休眠,以便负责接收请求的线程可以继续接收请求而不会阻塞。当我分析线程时,我发现为异步请求创建的线程数量如预期突然增加。然而,上述两种方法(4000 个并发连接 20 秒斜坡)会产生相同的吞吐量和延迟。我希望异步能够表现得更好。为什么会这样呢?

Fer*_*eia 5

简而言之,这两种方法本质上是相同的。

操作本身始终是异步的(请参阅有关处理异步结果的文档)。

在这两种情况下,sleep调用都发生在操作的线程池中(这不是最佳的)。

正如理解 Play 线程池中所述:

Play 框架从下到上是一个异步 Web 框架。使用迭代器异步处理流。Play 中的线程池经过调整,使用比传统 Web 框架更少的线程,因为 play-core 中的 IO 永远不会阻塞。

因此,如果您计划编写阻塞 IO 代码,或者可能执行大量 CPU 密集型工作的代码,您需要确切地知道哪个线程池正在承担该工作负载,并且需要相应地对其进行调整。

例如,此代码片段使用单独的线程池:

Future {
  // Some blocking or expensive code here
}(Contexts.myExecutionContext)
Run Code Online (Sandbox Code Playgroud)

作为其他资源,请参阅此答案此视频以获取有关处理异步操作的更多信息,以及论坛消息以获取有关该主题的广泛讨论。