我的应用程序使用Play框架来处理REST请求.我需要在http请求处理程序中执行一些可能持久的阻塞I / O操作.并行地,我想要有效地处理一些短暂的持久性请求.
如下所述:
http://www.playframework.com/documentation/2.2.0/JavaAsync
持久的操作可以异步运行.另一方面,如下所述:
http://www.playframework.com/documentation/2.2.x/ThreadPools
Play框架使用相同的默认线程池,其中执行所有应用程序代码.至少在Java api中,不可能在不同的线程池上运行异步工作.
所以,我的问题是,如果值得运行潜在的阻塞I / O操作异步,考虑到这样一个操作使用相同的线程池的事实.或者也许最好增加默认线程池大小,在这种情况下不要打扰async api? (这样至少代码可读性会高得多)
解决方法
我建议您设置自己的上下文,并使用Plays F.Promise& A>运行您的阻止/ cpu密集型操作.与线程一样,最优解决方案取决于许多内核等等.
首先在applications.conf中设置你的上下文:
play { akka { akka.loggers = ["akka.event.Logging$DefaultLogger","akka.event.slf4j.Slf4jLogger"] loglevel = WARNING actor { default-dispatcher = { fork-join-executor { parallelism-min = 1 parallelism-factor = 2 parallelism-max = 6 } } my-context { fork-join-executor { parallelism-min = 1 parallelism-factor = 4 parallelism-max = 16 } } } } }
然后在控制器中,使用Plays Promises(我使用Java 8)使用你的上下文:
public static F.Promise<Result> love() { ExecutionContext myExecutionContext = Akka.system().dispatchers().lookup("play.akka.actor.my-context"); F.Promise<Integer> integerPromise = F.Promise.promise(() -> LongRunningProcess.run(10000L),myExecutionContext); F.Promise<Integer> integerPromise2 = F.Promise.promise(() -> LongRunningProcess.run(10000L),myExecutionContext); return integerPromise.flatMap(i -> integerPromise2.map(x -> ok())); }
这样,您的Play应用程序仍将处理默认调度程序执行上下文中的短暂持久请求,并且阻止/ cpu密集型将在我的上下文中运行.
我为您演示了一个很简单的例子,请查看github.