问题描述
在使用 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
组合,使用 map
和 flatMap
就足够了.
使用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
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.
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.
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)
}
}
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.
Risks of using Await.result (In general all blocking code)
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.
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 的风险有多大的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!