在scala的世界, 我們常會用Future來處理某些非同步的工作,
用Future, 必需要透過implict的方式提供execution context, 來執行這些工作.
白話的說就是要指定你的code要在哪個thread pool跑.
使用Playframework, 在比較單純的情況下直接用預設的thread pool就可以了.
然後再透過application.conf設定適當的參數.
import play.api.libs.concurrent.Execution.Implicits._
def someAsyncAction = Action.async {
import play.api.Play.current
WS.url("http://www.playframework.com").get().map { response =>
// This code block is executed in the imported default execution context
// which happens to be the same thread pool in which the outer block of
// code in this action will be executed.
Results.Ok("The response code was " + response.status)
}
}
play {
akka {
akka.loggers = ["akka.event.Logging$DefaultLogger", "akka.event.slf4j.Slf4jLogger"]
loglevel = WARNING
actor {
default-dispatcher = {
fork-join-executor {
parallelism-factor = 1.0
parallelism-max = 24
}
}
}
}
}
import play.api.libs.concurrent.Execution.Implicits._
先來找找我們用的execution context在哪裡,
defaultContext是ActorSystem的dispatcher
而create ActorSystem用的設定是"play"這個關鍵字下面的所有屬性.
接下來就是看ActorSystem如何設定dispatcher囉~
defaultGlobalDispatcher是用DefaultDispatcherId(即akka.actor.default-dispatcher)抓到設定值
大概是這樣囉!
針對不同類型的工作, 有時候我們會不希望所有事情都塞在預設的thread pool做,
要使用其他的thread pool, 只需要先在application.conf加上一組新的設定.
再用lookup讓Akka能找到它就好.
可以直接在產生Future的時候指定execution context或是直接import讓implicit發生作用
my-context {
fork-join-executor {
parallelism-factor = 20.0
parallelism-max = 200
}
}
object Contexts {
implicit val myExecutionContext: ExecutionContext = Akka.system.dispatchers.lookup("my-context")
}
Future {
// Some blocking or expensive code here
}(Contexts.myExecutionContext)
or
import Contexts.myExecutionContext
Future {
// Some blocking or expensive code here
}
當然實際上要如何設定thread pool還是要參考測試結果啦!
ref:
-
playframework source code (2.3.x)
-
akka source code (2.3)
-
understanding play thread pools (2.3.5)
No comments:
Post a Comment