2016-03-06 83 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_池,應該是被動的 - 例如所有演員,除非你爲他們指定了不同的調度員。阻止應該被管理,而不僅僅是手中的空白白旗說一切都阻止:-) –