在 Controller NonFatal 中捕获异常
Catching Exception in Controller NonFatal
假设我有以下控制器方法:
def getAllRules() = AuthAction("View" on "Rules").async {
Metrics.measureTime("getAllRules", category = Category) {
ruleService.getAllRules.map({
case Nil => NoContent
case rules => Ok(Json.toJson(rules.toViewRules))
}).recover {
case e: Exception => handlerError(s"Failure occurred on getAllRules, ex: ${e.getMessage}", "getAllRules")
}
}
}
当 handleError
是:
def handlerError(err: String, occurredOn: String): Result = {
Metrics.errorsCounter(occurredOn).increment()
logger.error(err)
InternalServerError(Json.toJson(Json.obj("error" -> err)))
}
我明白捕获所有异常是错误的,我应该只捕获 NonFatal
个异常。
我想问:
- 什么是致命异常?怎么会发生?
VirtualMachineError, InterruptedException, LinkageError, ControlThrowable
- 为什么捕获所有异常不好,而只捕获
NonFatal
?
- 在
Fatal
异常的情况下 - 它需要如何处理?代码示例会很好,并提供解释
- 只是为了确保 - 如果控制器不会捕获任何异常,在 k8s 和 docker env 中,Pod 将因状态错误而失败并重新启动 - 对吗?
What is a Fatal Exception? How can occur? VirtualMachineError, InterruptedException, LinkageError, ControlThrowable
基本上,您可以考虑致命错误 - 那些您无法正确处理的错误。例如。 VirtualMachineError
或任何其他 java.lang.Error
识别 JVM 内部发生的问题,您不能做太多事情:像 AbstractMethodError
- 识别以某种方式被调用的方法没有实现,这意味着问题在字节码中。
或著名的 OutOfMemmoryError
- 通常建议不要处理,因为它可能导致堆损坏或其他问题。让他们让应用程序崩溃。
Why it's not good to catch all exceptions, but only NonFatal?
Because, suing case NonFatal(e) =>
you avoiding possible problems describe before.
In the case of Fatal Exception - how its need to be handled?,
code-example would be great with an explanation
你不应该发现它们 - 致命错误你的朋友,将使故障排除更容易。让他们崩溃应用程序。这是正确的做法。
Just to make sure - If the controller will not catch any Exception, in
k8s & docker env, the Pod will be failed with status Error and make a
Restart - Right?
是的,但请确保您有一些 circuit breaker
逻辑 - 不要无休止地重新启动应用程序,如果这样做没有帮助。例如。如果 AbstractMethodError
- 二进制文件存在问题并且修复它的唯一方法 - 重新构建或修复依赖项,但重述只会消耗资源,而不会产生结果。
我觉得看NonFatal
的apply
方法是最好理解的:
def apply(t: Throwable): Boolean = t match {
// VirtualMachineError includes OutOfMemoryError and other fatal errors
case _: VirtualMachineError | _: ThreadDeath | _: InterruptedException | _: LinkageError | _: ControlThrowable => false
case _ => true
}
来自Scaladoc:
Extractor of non-fatal Throwables. Will not match fatal errors like VirtualMachineError (for example, OutOfMemoryError and WhosebugError, subclasses of VirtualMachineError), ThreadDeath, LinkageError, InterruptedException, ControlThrowable.
让我们深入探讨上面的每个异常:
VirtualMachineError
:抛出表示 Java 虚拟机已损坏或 运行 没有继续运行所需的资源。
ThreadDeath
:只有在异步终止后必须清理时,应用程序才应捕获此 class 的实例。如果 ThreadDeath 被某个方法捕获,重要的是重新抛出它以便线程真正死亡。
InterruptedException
:偶尔一个方法可能希望测试当前线程是否已经被中断,如果是,就立即抛出这个异常。
LinkageError
:{@code LinkageError} 的 Subclasses 表明一个 class 对另一个 class 有一些依赖;然而,后者class在前者class.
编译后发生了不兼容的变化
ControlThrowable
:用于流控制的可抛对象的父对象 class。 ControlThrowable
的实例通常不应被捕获。
如你所见,所有异常都是进程无法恢复的异常。因此,最好让那些异常冒泡,并终止进程。
用法应该是(来自我附上的NonFatal
页面):
try {
// dangerous stuff
} catch {
case NonFatal(e) => log.error(e, "Something not that bad.")
// or
case e if NonFatal(e) => log.error(e, "Something not that bad.")
}
假设我有以下控制器方法:
def getAllRules() = AuthAction("View" on "Rules").async {
Metrics.measureTime("getAllRules", category = Category) {
ruleService.getAllRules.map({
case Nil => NoContent
case rules => Ok(Json.toJson(rules.toViewRules))
}).recover {
case e: Exception => handlerError(s"Failure occurred on getAllRules, ex: ${e.getMessage}", "getAllRules")
}
}
}
当 handleError
是:
def handlerError(err: String, occurredOn: String): Result = {
Metrics.errorsCounter(occurredOn).increment()
logger.error(err)
InternalServerError(Json.toJson(Json.obj("error" -> err)))
}
我明白捕获所有异常是错误的,我应该只捕获 NonFatal
个异常。
我想问:
- 什么是致命异常?怎么会发生?
VirtualMachineError, InterruptedException, LinkageError, ControlThrowable
- 为什么捕获所有异常不好,而只捕获
NonFatal
? - 在
Fatal
异常的情况下 - 它需要如何处理?代码示例会很好,并提供解释 - 只是为了确保 - 如果控制器不会捕获任何异常,在 k8s 和 docker env 中,Pod 将因状态错误而失败并重新启动 - 对吗?
What is a Fatal Exception? How can occur? VirtualMachineError, InterruptedException, LinkageError, ControlThrowable
基本上,您可以考虑致命错误 - 那些您无法正确处理的错误。例如。 VirtualMachineError
或任何其他 java.lang.Error
识别 JVM 内部发生的问题,您不能做太多事情:像 AbstractMethodError
- 识别以某种方式被调用的方法没有实现,这意味着问题在字节码中。
或著名的 OutOfMemmoryError
- 通常建议不要处理,因为它可能导致堆损坏或其他问题。让他们让应用程序崩溃。
Why it's not good to catch all exceptions, but only NonFatal? Because, suing
case NonFatal(e) =>
you avoiding possible problems describe before.In the case of Fatal Exception - how its need to be handled?, code-example would be great with an explanation
你不应该发现它们 - 致命错误你的朋友,将使故障排除更容易。让他们崩溃应用程序。这是正确的做法。
Just to make sure - If the controller will not catch any Exception, in k8s & docker env, the Pod will be failed with status Error and make a Restart - Right?
是的,但请确保您有一些 circuit breaker
逻辑 - 不要无休止地重新启动应用程序,如果这样做没有帮助。例如。如果 AbstractMethodError
- 二进制文件存在问题并且修复它的唯一方法 - 重新构建或修复依赖项,但重述只会消耗资源,而不会产生结果。
我觉得看NonFatal
的apply
方法是最好理解的:
def apply(t: Throwable): Boolean = t match {
// VirtualMachineError includes OutOfMemoryError and other fatal errors
case _: VirtualMachineError | _: ThreadDeath | _: InterruptedException | _: LinkageError | _: ControlThrowable => false
case _ => true
}
来自Scaladoc:
Extractor of non-fatal Throwables. Will not match fatal errors like VirtualMachineError (for example, OutOfMemoryError and WhosebugError, subclasses of VirtualMachineError), ThreadDeath, LinkageError, InterruptedException, ControlThrowable.
让我们深入探讨上面的每个异常:
VirtualMachineError
:抛出表示 Java 虚拟机已损坏或 运行 没有继续运行所需的资源。ThreadDeath
:只有在异步终止后必须清理时,应用程序才应捕获此 class 的实例。如果 ThreadDeath 被某个方法捕获,重要的是重新抛出它以便线程真正死亡。InterruptedException
:偶尔一个方法可能希望测试当前线程是否已经被中断,如果是,就立即抛出这个异常。
编译后发生了不兼容的变化LinkageError
:{@code LinkageError} 的 Subclasses 表明一个 class 对另一个 class 有一些依赖;然而,后者class在前者class.ControlThrowable
:用于流控制的可抛对象的父对象 class。ControlThrowable
的实例通常不应被捕获。
如你所见,所有异常都是进程无法恢复的异常。因此,最好让那些异常冒泡,并终止进程。
用法应该是(来自我附上的NonFatal
页面):
try {
// dangerous stuff
} catch {
case NonFatal(e) => log.error(e, "Something not that bad.")
// or
case e if NonFatal(e) => log.error(e, "Something not that bad.")
}