Scala for Backend Engineering & Functional Programming · Lekcja

Projektowanie systemów aktorów

Naucz się projektować i implementować hierarchie aktorów, definiować ich zachowanie oraz wysyłać i odbierać komunikaty.

Lekcja 2 z 311 kroki

Projektowanie systemów aktorów to bezpłatna lekcja Scala for Backend Engineering & Functional Programming na CoddyKit. To lekcja 2 z 3. Możesz przeczytać całą lekcję poniżej za darmo — a potem ćwiczyć ją interaktywnie w przeglądarce z wbudowanym edytorem kodu i tutorem AI dostępnym 24/7. To część ścieżki edukacyjnej Scala for Backend Engineering & Functional Programming, a Twój postęp synchronizuje się między webem a aplikacją CoddyKit. Kurs Scala for Backend Engineering & Functional Programming zawiera 3 lekcji w sumie.

Wprowadzenie do projektowania systemów aktorów

Witamy na lekcji 2! W poprzedniej lekcji poznaliśmy podstawy modelu aktorów Akka. Teraz przyjrzyjmy się bliżej projektowaniu systemów aktorów Akka.

Dobrze zaprojektowany system aktorów jest niezawodny, skalowalny i łatwy w utrzymaniu. Omówimy sposoby organizowania aktorów, definiowania ich zachowania oraz umożliwiania im skutecznej komunikacji.

Zrozumienie hierarchii aktorów

Aktorzy Akka są zorganizowani w hierarchię przypominającą drzewo, podobnie jak system plików. Każdy aktor, z wyjątkiem aktora „głównego”, ma rodzica.

  • Relacja rodzic–dziecko: Aktor, który tworzy innego aktora, staje się jego rodzicem.
  • Nadzorowanie: Ta hierarchia ma kluczowe znaczenie dla tolerowania błędów w Akka. Rodzice odpowiadają za nadzorowanie swoich dzieci (więcej informacji na ten temat znajdzie Pan/Pani w następnej lekcji!).
  • Adresowanie na podstawie ścieżki: Każdy aktor ma unikatową ścieżkę odzwierciedlającą jego położenie w hierarchii, taką jak /user/parentActor/childActor.

Konfigurowanie ActorSystem

ActorSystem jest punktem wejścia dla wszystkich aplikacji Akka. Zarządza zasobami potrzebnymi aktorom, w tym pulami wątków i harmonogramami.

Obiekt ten tworzy się raz na aplikację, a następnie używa do tworzenia aktorów najwyższego poziomu. Jest on swego rodzaju kontenerem dla całej aplikacji aktorów.

Proszę uruchomić ten prosty kod, aby utworzyć 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()
  }
}

Definiowanie zachowania aktora

Zachowanie aktora określa, jak reaguje on na różne komunikaty. W języku Scala definiuje się je przez rozszerzenie cechy Actor i zaimplementowanie metody receive.

  • Metoda receive jest funkcją częściową, która dopasowuje przychodzące komunikaty do określonych działań.
  • Każdy aktor przetwarza komunikaty pojedynczo i sekwencyjnie, zapewniając bezpieczeństwo wątkowe swojego stanu wewnętrznego.

ActorRef: adres aktora

Nie komunikuje się Pan/Pani bezpośrednio z instancjami aktorów. Zamiast tego wysyła się komunikaty do obiektu ActorRef. Można myśleć o ActorRef jak o adresie pocztowym aktora.

  • Jest to uchwyt reprezentujący konkretnego aktora w systemie.
  • Komunikaty wysyłane do obiektu ActorRef trafiają do skrzynki pocztowej aktora.
  • Obiekt ActorRef uzyskuje się podczas tworzenia aktora za pomocą actorOf.

Wysyłanie komunikatów do aktorów

Podstawowym sposobem komunikacji aktorów jest wysyłanie komunikatów. Najczęściej wysyła się komunikat za pomocą metody ! (wymawianej „tell”).

receiverActorRef ! "Your message here"

Metoda tell działa asynchronicznie i na zasadzie fire-and-forget. Wysyła komunikat i nie czeka na odpowiedź.

Połączmy teraz tworzenie aktora z wysyłaniem do niego komunikatów:

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()
  }
}

Tworzenie aktorów-dzieci

Aktorzy mogą tworzyć innych aktorów, tworząc opisaną wcześniej hierarchię. Aktor-rodzic tworzy aktorów-dzieci za pomocą context.actorOf.

  • context.actorOf: Służy aktorowi do tworzenia jego dzieci.
  • system.actorOf: Służy aplikacji do tworzenia aktorów najwyższego poziomu (aktorów-opiekunów).

Tworzenie aktorów-dzieci pomaga organizować system, delegować zadania i izolować awarie.

Komunikacja między rodzicem a dzieckiem

Aktorzy komunikują się, wysyłając komunikaty do obiektów ActorRef należących do siebie nawzajem. Aktor-dziecko może uzyskać ActorRef swojego rodzica za pomocą context.parent. Aby odpowiedzieć nadawcy komunikatu, aktor może użyć sender().

Zobaczmy przykład, w którym rodzic tworzy dziecko, zleca mu wykonanie zadania, a dziecko po jego zakończeniu odsyła odpowiedź:

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."))
  }
}

Bezpieczne zatrzymywanie aktorów

Aktorów, którzy nie są już potrzebni, należy bezpiecznie zatrzymać, aby zwolnić zasoby. Aktora można zatrzymać na kilka sposobów:

  • context.stop(self): Aktor zatrzymuje sam siebie.
  • context.stop(childRef): Rodzic zatrzymuje jedno ze swoich dzieci.
  • system.stop(actorRef): Dotyczy aktorów najwyższego poziomu, choć zwykle zatrzymuje się cały system.

Podczas zatrzymywania aktor przetwarza wszystkie komunikaty ze swojej skrzynki pocztowej, zanim zakończy działanie. Jego dzieci również są zatrzymywane rekurencyjnie.

Szybkie sprawdzenie: projektowanie aktorów

Proszę przeanalizować poniższy fragment kodu aktora Akka. Jaki jest poprawny sposób, aby MyChildActor wysłał komunikat z powrotem do tworzącego go rodzica, MyParentActor, jeśli MyParentActor był nadawcą początkowego komunikatu „request”?

Podsumowanie: projektowanie systemów aktorów

Świetnie! W tej lekcji omówiliśmy najważniejsze aspekty projektowania systemów aktorów Akka:

  • Aktorzy są zorganizowani w hierarchie, które mają kluczowe znaczenie dla nadzorowania i struktury systemu.
  • ActorSystem jest punktem wejścia aplikacji do Akka.
  • Zachowanie aktora definiuje się za pomocą metody receive.
  • ActorRef jest adresem używanym do wysyłania komunikatów.
  • Aktorzy komunikują się asynchronicznie za pomocą metody ! (tell).
  • Rodzice tworzą dzieci za pomocą context.actorOf, a dzieci mogą odpowiadać za pomocą sender().
  • Aktorów można bezpiecznie zatrzymywać za pomocą context.stop().

W następnej części przyjrzymy się bliżej zaawansowanym strategiom nadzorowania Akka i sposobom bezpiecznej obsługi awarii!

Bezpłatny start

Ucz się Scala dzięki korepetycjom AI — za darmo

Pisz i uruchamiaj kod w przeglądarce, otrzymuj natychmiastową pomoc od korepetytora AI dostępnego 24/7 i kontynuuj naukę w sieci lub w aplikacji.

Kursy
39
Lekcje
143

Często zadawane pytania

Czy lekcja „Projektowanie systemów aktorów” jest bezpłatna?

Tak — pełny tekst „Projektowanie systemów aktorów” jest dostępny za darmo tutaj w sieci. Aby ćwiczyć ją interaktywnie (wbudowany edytor kodu i tutor AI dostępny 24/7) i odblokować resztę kursu Scala for Backend Engineering & Functional Programming, przejdź na CoddyKit PRO. Kurs Scala for Backend Engineering & Functional Programming zawiera 3 lekcji w sumie.

Co nauczysz się w „Projektowanie systemów aktorów”?

Naucz się projektować i implementować hierarchie aktorów, definiować ich zachowanie oraz wysyłać i odbierać komunikaty. Ćwiczysz Scala for Backend Engineering & Functional Programming z praktycznym kodem, który uruchamiasz bezpośrednio w przeglądarce, a tutor AI dostępny 24/7 odpowiada na Twoje pytania podczas pracy nad lekcją.

Czy potrzebuję doświadczenia, aby zacząć Scala for Backend Engineering & Functional Programming?

Nie wymagamy żadnego doświadczenia. Scala for Backend Engineering & Functional Programming w CoddyKit jest strukturyzowany dla początkujących i zaawansowanych użytkowników, więc możesz zacząć tutaj lub od początku i uczyć się w swoim tempie. To lekcja 2 z 3.

Ile czasu zajmuje lekcja „Projektowanie systemów aktorów”?

Większość lekcji CoddyKit trwa około 5–10 minut. Każda lekcja to mały, interaktywny krok, dzięki czemu robisz systematyczne postępy i zawsze wracasz dokładnie do tego samego miejsca — na webie i w aplikacji.

Czy mogę pisać i uruchamiać kod w tej lekcji Scala for Backend Engineering & Functional Programming?

Tak. Każda lekcja Scala for Backend Engineering & Functional Programming zawiera wbudowany edytor kodu, więc piszesz i uruchamiasz prawdziwy kod bezpośrednio w przeglądarce i od razu otrzymujesz sprzężenie zwrotne od AI — bez konfiguracji na komputerze.

Wszystkie lekcje w tym kursie

  1. Podstawy modelu aktorów Akka
  2. Projektowanie systemów aktorów
  3. Nadzorowanie i odporność na awarie
← Powrót do Scala for Backend Engineering & Functional Programming