2016-03-06 62 views
2

我在我的freebsd 1CPU/2GB服务器上使用spray.io和akka.io,我面临 线程问题。当我因为“无法创建本地线程”而导致OutOfMemory异常 时,我开始注意到它。Scala服务器与喷雾Akka过度

我通常检查Thread.activeCount(),我发现它变得非常大。 目前我使用这些设置:

myapp-namespace-akka { 
    akka { 
    loggers = ["akka.event.Logging$DefaultLogger"] 
    loglevel = "DEBUG" 
    stdout-loglevel = "DEBUG" 

    actor { 
     deployment { 
     default { 
      dispatcher = "nio-dispatcher" 
      router = "round-robin" 
      nr-of-instances = 1 
     } 
     } 

     debug { 
     receive = on 
     autoreceive = on 
     lifecycle = on 
     } 

     nio-dispatcher { 
     type = "Dispatcher" 
     executor = "fork-join-executor" 

     fork-join-executor { 
      parallelism-min = 8 
      parallelism-factor = 1.0 
      parallelism-max = 16 
      task-peeking-mode = "FIFO" 
     } 

     shutdown-timeout = 4s 
     throughput = 4 
     throughput-deadline-time = 0ms 
     attempt-teamwork = off 
     mailbox-requirement = "" 
     } 

     aside-dispatcher { 
     type = "Dispatcher" 
     executor = "fork-join-executor" 

     fork-join-executor { 
      parallelism-min = 8 
      parallelism-factor = 1.0 
      parallelism-max = 32 
      task-peeking-mode = "FIFO" 
     } 

     shutdown-timeout = 4s 
     throughput = 4 
     throughput-deadline-time = 0ms 
     attempt-teamwork = on 
     mailbox-requirement = "" 
     } 
    } 
    } 
} 

我想nio-dispatcher是我的默认非阻塞(可以说单线程) 调度。我在aside-dispatcher上执行我所有的期货(数据库,网络查询)。

我经历了我的申请得到我的环境如下:

trait Contexts { 
    def system: ActorSystem 
    def nio: ExecutionContext 
    def aside: ExecutionContext 
} 

object Contexts { 
    val Scope = "myapp-namespace-akka" 
} 

class ContextsImpl(settings: Config) extends Contexts { 
    val System = "myapp-namespace-akka" 
    val NioDispatcher = "akka.actor.nio-dispatcher" 
    val AsideDispatcher = "akka.actor.aside-dispatcher" 
    val Settings = settings.getConfig(Contexts.Scope) 

    override val system: ActorSystem = ActorSystem(System, Settings) 
    override val nio: ExecutionContext = system.dispatchers.lookup(NioDispatcher) 
    override val aside: ExecutionContext = system.dispatchers.lookup(AsideDispatcher) 
} 

// Spray trait mixed to service actors 
trait ImplicitAsideContext { 
    this: EnvActor => 
    implicit val aside = env.contexts.aside 
} 

我认为我没有乱用CONFIGS或实现。在这里帮助我。 通常我在我的应用程序中看到数千个线程,直到它崩溃(我设置了 freebsd预处理限制为5000)。

回答

3

如果您的应用程序确实启动了如此多的线程,通常可以追踪到阻塞ForkJoinPools内部的行为(坏事要做!),我在这里回答了详细的问题:blocking blocks,因此您可能想要在那里阅读并验证应用程序中创建了哪些线程,以及为什么--ForkJoinPool没有静态上限。

+0

但为什么ForkJoinPool在默认情况下(例如在PlayFramework中),如果我有主I/O阻塞逻辑,那么ThreadPool有什么优势? – selfsx

+0

这是所有操作的_default_池,应该是被动的 - 例如所有演员,除非你为他们指定了不同的调度员。阻止应该被管理,而不仅仅是手中的空白白旗说一切都阻止:-) –