Are there major scaling limits with play framework and jdbc blocking io calls

左心房为你撑大大i 提交于 2019-12-04 10:43:36

Play can absolutely handle this load.

The documentation states that blocking code should be avoided inside controller methods - the default configuration is tuned for them to have asynchronous execution. If you stick some blocking calls in there, your controller will now be waiting for that call to finish before it can process another incoming request - this is bad.

You can’t magically turn synchronous IO into asynchronous by wrapping it in a Promise. If you can’t change the application’s architecture to avoid blocking operations, at some point that operation will have to be executed, and that thread is going to block. So in addition to enclosing the operation in a Promise, it’s necessary to configure it to run in a separate execution context that has been configured with enough threads to deal with the expected concurrency. See Understanding Play thread pools for more information. https://www.playframework.com/documentation/2.4.x/JavaAsync#Make-controllers-asynchronous

I believe you are aware of this but I wanted to point out the bolded section. Your database has a limited number of threads that are available for applications to make calls on - it may be helpful to track this number down, create a new execution context that is turned for these threads, and assign that new execution context to a promise that wraps your database call.

Check out this post about application turning for Play, it should give you an idea of what this looks like. I believe he is using Akka Actors, something that might be out of scope for you, but the idea for thread tuning is the same:

Play 2 is optimized out-of-the-box for HTTP requests which don’t contain blocking calls (i.e. asynchronous). Most database-driven apps in Java use synchronous calls via JDBC so Play 2 needs a bit of extra configuration to tune Akka for these types of requests. http://www.jamesward.com/2012/06/25/optimizing-play-2-for-database-driven-apps

If you try to execute a massive number of requests on the database without turning the threads, you run the risk of starving the rest of your application of threads, which will halt your application. For the load you are expecting, the default tuning might be ok, but it is worth performing some additional investigating.

Getting started with thread tuning: https://www.playframework.com/documentation/2.4.x/ThreadPools

You should update your controller to return Promise and there is also no reason to make it static anymore with Play 2.4. https://www.playframework.com/documentation/2.4.x/Migration24#Routing


Define an execution context in the application.conf with name "jdbc-execution-context"

//reference to context
ExecutionContext jdbcExecutionContext = Akka.system().dispatchers()
     .lookup("jdbc-execution-context");

return promise(() -> {
    //db call
}, jdbcExecutionContext)
.map(callResult -> ok(callResult));
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!