When to use Actors vs Futures?

James Cowhen picture James Cowhen · May 28, 2014 · Viewed 11.4k times · Source

I am currently working on a Play! project that has the following architecture:

Controllers -> Services (actors) -> Models (Regular case classes)

For each request that comes in, we will issue a call to the service layers like so:

Service ? DoSomething(request, context)

We have a set number of these service actors behind an akka router that are created during app initialization, and is expandable on demand.

And in the service we mostly do modest data manipulation or database calls:

receive = {
    case DoSomething(x, y) => {
           ...
           Model.doSometing(...)
           sender ! result
    }
}

I am having second thoughts on whether we should be using actors for our services or just use Futures only.

  1. We do not have any internal state that needs to be modified in the service actors, whatever message comes in goes to a function and spits out the result. Isn't this the big strength of the actor model?

  2. We are doing a lot of tasks which seem to take a lot away from the actor model

  3. We aren't doing heavy computation and remoting doesn't make sense because most of the work is for the database and roundtriping to a remote actor to make some db call is unnecessary

  4. We do use reactivemongo, so every db call is non blocking. We can make a lot of these calls

It seems to me that removing akka and just use Futures makes our life a lot easier, and we don't really lose anything.

Answer

cmbaxter picture cmbaxter · May 29, 2014

There certainly is no shortage of opinion on the topic of what should and shouldn't be an actor. Like these two posts:

http://noelwelsh.com/programming/2013/03/04/why-i-dont-like-akka-actors/

http://www.chrisstucchio.com/blog/2013/actors_vs_futures.html

I don't think you're going to find an absolute answer to this question other then that it's situational and it's really up to your preferences and your problem. What I can do for you is to offer my opinion that is based on us implementing Akka for about 2 years now.

For me, I like to think of Akka really as a platform. We come for the Actor Model but we stay for all of the other goodness that the platform provides like Clustering/Remoting, FSM, Routing, Circuit Breaker, Throttling and the like. We are trying to build an SOA like architecture with our actors acting as services. We are deploying these services across a cluster, so we are taking advantage of things like Location Transparency and Routing to provide the ability for a service consumer (which itself could be another service) to find and use a service no matter where it is deployed, and in a highly available manner. Akka makes this whole process pretty simple based on the platform tools they offer.

Within our system, we have the concept of what I call Foundation Services. These are really simple services (like basic lookup/management services for a particular entity). These services generally don't call any other services, and in some cases, just perform DB lookups. These services are pooled (router) and don't usually have any state. They are pretty similar to what you are describing some of your services to be like. We then start to build more and more complex services on top of these foundation services. Most of these services are short lived (to avoid asking), sometimes FSM based, that collect data from the foundation services and then crunch and do something as a result. Even though these foundation services are themselves pretty simple, and some would say don't require an actor, I like the flexibility in that when I compose them into a higher level service, I can look them up and they can be anywhere (location transparent) in my cluster with any number of instances available (routing) for using.

So for us, it was really a design decision to baseline around an actor as a sort of micro-like service that is available within our cluster for consumption by any other service, no matter how simple that service is. I like communicating with these services, where ever they are, through a coarse grained interface in an async manner. A lot of those principles are aspects of building out a good SOA. If that's your goal, then I think Akka can be very helpful in achieving that goal. If you are not looking to do something like that, then maybe your are right in questioning your decision to use Akka for your services. Like I said earlier, it's really up to you to figure out what you are trying to do from an architecture perspective and then design your services layer to meet those goals.