Open source Java projects: Akka

Building distributed systems for concurrent and scalable Java applications

1 2 3 4 5 6 Page 2
Page 2 of 6

The Akka toolkit implements the following actor model components:

  • ActorSystem is the glue that wires Actors, ActorRefs, MessageDispatchers, and Mailboxes together. Programmers use the ActorSystem to configure the desired implementation of each of these components.
  • ActorRef is an addressable location. Messages destined for an underlying Actor are sent to an ActorRef.
  • MessageDispatcher is the engine that runs the other parts of the ActorSystem and schedules all its activities. The MessageDispatcher's main responsibility is to run Mailboxes. When an ActorRef receives a message, it dispatches it to the MessageDispatcher, which puts that message in the message queue for the destination Mailbox.
  • Mailbox is the component that holds Actors. Every Actor has its own mailbox. When the mailbox receives a slice of time to run, it takes a message from the message queue and invokes the Actor with the message.
  • MessageQueue is the first recipient of new messages. When the MessageDispatcher receives a message from the ActorRef, it delivers that message to the mailbox's Message Queue, where it sits until the mailbox receives CPU cycles to run.
  • Actor is an object that provides a receive method, which is invoked by the mailbox when it has a message to process.

To summarize: When you want to invoke the functionality of an actor in Akka, you send a message to the ActorRef. The ActorRef dispatches it to a MessageDispatcher, which delivers it to a Mailbox's MessageQueue. When the Mailbox receives a thread time slice from the MessageDispatcher, it retrieves the message from the MessageQueue and then invokes the Actor's receive method, passing it the message.

Load balancing and horizontal scalability

Akka's message-passing process might sound convoluted but it affords Akka two especially powerful benefits:

  1. Load balancing: The MessageDispatcher can be configured with a one-to-one mapping of threads to actors, but it doesn't have to be. This means that the MessageDispatcher can maintain a thread pool that is configured to a sustainable quantity for the hardware on which it is running; but it can have far more actors than it does threads. Your application is still limited by the number of threads running actors, but unless all actors are always busy and using all of their CPU time-slices, this level of abstraction allows Akka to take advantage of actor downtime and support more load than a standard threading model could do.
  2. Horizontal scalability: While vertical scalability refers to building out bigger and bigger machines that can individually do more work, horizontal scalability refers to running multiple machines together to complete the work. Akka can easily support horizontal scalability because your application never directly interacts with Actors, but instead interacts with ActorRefs. The two variations of an ActorRef are local and remote. Local ActorRefs deliver messages to a MessageDispatcher running in the same JVM. Remote ActorRefs send messages to a MessageDispatcher running on a different machine. This proxy/stub model is key to distributed computing; Akka exploits it to gain horizontal scalability without requiring your application to change beyond its Akka configuration.

Actor hierarchies and the ActorPath

All of this leads to another important concept in the Actor model, and in Akka specifically: Actor hierarchies. All Actors belong to an actor hierarchy in the ActorSystem. Actors that can be directly created are called Top Level Actors. The ActorSystem defines two separate hierarchies: a system hierarchy to manage internal tasks and a user hierarchy to define Actors for your application. The ActorSystem defines a user-level root actor, named Guardian, under which all top-level actors are created. Top-level Actors are then free to create their own child Actors (which can then create their own child Actors, and so forth). Together, the Guardian, Actors, and their children comprise the user hierarchy.

The final concept that you need to understand in order to effectively use Akka is that all Actors are named, and there is an addressing scheme for locating Actors, called the ActorPath. Here's an example of an ActorPath:

akka://MySystem@MyServer:MyPort/user/MyTopLevelActor/MyChild

Its components are as follows:

  • akka is the name of the scheme, so it will always be "akka".
  • MySystem is the name of the ActorSystem that owns the Actor being addressed.
  • MyServer:MyPort is the server and port for the server hosting the Actor (e.g.,192.168.1.1:1234).
  • user is the name of the guardian, which is always "user" for non-system Actors
  • MyTopLevelActor is the name given to a top-level actor when you create an ActorSystem.
  • MyChild is the name of a child actor. You'll use this name if you're trying to access an actor that is a child of a specified top-level Actor. You can continue down the hierarchy until you reach the actor you're looking for.

Setting up Akka

Akka can run embedded inside your application or as a standalone server or set of servers. The beauty of Akka is that the code looks the same either way. For the purposes of this article we'll build Actors and ActorSystems inside of an application.

To build and run Akka applications using Maven, you only need to include the following dependency in your POM file (note that the latest artifact as of this writing was version 2.1.2):

<dependency>
            <groupId>com.typesafe.akka</groupId>
            <artifactId>akka-actor_2.10</artifactId>
            <version>2.1.2</version>
        </dependency>

If you are not using Maven, you'll need to download Akka from the Typesafe homepage and add

lib/akka/akka-actor_2.10-2.1.2.jar

to your CLASSPATH.

1 2 3 4 5 6 Page 2
Page 2 of 6