Reputation: 1680
How does the actor model (in Akka) work when you need to perform I/O (ie. a database operation)?
It is my understanding that a blocking operation will throw an exception (and essentially ruin all concurrency due to the evented nature of Netty, which Akka uses). Hence I would have to use a Future
or something similar - however I don't understand the concurrency model.
future
(ie. future.get()
) does that block only the current actor's execution; or will it prevent execution on all actors until the blocking call has completed?The basic context is this:
Is there a better way to achieve this?
Upvotes: 28
Views: 7882
Reputation: 6481
What Raymond and paradigmatic said, but also, if you want to avoid starving the thread pool, you should wrap any blocking operations in scala.concurrent.blocking
.
It's of course best to avoid blocking operations, but sometimes you need to use a library that blocks. If you wrap said code in blocking
, it will let the execution context know you may be blocking this thread so it can allocate another one if needed.
The problem is worse than paradigmatic describes since if you have several blocking operations you may end up blocking all threads in the thread pool and have no free threads. You could end up with deadlock if all your threads are blocked on something that won't happen until another actor/future gets scheduled.
Here's an example:
import scala.concurrent.blocking ... Future { val image = blocking { load_image_from_potentially_slow_media() } val enhanced = image.enhance() blocking { if (oracle.queryBetter(image, enhanced)) { write_new_image(enhanced) } } enhanced }
Documentation is here.
Upvotes: 1
Reputation: 40461
Blocking operations will generally not throw exceptions, but waiting on a future (for example by using !!
or !!!
send methods) can throw a time out exception. That's why you should stick with fire-and-forget as much as possible, use a meaningful time-out value and prefer callbacks when possible.
An akka actor cannot explicitly process several messages in a row, but you can play with the throughput
value via the config file. The actor will then process several message (i.e. its receive method will be called several times sequentially) if its message queue it's not empty: http://akka.io/docs/akka/1.1.3/scala/dispatchers.html#id5
Blocking operations inside an actor will not "block" all actors, but if you share threads among actors (recommended usage), one of the threads of the dispatcher will be blocked until operations resume. So try composing futures as much as possible and beware of the time-out value).
3 and 4. I agree with Raymond answers.
Upvotes: 10
Reputation: 4890
Blocking operations do not throw exceptions in Akka. You can do blocking calls from an Actor (which you probably want to minimize, but thats another story).
As for netty (and I assume you mean Remote Actors, because this is the only thing that netty is used for in Akka), pass of your work as soon as possible to a local actor or a future (with callback) if you are worried about timing or preventing netty to do it's job in some way.
Upvotes: 28