Akka - How many instances of an actor should you c

2020-05-13 20:43发布

问题:

I'm new to the Akka framework and I'm building an HTTP server application on top of Netty + Akka.

My idea so far is to create an actor for each type of request. E.g. I would have an actor for a POST to /my-resource and another actor for a GET to /my-resource.

Where I'm confused is how I should go about actor creation? Should I:

  1. Create a new actor for every request (by this I mean for every request should I do a TypedActor.newInstance() of the appropriate actor)? How expensive is it to create a new actor?

  2. Create one instance of each actor on server start up and use that actor instance for every request? I've read that an actor can only process one message at a time, so couldn't this be a bottle neck?

  3. Do something else?

Thanks for any feedback.

回答1:

Well, you create an Actor for each instance of mutable state that you want to manage.

In your case, that might be just one actor if my-resource is a single object and you want to treat each request serially - that easily ensures that you only return consistent states between modifications.

If (more likely) you manage multiple resources, one actor per resource instance is usually ideal unless you run into many thousands of resources. While you can also run per-request actors, you'll end up with a strange design if you don't think about the state those requests are accessing - e.g. if you just create one Actor per POST request, you'll find yourself worrying how to keep them from concurrently modifying the same resource, which is a clear indication that you've defined your actors wrongly.

I usually have fairly trivial request/reply actors whose main purpose it is to abstract the communication with external systems. Their communication with the "instance" actors is then normally limited to one request/response pair to perform the actual action.



回答2:

If you are using Akka, you can create an actor per request. Akka is extremely slim on resources and you can create literarily millions of actors on an pretty ordinary JVM heap. Also, they will only consume cpu/stack/threads when they actually do something.

A year ago I made a comparison between the resource consumption of the thread-based and event-based standard actors. And Akka is even better than the event-base.

One of the big points of Akka in my opinion is that it allows you to design your system as "one actor per usage" where earlier actor systems often forced you to do "use only actors for shared services" due to resource overhead.

I would recommend that you go for option 1.



回答3:

Options 1) or 2) have both their drawbacks. So then, let's use options 3) Routing (Akka 2.0+)

Router is an element which act as a load balancer, routing the requests to other Actors which will perform the task needed.

Akka providers different Router implementations with different logic to route a message (for example SmallestMailboxPool or RoundRobinPool).

Every Router may have several children and its task is to supervise their Mailbox to further decide where to route the received message.

//This will create 5 instances of the actor ExampleActor
//managed and supervised by a RoundRobinRouter
ActorRef roundRobinRouter = getContext().actorOf(
Props.create(ExampleActor.class).withRouter(new RoundRobinRouter(5)),"router");

This procedure is well explained in this blog.



回答4:

  1. It's quite a reasonable option, but whether it's suitable depends on specifics of your request handling.

  2. Yes, of course it could.

  3. For many cases the best thing to do would be to just have one actor responding to every request (or perhaps one actor per type of request), but the only thing this actor does is to forward the task to another actor (or spawn a Future) which will actually do the job.



回答5:

For scaling up the serial requests handling, add a master actor (Supervisor) which in turn will delegate to the worker actors (Children) (round-robin fashion).



标签: scala akka