0Pricing
Scala for Backend Engineering & Functional Programming · Lezione

Progettazione di sistemi ad attori

Impari a progettare e implementare gerarchie di attori, definire i comportamenti degli attori e inviare e ricevere messaggi.

Progettazione di sistemi ad attori è una lezione Scala for Backend Engineering & Functional Programming gratuita su CoddyKit. Questa è la lezione 2 di 3. Puoi leggere la lezione completa qui gratuitamente — poi esercitati direttamente nel browser con un editor di codice integrato e un tutor IA disponibile 24/7. Fa parte del percorso di apprendimento Scala for Backend Engineering & Functional Programming, e i tuoi progressi si sincronizzano tra il web e l'app CoddyKit. Il corso Scala for Backend Engineering & Functional Programming include 3 lezioni in totale.

Introduzione alla progettazione dei sistemi basati su actor

Benvenuto alla lezione 2! Nella lezione precedente abbiamo appreso le nozioni di base dell'Actor Model di Akka. Ora approfondiremo la progettazione dei sistemi basati su actor di Akka.

Un sistema basato su actor ben progettato è robusto, scalabile e facile da mantenere. Vedremo come strutturare gli actor, definirne il comportamento e consentire loro di comunicare in modo efficace.

Comprendere le gerarchie degli actor

Gli actor di Akka sono organizzati in una gerarchia ad albero, proprio come un file system. Ogni actor, ad eccezione dell'actor 'root', ha un parent.

  • Relazione parent-figlio: un actor che crea un altro actor ne diventa il parent.
  • Supervisione: questa gerarchia è fondamentale per la tolleranza agli errori di Akka. I parent sono responsabili della supervisione dei propri figli (approfondiremo questo argomento nella prossima lezione!).
  • Indirizzamento basato sul percorso: ogni actor ha un percorso univoco che riflette la sua posizione nella gerarchia, come /user/parentActor/childActor.

Configurazione di ActorSystem

ActorSystem è il punto di ingresso per tutte le applicazioni Akka. Gestisce le risorse necessarie agli actor, inclusi i pool di thread e gli scheduler.

Viene creato una sola volta per applicazione e utilizzato successivamente per creare gli actor di primo livello. È come il contenitore dell'intera applicazione basata su actor.

Provi a eseguire questo semplice codice per creare un 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()
  }
}

Definizione del comportamento degli actor

Il comportamento di un actor determina il modo in cui reagisce ai diversi messaggi. In Scala, lo si definisce estendendo il trait Actor e implementando il metodo receive.

  • Il metodo receive è una funzione parziale che associa i messaggi in arrivo ad azioni specifiche.
  • Ogni actor elabora i messaggi uno alla volta, in sequenza, garantendo la sicurezza dei thread per il proprio stato interno.

ActorRef: l'indirizzo dell'actor

Non si interagisce direttamente con le istanze degli actor. Al contrario, si inviano messaggi a un ActorRef. Consideri ActorRef come l'indirizzo postale di un actor.

  • È un riferimento che rappresenta uno specifico actor all'interno del sistema.
  • I messaggi inviati a un ActorRef vengono inseriti nella mailbox dell'actor.
  • Si ottiene un ActorRef quando si crea un actor utilizzando actorOf.

Invio di messaggi agli actor

Il modo principale in cui gli actor comunicano consiste nell'invio di messaggi. Il modo più comune per inviare un messaggio è utilizzare il metodo ! (pronunciato 'tell').

receiverActorRef ! "Your message here"

Il metodo tell è asincrono e segue il modello fire-and-forget. Invia il messaggio senza attendere una risposta.

Combiniamo ora la creazione di un actor con l'invio di messaggi:

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

Creazione di actor figli

Gli actor possono crearne altri, formando la gerarchia descritta in precedenza. Un actor parent crea i propri actor figli utilizzando context.actorOf.

  • context.actorOf: viene utilizzato da un actor per creare i propri figli.
  • system.actorOf: viene utilizzato dall'applicazione per creare actor di primo livello (guardian).

La creazione di actor figli aiuta a organizzare il sistema, delegare le attività e isolare gli errori.

Comunicazione tra parent e figli

Gli actor comunicano inviando messaggi agli ActorRef degli altri actor. Un actor figlio può ottenere l'ActorRef del parent tramite context.parent. Per rispondere al mittente di un messaggio, un actor può utilizzare sender().

Vediamo un esempio in cui un parent crea un figlio, gli ordina di eseguire un'attività e il figlio comunica il completamento:

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

Arresto corretto degli actor

Gli actor non più necessari devono essere arrestati correttamente per rilasciare le risorse. È possibile arrestare un actor in diversi modi:

  • context.stop(self): un actor arresta se stesso.
  • context.stop(childRef): un parent arresta uno dei propri figli.
  • system.stop(actorRef): viene utilizzato per gli actor di primo livello, anche se di solito si arresta l'intero sistema.

Quando un actor viene arrestato, elabora tutti i messaggi presenti nella mailbox prima di terminare. Anche i suoi figli vengono arrestati ricorsivamente.

Verifica rapida: progettazione degli actor

Consideri il seguente frammento di codice di un actor Akka. Qual è il modo corretto per consentire a MyChildActor di inviare un messaggio al parent che lo ha creato, MyParentActor, se MyParentActor era il mittente del messaggio iniziale 'request'?

Riepilogo: progettazione dei sistemi basati su actor

Ottimo lavoro! In questa lezione abbiamo trattato alcuni aspetti fondamentali della progettazione dei sistemi basati su actor di Akka:

  • Gli actor sono organizzati in gerarchie, fondamentali per la supervisione e la struttura del sistema.
  • ActorSystem è il punto di ingresso dell'applicazione in Akka.
  • Il comportamento degli actor viene definito utilizzando il metodo receive.
  • ActorRef è l'indirizzo utilizzato per inviare messaggi.
  • Gli actor comunicano in modo asincrono utilizzando il metodo ! (tell).
  • I parent creano i figli con context.actorOf e i figli possono rispondere utilizzando sender().
  • Gli actor possono essere arrestati correttamente utilizzando context.stop().

Successivamente approfondiremo le potenti strategie di supervisione di Akka e la gestione corretta degli errori!

Domande Frequenti

La lezione «Progettazione di sistemi ad attori» è gratuita?

Sì — il testo completo di «Progettazione di sistemi ad attori» è gratuito qui sul web. Per esercitarvi in modo interattivo (un editor di codice integrato e un tutor IA 24/7) e sbloccare il resto del corso Scala for Backend Engineering & Functional Programming, passa a CoddyKit PRO. Il corso Scala for Backend Engineering & Functional Programming include 3 lezioni in totale.

Cosa imparerò in «Progettazione di sistemi ad attori»?

Impari a progettare e implementare gerarchie di attori, definire i comportamenti degli attori e inviare e ricevere messaggi. Eserciti Scala for Backend Engineering & Functional Programming con codice pratico che esegui direttamente nel browser, e un tutor IA 24/7 risponde alle tue domande mentre lavori sulla lezione.

Ho bisogno di esperienza per iniziare Scala for Backend Engineering & Functional Programming?

Non è richiesta alcuna esperienza precedente. Scala for Backend Engineering & Functional Programming su CoddyKit è strutturato per principianti e studenti avanzati, quindi puoi iniziare da qui o dall'inizio e procedere al tuo ritmo. Questa è la lezione 2 di 3.

Quanto tempo richiede la lezione «Progettazione di sistemi ad attori»?

La maggior parte delle lezioni CoddyKit richiede circa 5–10 minuti. Ogni lezione è breve e interattiva, quindi fai progressi costanti e riprendi esattamente da dove hai lasciato su web e app.

Posso scrivere ed eseguire codice in questa lezione Scala for Backend Engineering & Functional Programming?

Sì. Ogni lezione Scala for Backend Engineering & Functional Programming include un editor di codice integrato, quindi scrivi ed esegui codice reale direttamente nel tuo browser e ricevi feedback istantaneo dall'IA — nessuna configurazione locale necessaria.

Tutte le lezioni di questo corso

  1. Fondamenti del modello ad attori di Akka
  2. Progettazione di sistemi ad attori
  3. Supervisione e tolleranza ai guasti
← Torna a Scala for Backend Engineering & Functional Programming