Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/json/14.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Scala:未来如何管理致命错误(如OOM)_Scala_Future_Fatal Error - Fatal编程技术网

Scala:未来如何管理致命错误(如OOM)

Scala:未来如何管理致命错误(如OOM),scala,future,fatal-error,Scala,Future,Fatal Error,我们的分布式应用程序中存在一些奇怪的行为。我们还没有找到原因,但我们认为这可能与OutOfMemory错误有关 然而,我们试图遵循关于致命错误的良好编码实践,例如从不捕获所有可丢弃的错误,以及最大非致命错误。但我意识到,对于将来发生的致命错误,我还不太了解,我们的代码在某种程度上几乎都被包装到了未来 下面是一个简单的例子: val f = Future{ /* some code that makes an OOM error */ } val result = Await.result(f,

我们的分布式应用程序中存在一些奇怪的行为。我们还没有找到原因,但我们认为这可能与OutOfMemory错误有关

然而,我们试图遵循关于致命错误的良好编码实践,例如从不捕获所有可丢弃的错误,以及最大非致命错误。但我意识到,对于将来发生的致命错误,我还不太了解,我们的代码在某种程度上几乎都被包装到了未来

下面是一个简单的例子:

val f = Future{ /* some code that makes an OOM error */ }
val result = Await.result(f, 1 minutes)
发生的是

  • 运行未来代码的线程失败。OOM是用stderr打印的。但我们没有看到它,因为应用程序部署在“某处”,我们没有重定向stderr
  • 然而,未来并没有结束(它只捕获非致命的病毒)。值得的是,它不会释放资源
  • 1分钟后,我们得到与OOM无关的TimeoutException。希望它能释放资源。但我们已经失去了时间,其他线程可能会受到影响。然后我们把它当作一个没有时间完成的未来。类似地,如果某些数据库访问没有及时响应,即我们通常会重试
我在这里找到了对该问题的良好描述:

我的问题:我们应该如何处理将来发生的致命错误

  • 至少,整个应用程序应该像主线程中发生致命错误一样失败。也许是堆芯垃圾
  • 最好是进行适当的管理:记录异常,应用适当的重新执行模式,可能优雅地终止其他正在运行的未来/线程

注意:这是一个与类似的问题,但答案是“这是有意的”,而不是如何管理它

我找到了一种方法,它要求使用我们自己的ExecutionContext,执行者包含我们自己的UncaughtExceptionHandler:

// UncaughtExceptionHandler that process Fatal error
val exceptionHandler = new Thread.UncaughtExceptionHandler {
  override def uncaughtException(t: Thread, err: Throwable): Unit =  err match {
    case NonFatal(_) =>
      // don't process NonFatal which should be managed by the processing code

    case t =>
      // process fatal error
      log.error("FATAL ERROR", t)
      System.exit(1)       
  }
}


// make the Execution context with our UncaughtExceptionHandler
//   here I chose a ForkJoinPool which is the type of EC.global
//   I hard-coded the thread number to 8. global use the number of available core
val fjp = new ForkJoinPool(8, ForkJoinPool.defaultForkJoinWorkerThreadFactory, exceptionHandler, false)
implicit val ec = ExecutionContext.fromExecutor(fjp)


// used implicitly in the future code
val f = Future{ /* some code that makes an OOM error */ }
val result = Await.result(f, 1 minutes)

你考虑过这个解决方案吗?不。实际上,java中也存在同样的问题,这个解决方案可以在这里应用(这是我问题的有效答案)。OOM是我最关心的问题,但您知道它是否可以应用于其他致命错误吗?请尝试Scala 2.13.0-M5一旦发布,我已经重新处理了致命错误的处理,但我不知道它会如何影响您的特定代码。谢谢,当它出现时,我会研究它。
case t
可能会捕捉到多个异常。您不希望Controlle异常杀死jvm。使用
-XX:+ExitOnOutOfMemoryError
而不是相反,这里的错误管理非常简单,可以提出我的案例(并且符合我的第一个要求“至少,整个应用程序应该失败”)。这可能不是我们想要做的,也不是所有致命的错误。