scala.MatchError:某个时间点之后的所有请求都为空

Posted

技术标签:

【中文标题】scala.MatchError:某个时间点之后的所有请求都为空【英文标题】:scala.MatchError: null for all requests after some timepoint 【发布时间】:2016-02-12 15:41:50 【问题描述】:

我有一个相当大的 Play Framework 应用程序在生产中运行 Play 2.4.3。我遇到过一些情况,突然对服务器的所有请求都开始收到以下 MatchError:

! @6p4o8d49h - Internal server error, for (GET) [/bookings/desk/suggest-products?term=&maxSize=50&page=1] ->
play.api.UnexpectedException: Unexpected exception[MatchError: null]
    at play.api.http.HttpErrorHandlerExceptions$.throwableToUsefulException(HttpErrorHandler.scala:261) ~[com.typesafe.play.play_2.11-2.4.3.jar:2.4.3]
    at play.api.http.HttpErrorHandlerExceptions.throwableToUsefulException(HttpErrorHandler.scala) ~[com.typesafe.play.play_2.11-2.4.3.jar:2.4.3]
    at play.http.DefaultHttpErrorHandler.throwableToUsefulException(DefaultHttpErrorHandler.java:169) ~[com.typesafe.play.play_2.11-2.4.3.jar:2.4.3]
    at play.http.DefaultHttpErrorHandler.onServerError(DefaultHttpErrorHandler.java:131) ~[com.typesafe.play.play_2.11-2.4.3.jar:2.4.3]
    at play.core.j.JavaHttpErrorHandlerAdapter$$anonfun$onServerError$1.apply(JavaHttpErrorHandlerAdapter.scala:22) [com.typesafe.play.play_2.11-2.4.3.jar:2.4.3]
    at play.core.j.JavaHttpErrorHandlerAdapter$$anonfun$onServerError$1.apply(JavaHttpErrorHandlerAdapter.scala:22) [com.typesafe.play.play_2.11-2.4.3.jar:2.4.3]
    at play.core.j.JavaHelpers$$anonfun$invokeWithContext$1.apply(JavaHelpers.scala:140) [com.typesafe.play.play_2.11-2.4.3.jar:2.4.3]
    at play.core.j.JavaHelpers$$anonfun$invokeWithContext$1.apply(JavaHelpers.scala:139) [com.typesafe.play.play_2.11-2.4.3.jar:2.4.3]
    at play.core.j.JavaHelpers$class.withContext(JavaHelpers.scala:151) [com.typesafe.play.play_2.11-2.4.3.jar:2.4.3]
    at play.core.j.JavaHelpers$.withContext(JavaHelpers.scala:160) [com.typesafe.play.play_2.11-2.4.3.jar:2.4.3]
    at play.core.j.JavaHelpers$class.invokeWithContext(JavaHelpers.scala:139) [com.typesafe.play.play_2.11-2.4.3.jar:2.4.3]
    at play.core.j.JavaHelpers$.invokeWithContext(JavaHelpers.scala:160) [com.typesafe.play.play_2.11-2.4.3.jar:2.4.3]
    at play.core.j.JavaHttpErrorHandlerAdapter.onServerError(JavaHttpErrorHandlerAdapter.scala:22) [com.typesafe.play.play_2.11-2.4.3.jar:2.4.3]
    at play.core.server.netty.PlayDefaultUpstreamHandler$$anonfun$9$$anonfun$apply$1.applyOrElse(PlayDefaultUpstreamHandler.scala:158) [com.typesafe.play.play-netty-server_2.11-2.4.3.jar:2.4.3]
    at play.core.server.netty.PlayDefaultUpstreamHandler$$anonfun$9$$anonfun$apply$1.applyOrElse(PlayDefaultUpstreamHandler.scala:155) [com.typesafe.play.play-netty-server_2.11-2.4.3.jar:2.4.3]
    at scala.runtime.AbstractPartialFunction.apply(AbstractPartialFunction.scala:36) [org.scala-lang.scala-library-2.11.7.jar:na]
    at scala.util.Failure$$anonfun$recover$1.apply(Try.scala:216) [org.scala-lang.scala-library-2.11.7.jar:na]
    at scala.util.Try$.apply(Try.scala:192) [org.scala-lang.scala-library-2.11.7.jar:na]
    at scala.util.Failure.recover(Try.scala:216) [org.scala-lang.scala-library-2.11.7.jar:na]
    at scala.concurrent.Future$$anonfun$recover$1.apply(Future.scala:324) [org.scala-lang.scala-library-2.11.7.jar:na]
    at scala.concurrent.Future$$anonfun$recover$1.apply(Future.scala:324) [org.scala-lang.scala-library-2.11.7.jar:na]
    at scala.concurrent.impl.CallbackRunnable.run(Promise.scala:32) [org.scala-lang.scala-library-2.11.7.jar:na]
    at play.api.libs.iteratee.Execution$trampoline$.executeScheduled(Execution.scala:109) [com.typesafe.play.play-iteratees_2.11-2.4.3.jar:2.4.3]
    at play.api.libs.iteratee.Execution$trampoline$.execute(Execution.scala:71) [com.typesafe.play.play-iteratees_2.11-2.4.3.jar:2.4.3]
    at scala.concurrent.impl.CallbackRunnable.executeWithValue(Promise.scala:40) [org.scala-lang.scala-library-2.11.7.jar:na]
    at scala.concurrent.impl.Promise$DefaultPromise.tryComplete(Promise.scala:248) [org.scala-lang.scala-library-2.11.7.jar:na]
    at scala.concurrent.Promise$class.complete(Promise.scala:55) [org.scala-lang.scala-library-2.11.7.jar:na]
    at scala.concurrent.impl.Promise$DefaultPromise.complete(Promise.scala:153) [org.scala-lang.scala-library-2.11.7.jar:na]
    at scala.concurrent.impl.Future$PromiseCompletingRunnable.run(Future.scala:23) [org.scala-lang.scala-library-2.11.7.jar:na]
    at akka.dispatch.TaskInvocation.run(AbstractDispatcher.scala:39) [com.typesafe.akka.akka-actor_2.11-2.4.0.jar:na]
    at akka.dispatch.ForkJoinExecutorConfigurator$AkkaForkJoinTask.exec(AbstractDispatcher.scala:399) [com.typesafe.akka.akka-actor_2.11-2.4.0.jar:na]
    at scala.concurrent.forkjoin.ForkJoinTask.doExec(ForkJoinTask.java:260) [org.scala-lang.scala-library-2.11.7.jar:na]
    at scala.concurrent.forkjoin.ForkJoinPool$WorkQueue.runTask(ForkJoinPool.java:1339) [org.scala-lang.scala-library-2.11.7.jar:na]
    at scala.concurrent.forkjoin.ForkJoinPool.runWorker(ForkJoinPool.java:1979) [org.scala-lang.scala-library-2.11.7.jar:na]
    at scala.concurrent.forkjoin.ForkJoinWorkerThread.run(ForkJoinWorkerThread.java:107) [org.scala-lang.scala-library-2.11.7.jar:na]
Caused by: scala.MatchError: null
    at play.core.j.JavaAction.apply(JavaAction.scala:97) ~[com.typesafe.play.play_2.11-2.4.3.jar:2.4.3]
    at play.api.mvc.Action$$anonfun$apply$1$$anonfun$apply$4$$anonfun$apply$5.apply(Action.scala:105) ~[com.typesafe.play.play_2.11-2.4.3.jar:2.4.3]
    at play.api.mvc.Action$$anonfun$apply$1$$anonfun$apply$4$$anonfun$apply$5.apply(Action.scala:105) ~[com.typesafe.play.play_2.11-2.4.3.jar:2.4.3]
    at play.utils.Threads$.withContextClassLoader(Threads.scala:21) ~[com.typesafe.play.play_2.11-2.4.3.jar:2.4.3]
    at play.api.mvc.Action$$anonfun$apply$1$$anonfun$apply$4.apply(Action.scala:104) ~[com.typesafe.play.play_2.11-2.4.3.jar:2.4.3]
    at play.api.mvc.Action$$anonfun$apply$1$$anonfun$apply$4.apply(Action.scala:103) ~[com.typesafe.play.play_2.11-2.4.3.jar:2.4.3]
    at scala.Option.map(Option.scala:146) ~[org.scala-lang.scala-library-2.11.7.jar:na]
    at play.api.mvc.Action$$anonfun$apply$1.apply(Action.scala:103) ~[com.typesafe.play.play_2.11-2.4.3.jar:2.4.3]
    at play.api.mvc.Action$$anonfun$apply$1.apply(Action.scala:96) ~[com.typesafe.play.play_2.11-2.4.3.jar:2.4.3]
    at play.api.libs.iteratee.Iteratee$$anonfun$mapM$1.apply(Iteratee.scala:524) ~[com.typesafe.play.play-iteratees_2.11-2.4.3.jar:2.4.3]
    at play.api.libs.iteratee.Iteratee$$anonfun$mapM$1.apply(Iteratee.scala:524) ~[com.typesafe.play.play-iteratees_2.11-2.4.3.jar:2.4.3]
    at play.api.libs.iteratee.Iteratee$$anonfun$flatMapM$1.apply(Iteratee.scala:560) ~[com.typesafe.play.play-iteratees_2.11-2.4.3.jar:2.4.3]
    at play.api.libs.iteratee.Iteratee$$anonfun$flatMapM$1.apply(Iteratee.scala:560) ~[com.typesafe.play.play-iteratees_2.11-2.4.3.jar:2.4.3]
    at play.api.libs.iteratee.Iteratee$$anonfun$flatMap$1$$anonfun$apply$13.apply(Iteratee.scala:536) ~[com.typesafe.play.play-iteratees_2.11-2.4.3.jar:2.4.3]
    at play.api.libs.iteratee.Iteratee$$anonfun$flatMap$1$$anonfun$apply$13.apply(Iteratee.scala:536) ~[com.typesafe.play.play-iteratees_2.11-2.4.3.jar:2.4.3]
    at scala.concurrent.impl.Future$PromiseCompletingRunnable.liftedTree1$1(Future.scala:24) [org.scala-lang.scala-library-2.11.7.jar:na]
    at scala.concurrent.impl.Future$PromiseCompletingRunnable.run(Future.scala:24) [org.scala-lang.scala-library-2.11.7.jar:na]
    ... 6 common frames omitted

在第一个错误发生之前,日志看起来非常健康和正常,第一个异常是一些随机请求。在第一次请求遇到此错误后,所有后续请求都会收到相同的错误,直到我们重新启动服务器。

play.core.j.JavaAction.apply(JavaAction.scala:97) 看来,错误意味着返回的响应对象都是null

我查看了从发生这种情况时的一些堆空间使用情况图表,内存使用情况出现了巨大的峰值。我强烈怀疑 MatchErrors 隐藏了 OutOfMemoryError("Java heap space") 错误。

有没有办法阻止 scala.MatchError 隐藏实际的 OutOfMemoryError?

【问题讨论】:

您的操作似乎有错误,但框架并未向您显示真正的问题。您是否实现了自己的错误处理程序? playframework.com/documentation/2.4.x/JavaErrorHandling 或 playframework.com/documentation/2.4.x/GlobalSettings 是的,我有自己的 HttpErrorHandler 实现。据我所知,它能够将这些错误的报告发送到跟踪系统,并向用户显示一个错误页面,他们可以在其中向我们的支持系统报告错误。 可以在您的错误处理程序中创建匹配错误吗?这可能会隐藏原始错误。如果您遇到内存泄漏,我只能建议您在测试服务器中对您的应用程序施加压力,并在此服务器中删除您的错误处理程序。另一种选择可能是在您的用户无法访问出现故障的生产服务器上进行远程调试。 几个小时前遇到了完全相同的问题(连同内存峰值)。对此有任何跟进吗?您是否设法找出问题的根源? MatchError 仅仅是因为 JVM 无法分配内存来进行匹配。我最终所做的是更改导致 OOME 正确释放内存的部分。据我所知,当堆空间填满时,play 仍然存在运行到 MatchError 的问题。 【参考方案1】:

这是由于堆已满,Scala 需要分配堆来进行模式匹配。

解决方案是修复导致 OutOfMemoryException 的任何原因,MatchError 是一个红鲱鱼。这只是堆空间不足的副作用。

【讨论】:

感谢您发布此信息。您是如何克服隐藏 OOME 的框架的?我没有自定义错误处理程序,但堆栈的那部分丢失了。 澄清一下,我根本没有设法克服隐藏 OOME 的框架。我刚刚了解到 MatchError 只是它之前的 OOME 的副作用。

以上是关于scala.MatchError:某个时间点之后的所有请求都为空的主要内容,如果未能解决你的问题,请参考以下文章

线性回归 scala.MatchError:

Spark UserDefinedAggregateFunction:scala.MatchError 0.0(类 java.lang.Double)

Some(null) 到 Stringtype 可为空的 scala.matcherror

scala.MatchError:运行sbt命令时为10

Spark: scala.MatchError (of class org.apache.spark.sql.catalyst.expressions.GenericRowWithSchema

在某个点之后无法删除表格单元格