akka in traditional systems (with blocking IO)

1,051 views
Skip to first unread message

Jason Mason

unread,
Apr 27, 2012, 12:08:31 AM4/27/12
to Akka User List
Hi

New to akka and actor systems in general. I see this in the best
practices section:

"The blocking operations should be done in some special-cased thread
which sends messages to the actors which shall act on them."

I'm sure this is a very common scenario for most users (and for many
of the use cases listed in the documentation), inevitably doing disk
IO (db) or network IO (web/queues/legacy RPC). It would be great if
the documentation had some more in depth guidance on these common
topics.

One example I could find in the play! 2.0 samples:

https://github.com/playframework/Play20/blob/master/samples/java/websocket-chat/app/models/ChatRoom.java

see notifyAll() method, I imagine writing back to those WebSockets are
blocking calls? Doesn't appear to be in the spirit of best practices
of not blocking on external entities.

Are there any better examples of doing persistence or network IO
following the guidelines?

Thanks
Jason

ido

unread,
Apr 27, 2012, 9:34:50 AM4/27/12
to akka...@googlegroups.com


On Friday, April 27, 2012 6:08:31 AM UTC+2, Jason Mason wrote:
Hi

New to akka and actor systems in general. I see this in the best
practices section:

"The blocking operations should be done in some special-cased thread
which sends messages to the actors which shall act on them."


I simply wrap blocking IO in a Future.
This works, and I hope its correct.
The only problem I have is getting to the ExecutorService which Future needs.
This should be available from the actor system somehow (I read somewhere), but I could not find it yet.
Now I intialize my own outside of akka.

def receive = {
  case DoBlocking => {
      Future {
           val result = doblocking()
           sender ! result
      }(ExecutionContext.fromExecutorService(executorService))
  }
}


best,
ido
 

Roland Kuhn

unread,
Apr 27, 2012, 9:56:02 AM4/27/12
to akka...@googlegroups.com
Hi Ido,

On Apr 27, 2012, at 15:34 , ido wrote:

On Friday, April 27, 2012 6:08:31 AM UTC+2, Jason Mason wrote:
Hi

New to akka and actor systems in general. I see this in the best
practices section:

"The blocking operations should be done in some special-cased thread
which sends messages to the actors which shall act on them."


I simply wrap blocking IO in a Future.
This works, and I hope its correct.
The only problem I have is getting to the ExecutorService which Future needs.
This should be available from the actor system somehow (I read somewhere), but I could not find it yet.
Now I intialize my own outside of akka.

def receive = {
  case DoBlocking => {
      Future {
           val result = doblocking()

Assuming that this is some externally required blocking API, right? If you have a choice, always prefer non-blocking APIs. But even then it might well be better to do the blocking within the actor (Future and Actor are executed in the same way, so blocking is exactly equally bad in both cases), because your code will queue up blocking tasks without bound, and if the underlying resource uses synchronization then you block even more uselessly.

           sender ! result

This will not reply to the right sender, because you are closing over a mutable entity. I know that we’d all like the compiler to flag this as an error, but unfortunately this feature is just being developed and might (with luck) end up in 2.10.

      }(ExecutionContext.fromExecutorService(executorService))

This is rather wasteful, depending on what your “executorService” does. Why not simply “import context.dispatcher”? Then you can configure it as described in the docs.

Let’s make a superficially recursively paradox statement: the only general statement about solutions to the Blocking Problem is that no such statement can be made ;-)

If you must use blocking, this must always be carefully planned (how many in parallel, given the characteristics of the API, on which thread pool, what about interruption, …)

Regards,

Roland Kuhn
Typesafe – The software stack for applications that scale.
twitter: @rolandkuhn


√iktor Ҡlang

unread,
Apr 27, 2012, 9:58:28 AM4/27/12
to akka...@googlegroups.com
On Fri, Apr 27, 2012 at 3:56 PM, Roland Kuhn <goo...@rkuhn.info> wrote:
Hi Ido,

On Apr 27, 2012, at 15:34 , ido wrote:

On Friday, April 27, 2012 6:08:31 AM UTC+2, Jason Mason wrote:
Hi

New to akka and actor systems in general. I see this in the best
practices section:

"The blocking operations should be done in some special-cased thread
which sends messages to the actors which shall act on them."


I simply wrap blocking IO in a Future.
This works, and I hope its correct.
The only problem I have is getting to the ExecutorService which Future needs.
This should be available from the actor system somehow (I read somewhere), but I could not find it yet.
Now I intialize my own outside of akka.

def receive = {
  case DoBlocking => {
      Future {
           val result = doblocking()

Assuming that this is some externally required blocking API, right? If you have a choice, always prefer non-blocking APIs. But even then it might well be better to do the blocking within the actor (Future and Actor are executed in the same way, so blocking is exactly equally bad in both cases), because your code will queue up blocking tasks without bound, and if the underlying resource uses synchronization then you block even more uselessly.

           sender ! result

This will not reply to the right sender, because you are closing over a mutable entity. I know that we’d all like the compiler to flag this as an error, but unfortunately this feature is just being developed and might (with luck) end up in 2.10.

 

      }(ExecutionContext.fromExecutorService(executorService))

This is rather wasteful, depending on what your “executorService” does. Why not simply “import context.dispatcher”? Then you can configure it as described in the docs.

Or even: context.system.dispatchers.lookup("my-blocking-dispatcher")
 

Let’s make a superficially recursively paradox statement: the only general statement about solutions to the Blocking Problem is that no such statement can be made ;-)

If you must use blocking, this must always be carefully planned (how many in parallel, given the characteristics of the API, on which thread pool, what about interruption, …)

Regards,

Roland Kuhn
Typesafe – The software stack for applications that scale.
twitter: @rolandkuhn


--
You received this message because you are subscribed to the Google Groups "Akka User List" group.
To post to this group, send email to akka...@googlegroups.com.
To unsubscribe from this group, send email to akka-user+...@googlegroups.com.
For more options, visit this group at http://groups.google.com/group/akka-user?hl=en.


Cheers,



--
Viktor Klang

Akka Tech Lead
Typesafe - The software stack for applications that scale

Twitter: @viktorklang

ido

unread,
Apr 27, 2012, 2:01:19 PM4/27/12
to akka...@googlegroups.com
Thank you very much for all of your instructive comments and pointing out the mistakes
and for the link to the docs.

best,
ido

√iktor Ҡlang

unread,
Apr 27, 2012, 3:10:13 PM4/27/12
to akka...@googlegroups.com

Happy hAkking!

--
You received this message because you are subscribed to the Google Groups "Akka User List" group.
To view this discussion on the web visit https://groups.google.com/d/msg/akka-user/-/IkkVYx83HnsJ.

Jason Mason

unread,
Apr 27, 2012, 4:18:06 PM4/27/12
to akka...@googlegroups.com
Good information, thanks everyone. 

However, I would love to see some fleshed out examples with common scenarios such as persistence. I think the documentation and newcomers would greatly benefit from these :)


Reply all
Reply to author
Forward
0 new messages