0Pricing
Scala for Backend Engineering & Functional Programming · درس

تصميم أنظمة Actor

تعلّم تصميم التسلسلات الهرمية لـ actors وتنفيذها، وتعريف سلوكيات actors، وإرسال الرسائل واستقبالها

تصميم أنظمة Actor درس مجاني في Scala for Backend Engineering & Functional Programming على CoddyKit. هذا هو الدرس 2 من أصل 3. يمكنك قراءة الدرس كاملاً أدناه مجاناً — ثم تمرن عليه مباشرة في المتصفح باستخدام محرر أكواد مدمج ومدرس ذكاء اصطناعي متاح 24/7. هذا الدرس جزء من مسار التعلم في Scala for Backend Engineering & Functional Programming، وتقدمك يتزامن عبر الويب وتطبيق CoddyKit. تتضمن دورة Scala for Backend Engineering & Functional Programming 3 دروس في المجموع.

بعض أجزاء هذا الدرس لم تُترجم بعد وتظهر باللغة الإنجليزية.

Design Actor Systems: Intro

Welcome to Lesson 2! In the previous lesson, we learned the basics of the Akka Actor Model. Now, let's dive into designing Akka Actor Systems.

A well-designed actor system is robust, scalable, and easy to maintain. We'll explore how to structure your actors, define their behaviors, and enable them to communicate effectively.

Understanding Actor Hierarchies

Akka actors are organized in a tree-like hierarchy, much like a file system. Every actor, except the 'root' actor, has a parent.

  • Parent-Child Relationship: An actor that creates another actor becomes its parent.
  • Supervision: This hierarchy is crucial for Akka's fault tolerance. Parents are responsible for supervising their children (more on this in the next lesson!).
  • Path-based Addressing: Each actor has a unique path, reflecting its position in the hierarchy, like /user/parentActor/childActor.

Setting Up Your ActorSystem

The ActorSystem is the entry point for all Akka applications. It manages the resources needed for actors, including thread pools and schedulers.

You create it once per application and then use it to create your top-level actors. It's like the container for your entire actor application.

Try running this simple code to create an ActorSystem:

import akka.actor.ActorSystem

object AkkaSystemApp {
  def main(args: Array[String]): Unit = {
    // Create an ActorSystem with a unique name
    val system = ActorSystem("MyFirstActorSystem")
    println("ActorSystem created: " + system.name)

    // Remember to terminate the system when done!
    system.terminate()
  }
}

Defining Actor Behavior

An actor's behavior determines how it reacts to different messages. In Scala, you define this by extending the Actor trait and implementing the receive method.

  • The receive method is a partial function that matches incoming messages to specific actions.
  • Each actor processes messages one by one, sequentially, ensuring thread safety for its internal state.

ActorRef: The Actor's Address

You don't directly interact with actor instances. Instead, you send messages to an ActorRef. Think of ActorRef as a postal address for an actor.

  • It's a handle that represents a specific actor within the system.
  • Messages sent to an ActorRef are placed in the actor's mailbox.
  • You obtain an ActorRef when you create an actor using actorOf.

Sending Messages to Actors

The primary way actors communicate is by sending messages. The most common way to send a message is using the ! (pronounced 'tell') method.

receiverActorRef ! "Your message here"

The tell method is asynchronous and fire-and-forget. It sends the message and doesn't wait for a reply.

Let's combine creating an actor and sending it messages:

import akka.actor.{Actor, ActorRef, Props, ActorSystem}

// 1. Define the actor's behavior
class GreeterActor extends Actor {
  def receive = {
    case "hello" => println(s"Greeter: Hello from ${self.path.name}!")
    case msg: String => println(s"Greeter: Received message: '$msg'")
    case _ => println("Greeter: Received something unexpected!")
  }
}

object SimpleActorApp {
  def main(args: Array[String]): Unit = {
    // 2. Create the ActorSystem
    val system = ActorSystem("GreeterSystem")

    // 3. Create a top-level actor and get its ActorRef
    val greeter: ActorRef = system.actorOf(Props[GreeterActor], "myGreeter")
    
    // 4. Send messages to the actor using '!'
    greeter ! "hello"
    greeter ! "How are you doing today?"
    greeter ! 123 // This will match the _ case

    // Give actors time to process messages, then terminate
    Thread.sleep(1000)
    system.terminate()
  }
}

Creating Child Actors

Actors can create other actors, forming the hierarchy we discussed. A parent actor creates its child actors using context.actorOf.

  • context.actorOf: Used by an actor to create its children.
  • system.actorOf: Used by the application to create top-level (guardian) actors.

Creating child actors helps in organizing your system, delegating tasks, and isolating failures.

Parent-Child Communication

Actors communicate by sending messages to each other's ActorRef. A child actor can get its parent's ActorRef via context.parent. To reply to the sender of a message, an actor can use sender().

Let's see an example where a parent creates a child, tells it to do work, and the child reports back when done:

import akka.actor.{Actor, ActorRef, Props, ActorSystem}
import scala.concurrent.ExecutionContext.Implicits.global

// Child Actor Definition: Does work and replies to sender
class ChildActor extends Actor {
  def receive = {
    case "work" =>
      println(s"ChildActor (${self.path.name}): Doing work from ${sender().path.name}")
      sender() ! "done" // Reply 'done' to the sender (parent)
  }
}

// Parent Actor Definition: Creates child, sends work, receives reply
class ParentActor extends Actor {
  // Create a child actor when the parent starts
  val child: ActorRef = context.actorOf(Props[ChildActor], "myChild")

  def receive = {
    case "start" =>
      println("ParentActor: Kicking off child's work.")
      child ! "work" // Tell the child to do 'work'
    case "done" =>
      println(s"ParentActor: Child ${sender().path.name} reported 'done'.")
      context.stop(child) // Stop the child actor
      context.stop(self)   // Stop the parent actor
  }
}

object HierarchyApp {
  def main(args: Array[String]): Unit = {
    val system = ActorSystem("HierarchySystem")
    val parent: ActorRef = system.actorOf(Props[ParentActor], "parentActor")
    parent ! "start" // Start the interaction

    // Wait for the system to terminate (actors will stop themselves)
    system.whenTerminated.onComplete(_ => println("ActorSystem terminated."))
  }
}

Stopping Actors Gracefully

Actors should be stopped gracefully when they are no longer needed to release resources. You can stop an actor in a few ways:

  • context.stop(self): An actor stops itself.
  • context.stop(childRef): A parent stops one of its children.
  • system.stop(actorRef): For top-level actors, though usually, you stop the entire system.

When an actor stops, it processes all messages in its mailbox before terminating. Its children are also stopped recursively.

Quick Check: Actor Design

Consider the following Akka actor code snippet. What is the correct way for MyChildActor to send a message back to its creating parent, MyParentActor, if MyParentActor was the sender of the initial 'request' message?

Recap: Designing Actor Systems

Great job! In this lesson, we've covered key aspects of designing Akka Actor Systems:

  • Actors are organized in hierarchies, which are vital for supervision and structure.
  • The ActorSystem is your application's entry point for Akka.
  • You define actor behavior using the receive method.
  • ActorRef is the address for sending messages.
  • Actors communicate asynchronously using the ! (tell) method.
  • Parents create children with context.actorOf, and children can reply using sender().
  • Actors can be stopped gracefully using context.stop().

Next, we'll delve deeper into Akka's powerful supervision strategies and how to handle failures gracefully!

الأسئلة الشائعة

هل درس «تصميم أنظمة Actor» مجاني؟

نعم — نص درس «تصميم أنظمة Actor» كامل متاح مجاناً هنا على الويب. لتمرينه بشكل تفاعلي (محرر أكواد مدمج ومدرس ذكاء اصطناعي متاح 24/7) وفتح باقي دورة Scala for Backend Engineering & Functional Programming، انتقل إلى CoddyKit PRO. تتضمن دورة Scala for Backend Engineering & Functional Programming 3 دروس في المجموع.

ماذا ستتعلم في «تصميم أنظمة Actor»؟

تعلّم تصميم التسلسلات الهرمية لـ actors وتنفيذها، وتعريف سلوكيات actors، وإرسال الرسائل واستقبالها تتمرن على Scala for Backend Engineering & Functional Programming مع أكواد عملية تشغلها مباشرة في المتصفح، ومدرس ذكاء اصطناعي متاح 24/7 يجيب على أسئلتك أثناء عملك.

هل أحتاج إلى خبرة سابقة لأبدأ Scala for Backend Engineering & Functional Programming؟

لا تُشترط خبرة سابقة. Scala for Backend Engineering & Functional Programming على CoddyKit منظم للمبتدئين حتى المتقدمين، لذا يمكنك البدء من هنا أو من البداية والتقدم بسرعتك الخاصة. هذا هو الدرس 2 من أصل 3.

كم من الوقت يستغرق درس «تصميم أنظمة Actor»؟

معظم دروس CoddyKit تستغرق حوالي 5–10 دقائق. كل منها موجز وتفاعلي، لذا تحرز تقدماً مستمراً وتستأنف من حيث توقفت عبر الويب والتطبيق.

هل يمكنني كتابة وتشغيل أكواد في درس Scala for Backend Engineering & Functional Programming هذا؟

نعم. كل درس في Scala for Backend Engineering & Functional Programming يتضمن محرر أكواد مدمج، لذا تكتب وتشغل أكواداً حقيقية مباشرة في متصفحك وتحصل على تعليقات فورية من الذكاء الاصطناعي — بدون إعداد محلي.

جميع الدروس في هذه الدورة

  1. أساسيات نموذج Akka Actor
  2. تصميم أنظمة Actor
  3. الإشراف وتحمل الأعطال
← العودة إلى Scala for Backend Engineering & Functional Programming