在db调用上调用Await.result有多大的风险

时间:2016-11-24 22:08:09

标签: scala cassandra phantom-dsl

使用幻像时,在db调用中遵循此模式有多危险:

Await.result(dbOperationFut, 30.seconds)

这不是特定的幻像,但它是使用的scala驱动程序。

我厌倦了这种模式,因为潜在的GC暂停可能会持续超过x秒。 GC暂停时安全多少秒?

我个人赞成使用for-comp而不是像这样阻止,但只是想知道这是不是很糟糕的做法,或者它很好。

上下文:这适用于基于akka的应用程序(akka,akka http)

思想?

1 个答案:

答案 0 :(得分:2)

对Await.result感到满意

请注意,这适用于Akka和播放应用

  只有在绝对必要时才应非常小心地使用

Await.result

Await.result阻止运行它的线程,直到给定的持续时间。阻塞线程将浪费宝贵的计算资源,因为该线程将无法执行任何有用的计算,如处理新请求或算法中的数字运算等。

因此,尽量避免使用Await.result

  

但是,我们什么时候使用它(Await.result)?

以下是使用Await.result的典型用例之一。

假设您已编写包含主线程的程序,并且主线程内的所有计算都是异步的。现在,一旦在主线程内启动异步计算。有些人必须停止主线程的存在,直到异步计算完成,如果不是程序停止运行,你就看不到异步计算的结果。

  

当应用程序开始运行时,有一个非守护程序线程,其作用是执行main()。除非非守护程序线程完成,否则JVM不会自行退出。

object Main {
 def main(args: Array[String]): Unit = {
  import scala.concurrent.Future
  import scala.concurrent.duration._

  val f = Future { //do something }
  //stop main thread till f completes
  Await.result(f, 10 seconds)
 }
}
  

Future使用守护程序线程进行运行。因此守护程序线程无法阻止JVM关闭。因此,即使非守护程序线程正在运行,JVM也会关闭。

在上面的例子中,没有其他方法可以阻止(阻塞)主线程直到计算f完成,如果主线程没有退出并且计算停止。

  

在大多数情况下,您不需要使用Await.result,使用Futuremap进行简单flatMap合成就足够了。

使用Await.result的风险(通常所有阻止代码)

  

在基于事件的模型中耗尽线程

在基于事件的模型中,如果您有阻塞代码需要很长时间才能返回,那么您将很快耗尽线程。在playframework中,任何阻塞调用都可能降低应用程序的性能,并且应用程序在线程耗尽时会变得很慢。

  

在基于非事件的模型中耗尽内存

在每个请求模型的线程中。当您有阻止呼叫时需要很长时间才能退出/返回。

案例1:如果你有固定的线程池,那么应用程序可能会用完线程。

案例2:如果你有一个动态增长的线程池,你的应用程序将遭受过多的上下文切换开销,并且由于内存中被阻塞的线程太多,内存也会耗尽。

在所有情况下,等待某些IO或其他事件都无法完成任何有用的工作。