scala, spray, akka - java.lang.OutOfMemoryError: unable to create new native thread

scala, spray, akka - java.lang.OutOfMemoryError: unable to create new native thread

在检查 spray 的吞吐量时 api。

场景:25个并发用户

Os:免费 BSD

内存:2GB

核心数:2

在大约 13 个并发用户时,我收到以下错误。

[ERROR] [06/29/2015 05:01:56.407] [default-akka.actor.default-dispatcher-2]     [ActorSystem(default)] Uncaught error from thread [default-akka.actor.default-dispatcher-2] shutting down JVM since 'akka.jvm-exit-on-fatal-error' is enabled
java.lang.OutOfMemoryError: unable to create new native thread
    at java.lang.Thread.start0(Native Method)
    at java.lang.Thread.start(Thread.java:714)
    at scala.concurrent.forkjoin.ForkJoinPool.tryAddWorker(ForkJoinPool.java:1672)
    at scala.concurrent.forkjoin.ForkJoinPool.deregisterWorker(ForkJoinPool.java:1795)
    at scala.concurrent.forkjoin.ForkJoinWorkerThread.run(ForkJoinWorkerThread.java:117)

Akka 和 Spray Conf 的默认更改:

akka{
    tcp{
        register-timeout = 20s
    }
}

spray.can {
    request-timeout = 30 s
    bind-timeout = 30s
    unbind-timeout = 5s
    registration-timeout = 30s
}

http.spray.can {
    server{
        pipelining-limit = 50
    }
}

导致 OutOfMemmoryError 的原因。异常是从 router actor

抛出的

不能读心术,但可能你在 actors 内部进行了阻塞(Await.result 或类似)。 ForkJoinPool 自动为每个阻塞的线程创建一个新线程。因此,如果您有一个长时间的块 count_of_threads == count_of_requests(+ 每个线程都保存引用 iside 调用堆栈),最终会导致 OutOfMemory.

看,Blocking Needs Careful Management

P.S。 您可能会发现为什么 Await.result(在内部使用 scala.concurrent.blocking)导致无法管理地在 ForkJoinPool 中创建线程(即使不考虑 maxParallelism)。


或者您创建了很多 ActorSystems,same page of akka documentation 状态:

An ActorSystem is a heavyweight structure that will allocate 1…N Threads, so create one per logical application.