Play Framework (8) – blocking & non-blocking & thread pool

Blocking:

Some cases when our code may block includes:

  • None of major databases provide asynchronous database drivers for the JVM, except MongoDB.
  • Using REST/WebService APIs through a 3rd party client library (i.e., not using Play asynchronous WS API)
  • Some messaging technologies only provide synchronous APIs to send messages.
  • When we open files or sockets directly ourself
  • CPU intensive operations that block by virtue of the fact that they take a long time to execute.

In general, if the API you are using returns futures, it is not non blocking, otherwise it is blocking.
(Note that you may be tempted to therefore wrap your blocking code in Futures. This does not make it non blocking, it just means the blocking will happen in a different thread. You still need to make sure that the thread pool that you are using there has enough threads to handle the blocking. )

Non Blocking:

The following types of IO do not block:

  • The Play WS API
  • Asynchronous database drivers such as ReativeMongo
  • Sending/receiving messages to/from Akka actors

Thread Pool:

  • Play Default Thread Pool:
    • This is the default thread pool in which all application code in Play Framework is executed. It is an Akka dispatcher, and can be configured by configuring Akka. By default, it has one thread per processor.
    • All actions in Play Framework use the default thread pool. When doing certain asynchronous operations, for example calling map or flatMap on a future, you may need to provide an implicit execution context to execute the given functions in. An execution context is basically another name for a thread pool.
    • The default thread pool can be configured using standard Akka configuration in application.conf under the play namespace. This execution context is accessible through play.api.libs.concurrent.Execution.Implicits._
    • Configuration:
      akka {
        actor {
          default-dispatcher {
            fork-join-executor {
              parallelism-factor = 1.0
              parallelism-max = 24
              task-peeking-mode =LIFO
            }
          }
        }
      }
  • Using other thread pools:
    • In certain circumstances, we may wish to dispatch work to other thread pools, including CPU heavy work, or IO work, such as database access. In this case, we should create our own ThreadPool.
      • create a ThreadPool
        val dbExecutionContext: ExecutionContext = akkaSystem.dispatchers.lookup("db-context")
      • configure this pool
        db-context {
          fork-join-executor {
            parallelism-factor = 20.0
            parallelism-max = 200
          }
        }
      • use it
        Future {
          ...
        }(dbExecutionContext)
Advertisements

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s