Projetando sistemas de atores
Aprenda a projetar e implementar hierarquias de atores, definir comportamentos de atores e enviar e receber mensagens.
Projetando sistemas de atores é uma aula grátis de Scala for Backend Engineering & Functional Programming no CoddyKit. Esta é a aula 2 de 3. Você pode ler a aula completa abaixo gratuitamente — depois pratica ao vivo no navegador com um editor de código integrado e um tutor de IA 24/7. Faz parte do caminho de aprendizado de Scala for Backend Engineering & Functional Programming, e seu progresso é sincronizado entre a web e o app CoddyKit. O curso de Scala for Backend Engineering & Functional Programming inclui 3 aulas no total.
Criando sistemas de atores: introdução
Boas-vindas à Lição 2! Na lição anterior, aprendemos os fundamentos do Modelo de Atores do Akka. Agora, vamos nos aprofundar no design de sistemas de atores do Akka.
Um sistema de atores bem projetado é robusto, escalável e fácil de manter. Vamos explorar como estruturar seus atores, definir seus comportamentos e permitir que eles se comuniquem com eficiência.
Compreendendo as hierarquias de atores
Os atores do Akka são organizados em uma hierarquia semelhante a uma árvore, assim como um sistema de arquivos. Todo ator, exceto o ator 'raiz', tem um pai.
- Relação pai-filho: um ator que cria outro ator torna-se seu pai.
- Supervisão: essa hierarquia é essencial para a tolerância a falhas do Akka. Os pais são responsáveis por supervisionar seus filhos (veremos mais sobre isso na próxima lição!).
- Endereçamento baseado em caminho: cada ator tem um caminho exclusivo, que representa sua posição na hierarquia, como
/user/parentActor/childActor.
Configurando seu ActorSystem
O ActorSystem é o ponto de entrada para todas as aplicações Akka. Ele gerencia os recursos necessários aos atores, incluindo conjuntos de segmentos e agendadores.
Você o cria uma vez por aplicação e depois o utiliza para criar seus atores de nível superior. Ele funciona como o contêiner de toda a sua aplicação de atores.
Experimente executar este código simples para criar um 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()
}
}Definindo o comportamento dos atores
O comportamento de um ator determina como ele reage a diferentes mensagens. Em Scala, você define isso estendendo o traço Actor e implementando o método receive.
- O método
receiveé uma função parcial que associa mensagens recebidas a ações específicas. - Cada ator processa as mensagens uma por vez, sequencialmente, garantindo a segurança de threads para seu estado interno.
ActorRef: o endereço do ator
Você não interage diretamente com as instâncias dos atores. Em vez disso, envia mensagens para um ActorRef. Pense no ActorRef como o endereço postal de um ator.
- Ele é uma referência que representa um ator específico dentro do sistema.
- As mensagens enviadas para um
ActorRefsão colocadas na caixa de mensagens do ator. - Você obtém um
ActorRefao criar um ator usandoactorOf.
Enviando mensagens aos atores
A principal forma de comunicação entre atores é o envio de mensagens. A maneira mais comum de enviar uma mensagem é usando o método ! (pronunciado 'tell').
receiverActorRef ! "Your message here"
O método tell é assíncrono e funciona no modelo de disparar e esquecer. Ele envia a mensagem e não espera uma resposta.
Vamos combinar a criação de um ator com o envio de mensagens para ele:
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()
}
}Criando atores filhos
Os atores podem criar outros atores, formando a hierarquia que discutimos. Um ator pai cria seus atores filhos usando context.actorOf.
context.actorOf: usado por um ator para criar seus filhos.system.actorOf: usado pela aplicação para criar atores de nível superior (guardiões).
A criação de atores filhos ajuda a organizar o sistema, delegar tarefas e isolar falhas.
Comunicação entre pai e filho
Os atores se comunicam enviando mensagens para o ActorRef uns dos outros. Um ator filho pode obter o ActorRef de seu pai por meio de context.parent. Para responder ao remetente de uma mensagem, um ator pode usar sender().
Vamos ver um exemplo em que um pai cria um filho, diz a ele para realizar um trabalho e o filho informa quando termina:
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."))
}
}Interrompendo atores de forma adequada
Os atores devem ser interrompidos de forma adequada quando não forem mais necessários, para que os recursos sejam liberados. Você pode interromper um ator de algumas maneiras:
context.stop(self): o ator interrompe a si mesmo.context.stop(childRef): um pai interrompe um de seus filhos.system.stop(actorRef): usado para atores de nível superior, embora normalmente você interrompa o sistema inteiro.
Quando um ator é interrompido, ele processa todas as mensagens em sua caixa de mensagens antes de terminar. Seus filhos também são interrompidos recursivamente.
Verificação rápida: design de atores
Considere o seguinte trecho de código de um ator do Akka. Qual é a maneira correta de MyChildActor enviar uma mensagem de volta ao pai que o criou, MyParentActor, se MyParentActor foi o remetente da mensagem inicial de 'request'?
Recapitulação: criando sistemas de atores
Excelente trabalho! Nesta lição, abordamos aspectos importantes do design de sistemas de atores do Akka:
- Os atores são organizados em hierarquias, essenciais para a supervisão e a estrutura.
- O
ActorSystemé o ponto de entrada da sua aplicação para o Akka. - Você define o comportamento dos atores usando o método
receive. - O
ActorRefé o endereço usado para enviar mensagens. - Os atores se comunicam de forma assíncrona usando o método
!(tell). - Os pais criam filhos com
context.actorOf, e os filhos podem responder usandosender(). - Os atores podem ser interrompidos de forma adequada usando
context.stop().
Em seguida, vamos nos aprofundar nas poderosas estratégias de supervisão do Akka e em como lidar adequadamente com falhas!
Perguntas Frequentes
A aula “Projetando sistemas de atores” é grátis?
Sim — o texto completo de “Projetando sistemas de atores” é grátis para ler aqui na web. Para praticá-la interativamente (um editor de código integrado e um tutor de IA 24/7) e desbloquear o restante do curso de Scala for Backend Engineering & Functional Programming, atualize para CoddyKit PRO. O curso de Scala for Backend Engineering & Functional Programming inclui 3 aulas no total.
O que vou aprender em “Projetando sistemas de atores”?
Aprenda a projetar e implementar hierarquias de atores, definir comportamentos de atores e enviar e receber mensagens. Você pratica Scala for Backend Engineering & Functional Programming com código prático que executa diretamente no navegador, e um tutor de IA 24/7 responde suas dúvidas enquanto trabalha na aula.
Preciso ter experiência prévia para começar Scala for Backend Engineering & Functional Programming?
Nenhuma experiência prévia é necessária. Scala for Backend Engineering & Functional Programming no CoddyKit é estruturado para alunos iniciantes até avançados, então você pode começar aqui ou desde o início e aprender no seu ritmo. Esta é a aula 2 de 3.
Quanto tempo leva a aula “Projetando sistemas de atores”?
A maioria das aulas CoddyKit leva cerca de 5–10 minutos. Cada uma é compacta e interativa, então você faz progresso constante e retoma exatamente de onde parou entre web e app.
Posso escrever e executar código nesta aula de Scala for Backend Engineering & Functional Programming?
Sim. Cada aula de Scala for Backend Engineering & Functional Programming inclui um editor de código integrado, então você escreve e executa código real direto no navegador e recebe feedback de IA instantaneamente — nenhuma configuração local necessária.
Todas as aulas deste curso
- Fundamentos do modelo de atores do Akka
- Projetando sistemas de atores
- Supervisão e tolerância a falhas