在 db 调用上调用 Await.result 的风险有多大 [英] How risky is it to call Await.result on db calls

查看:15
本文介绍了在 db 调用上调用 Await.result 的风险有多大的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在使用 phantom 时,在 db 调用中遵循这种模式有多危险:

Await.result(dbOperationFut, 30.seconds)

这并不是真正的幻象特定的,而是正在使用的 Scala 驱动程序.

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

我个人赞成使用 for-comp 而不是像这样阻塞,但只是想知道这是一种非常糟糕的做法还是很好.

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

想法?

解决方案

小心 Await.result

注意这适用于 Akka 和 play 应用

<块引用>

Await.result 仅在绝对必要时才应谨慎使用.

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

因此,尽可能避免使用 Await.result.

<块引用>

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

这是使用 Await.result 的典型用例之一.

假设您编写了一个包含主线程的程序,并且主线程内的所有计算都是异步的.现在,一旦您在主线程内开始异步计算.有些人必须停止主线程的存在,直到异步计算完成,否则程序停止运行,您看不到异步计算的结果.

<块引用>

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

object Main {def main(args: Array[String]): Unit = {导入 scala.concurrent.Future导入 scala.concurrent.duration._val f = Future {//做某事 }//停止主线程直到f完成Await.result(f, 10 秒)}}

<块引用>

Future 使用守护线程来运行.所以守护线程不能阻止JVM关闭.因此,即使非守护线程正在运行,JVM 也会关闭.

在上述情况下,没有其他方法可以期望停止(阻塞)主线程,直到计算 f 完成,如果主线程没有退出并且计算停止.

<块引用>

在大多数情况下,您不需要使用 Await.result 和简单的 Future 组合,使用 mapflatMap 就足够了.

使用Await.result的风险(一般都是阻塞代码)

<块引用>

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

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

<块引用>

在非基于事件的模型中内存不足

在每个请求模型的线程中.当您遇到需要很长时间退出/返回的阻塞调用时.

情况 1:如果您有固定的线程池,那么应用程序可能会耗尽线程.

情况 2:如果您有动态增长的线程池,那么您的应用程序将遭受过多的上下文切换开销,并且还会因为内存中的阻塞线程过多而耗尽内存.

在所有情况下,除了等待某些 IO 或某些其他事件外,没有完成任何有用的工作.

When using phantom how dangerous is it to be following this pattern in db calls:

Await.result(dbOperationFut, 30.seconds)

This isn't really phantom specific but it is the scala driver being used.

I am weary of this pattern because of the potential GC pause that might last for over x seconds. How many seconds is safe given GC pauses?

I am personally in favor of using for-comp and not blocking like this, but just want to know if this is a REALLY bad practice or it is fine.

Context: This would be for akka based applications (akka, akka http)

Thoughts?

解决方案

Becareful with Await.result

Note this applies for both Akka and play apps

Await.result should be used very carefully only when it is absolutely necessary.

Await.result blocks the thread in which it is running until the given duration. Blocking the thread will waste the precious computation resource because that thread will not be able to do any useful computation like handling the new request or number crunching in an algorithm etc.

So, Avoid using the Await.result as much as possible.

But, when do we use it (Await.result) ?

Here is one of the typical use case for using Await.result.

Lets say you have written a program containing main thread and all the computation inside the main thread is asynchronous. Now once you start the asynchronous computation inside the main thread. Some one has to stop the main thread from existing till the asynchronous computation finishes, if not the program stops running and you cannot see the result of the asynchronous computation.

When an application begins running, there is one non-daemon thread, whose job is to execute main(). JVM will not exit by itself until and unless non-daemon threads are completed.

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 uses daemon threads for running. So daemon threads cannot stop the JVM from shutting down. So JVM shuts down even if non-daemon threads are running.

In the above case there is no other way expect stopping (blocking) the main thread till the computation f completes if not main thread exits and computation stops.

In most of the cases you do not need to use Await.result and simple Future composition using map and flatMap would suffice.

Risks of using Await.result (In general all blocking code)

Running out of threads in event based model

In event based model you will quickly run out of threads if you have blocking code which takes long time to return. In playframework any blocking call could decrease the performance of the application and app will becomes dead slow as it runs out of threads.

Running out of memory in non-event based models

In thread per request models. When you have blocking calls which take long time to exit/return.

case 1: If you have fixed thread pool then application might run out of threads.

case 2: If you have dynamically growing thread pool then your application will suffer from too much context switching overhead and also will run out of memory because of too many blocked threads in memory.

In all of the cases no useful work is done expect for waiting for some IO or some other event.

这篇关于在 db 调用上调用 Await.result 的风险有多大的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆