Akka (2) – Actor: life cycle & create an actor & send message & stop actors & kill an actor

Akka is a messaging system based on actor module(message should be immutable, this is to avoid the shared mutable state trap). So this post, we focus on talking about Actor, including its life cycle, how to send messages between actors, how to stop actors and how to kill an actor.

  • Basic Concepts of actor
    • Akka’s unit of code organization is called actor.
    • actors can help you crate concurrent scalable and fault-tolerance applications.
    • actor is model of organizing your code that keeps many “policy decisions” separate from the business logic.
    • Each actor manages their own memory and behavior, communicates with asynchronous non-blocking messages.
    • actor can receive and send message, define behavior of next message, create anther actor.
    • It is hot deploy, which changes behavior at runtime.
    • Actors are implemented by extending the Actor base trait and implementing the receive method.
  • Actor Life Cycle
    Here we use a graph to show what’s actor lifecycle.
    Screenshot 2016-04-20 17.00.30
  • Create an actor
    • Actors are created by passing a Props instance into the actorOf factory method which is available on ActorSystem and AcotrContext.
      Props is a configuration class to specify options for the creation of actors, think it as an immutable and thus freely shareable recipe of creating an actor including associated deployment information.
  • Send messages
    There are three ways to send messages between actors.

    • tell |
      It means “fire-and-forget”, e.g. send a message asynchronously and return immediately. No blocking waiting fro a message. This gives the best concurrency and scalability characteristics.
    • ask | ?
      It sends a message asynchronously and returns a Future representing a possible reply.  Using ask will send a message to the receiving actor as with tell, and the receiving actor must reply with sender() ! reply in order to complete the returned Future with a value. The ask operation involves creating an internal actor for handling this reply, which needs to have a timeout after which it is destroyed in order not to leak resources.
      Receive timeout:

      • the ActorContext setReceiveTimeout defines the inactivity timeout after which the sending of a ReceiveTimeout message is triggered.
      • Message marked with NotInfluenceReceiveTimeout will not rest the timer. This can be useful when ReceiveTimeout should be fired by external inactivity but not influenced by internal activity, e.g. scheduled tick messages.
    • forward
      You can forward a message from one actor to another; this can be useful when writing actors that work as routers, load-balancers, replicators, etc.
  • Stopping actors:
    • stop
      • The context is used for stopping the actor itself or child actors and the system for stopping top level actors.
        context.stop(self)
        content.stop(childActor)
        actorSystem.stop(anActor)

        The actual termination of actor is performed asynchronously, i.e. stop may return before the actor is stopped. The termination of an actor proceeds in three steps:

        • first the actor suspends its mailbox processing and sends a stop command to all its children
        • then it keeps processing the internal termination notifications from its children until the last one is gone
        • finally terminating itself (involving postStop, dumping Terminated on the DeathWatch, telling its supervisor)
      • If one of the actors does not respond (i.e. processing a message for extended periods of time and therefore not receiving the stop command), this whole process will be stuck.
      • Upon ActorSystem.terminate, the system guardian actors will be stopped, and the aforementioned process will ensure proper termination of the whole system.
      • The postStop hook is invoked after an actor is fully stopped. This enables cleaning up resources.
    • PoisonPill
      You can send an actor the akka.actor.PoisonPill message, which will stop the actor when the message is proceed. PoisonPill is enqueued as ordinary messages and will be handled after messages that were already queued in the mailbox.

      actor ! PoisonPill
    • gracefulStop
      It is useful if you need to wait for termination or compose ordered termination of several actors. When gracefulStop() returns successfully, the actors’ postStop() hook will have been executed: there exists an happens-before edge between the end of postStop() and the return of gracefulStop().

      import akka.pattern.gracefulStop
      
      object GracefulStopTest extends App {
        val system = ActorSystem("GracefulStopTest")
        val testActor = system.actorOf(Prof[TestActor], name="TestActor")
        try {
          val stopped: Future[Boolean] = gracefulStop(testActor, 2 seconds)(sytem)
          Await.result(stopped, 3 seconds)
          println("testActor was stopped")
        } catch {
          case e:Exception => e.printStackTrace 
        } finally {
          system.shutdown
        }
      }
  • Killing an actor:
    You can kill an actor by sending a Kill message. This will cause the actor to throw a ActorKilledException, trigger a failure. The actor will suspend operation and its supervisor will asked how to handle the failure, which may mean resuming the actor, restarting it or terminating it completely.

    actor ! Kill

Leave a comment