Überwachung und Fehlertoleranz
Erkunden Sie Akkas Überwachungsstrategien, um robuste Systeme zu erstellen, die sich angemessen von Fehlern erholen können.
Überwachung und Fehlertoleranz ist eine kostenlose Scala for Backend Engineering & Functional Programming-Lektion auf CoddyKit. Dies ist Lektion 3 von 3. Du kannst die komplette Lektion unten kostenlos lesen – dann übst du sie direkt im Browser mit einem integrierten Code-Editor und einem KI-Tutor rund um die Uhr. Sie ist Teil des Scala for Backend Engineering & Functional Programming-Lernpfads, und dein Fortschritt wird über Web und CoddyKit-App synchronisiert. Der Scala for Backend Engineering & Functional Programming-Kurs umfasst insgesamt 3 Lektionen.
Teile dieser Lektion wurden noch nicht übersetzt und werden auf Englisch angezeigt.
Building Resilient Systems
In concurrent applications, things can go wrong. An actor might crash, a network call might fail, or a database might be unreachable.
Fault tolerance is the ability of a system to continue operating correctly even when parts of it fail. Akka provides powerful mechanisms to achieve this.
Parent-Child Supervision
Akka actors are organized in a hierarchy, much like a family tree. When an actor creates another actor, it becomes its parent.
- Parents are responsible for supervising their children.
- If a child actor fails, its parent receives a notification.
- The parent then decides how to handle the child's failure. This is called a supervision strategy.
Deciding on Failure
When an actor fails, its parent can issue one of four directives:
Resume: The actor continues processing messages, ignoring the failure.Restart: The actor is stopped, recreated, and then resumes processing. Its internal state is reset.Stop: The actor is permanently terminated.Escalate: The failure is passed up to the parent's supervisor (its grandparent).
OneForOne Strategy
The OneForOneStrategy is a common supervision strategy. It means that a directive applies only to the child actor that failed.
For example, if one child actor crashes, the parent might decide to restart only that specific child, leaving other children unaffected.
OneForOne in Action
Let's see OneForOneStrategy. We'll create a parent that restarts a child on an ArithmeticException but stops it on other exceptions.
import akka.actor._
import akka.actor.SupervisorStrategy._
import scala.concurrent.duration._
object OneForOneExample extends App {
class Child extends Actor {
override def preStart(): Unit = {
println(s"Child ${self.path.name}: Started!")
}
override def postStop(): Unit = {
println(s"Child ${self.path.name}: Stopped!")
}
override def preRestart(reason: Throwable, message: Option[Any]): Unit = {
println(s"Child ${self.path.name}: Pre-restart due to ${reason.getMessage}")
}
override def postRestart(reason: Throwable): Unit = {
println(s"Child ${self.path.name}: Post-restart!")
}
def receive = {
case "divideByZero" => throw new ArithmeticException("Oops, dividing by zero!")
case "nullPointer" => throw new NullPointerException("Something is null!")
case msg => println(s"Child ${self.path.name}: Received $msg")
}
}
class Parent extends Actor {
override val supervisorStrategy: SupervisorStrategy =
OneForOneStrategy(maxNrOfRetries = 10, withinTimeRange = 1.minute) {
case _: ArithmeticException => Restart
case _: NullPointerException => Stop
case _ => Escalate
}
val child = context.actorOf(Props[Child], "myChild")
def receive = {
case msg => child ! msg
}
}
val system = ActorSystem("OneForOneSystem")
val parent = system.actorOf(Props[Parent], "myParent")
parent ! "Hello"
parent ! "divideByZero" // Should cause a restart
Thread.sleep(100)
parent ! "Hello again"
Thread.sleep(1000) // Give time for restart to complete
parent ! "nullPointer" // Should cause a stop
Thread.sleep(100)
parent ! "Hello after null" // This message will not be processed by child
Thread.sleep(2000)
system.terminate()
}Observing OneForOne
Did you run the previous code? Here's what happened:
- When
"divideByZero"was sent, the child threw anArithmeticException. The parent appliedRestart. You saw "Pre-restart" and "Post-restart" logs. - The child then processed "Hello again".
- When
"nullPointer"was sent, the child threw aNullPointerException. The parent appliedStop. The child was terminated. - "Hello after null" was sent, but the child was already stopped and couldn't process it.
AllForOne Strategy
Sometimes, a failure in one child means that all sibling children might also be compromised or unable to function correctly.
The AllForOneStrategy applies the same directive to all children of the supervisor, not just the one that failed. If one child fails, all children are affected by the chosen directive.
AllForOne in Action
Let's modify our parent to use AllForOneStrategy. Notice how one child's failure affects its sibling.
import akka.actor._
import akka.actor.SupervisorStrategy._
import scala.concurrent.duration._
object AllForOneExample extends App {
class Child extends Actor {
override def preStart(): Unit = {
println(s"Child ${self.path.name}: Started!")
}
override def postStop(): Unit = {
println(s"Child ${self.path.name}: Stopped!")
}
override def preRestart(reason: Throwable, message: Option[Any]): Unit = {
println(s"Child ${self.path.name}: Pre-restart due to ${reason.getMessage}")
}
override def postRestart(reason: Throwable): Unit = {
println(s"Child ${self.path.name}: Post-restart!")
}
def receive = {
case "fail" => throw new RuntimeException("Child failed!")
case msg => println(s"Child ${self.path.name}: Received $msg")
}
}
class Parent extends Actor {
override val supervisorStrategy: SupervisorStrategy =
AllForOneStrategy(maxNrOfRetries = 10, withinTimeRange = 1.minute) {
case _: RuntimeException => Restart
case _ => Escalate
}
val childA = context.actorOf(Props[Child], "childA")
val childB = context.actorOf(Props[Child], "childB")
def receive = {
case "failA" => childA ! "fail"
case "msgB" => childB ! "Hello from B"
case msg => println(s"Parent received: $msg")
}
}
val system = ActorSystem("AllForOneSystem")
val parent = system.actorOf(Props[Parent], "myParent")
parent ! "msgB" // Child B receives a message
Thread.sleep(100)
parent ! "failA" // Child A fails, causing all children to restart
Thread.sleep(1000)
parent ! "msgB" // Child B (restarted) receives another message
Thread.sleep(2000)
system.terminate()
}Customizing Deciders
You can create highly customized supervision logic using a decider function. This function takes a Throwable (the exception) and returns a Directive.
This allows you to implement complex rules based on the type of exception, the message that caused it, or even the state of the supervisor.
Advanced Supervision
Here's how to define a custom decider within your supervisor strategy for fine-grained control.
import akka.actor._
import akka.actor.SupervisorStrategy._
import scala.concurrent.duration._
object CustomDeciderExample extends App {
class Worker extends Actor {
def receive = {
case "criticalError" => throw new IllegalStateException("Critical state!")
case "minorError" => throw new IllegalArgumentException("Bad input!")
case msg => println(s"Worker: Received $msg")
}
}
class Supervisor extends Actor {
override val supervisorStrategy: SupervisorStrategy =
OneForOneStrategy(maxNrOfRetries = 3, withinTimeRange = 10.seconds) {
case _: IllegalArgumentException => Resume // Minor error, just resume
case _: IllegalStateException => Restart // Critical, restart
case _: Exception => Stop // Unknown, stop
case _ => Escalate // Others, escalate
}
val worker = context.actorOf(Props[Worker], "myWorker")
def receive = {
case msg => worker ! msg
}
}
val system = ActorSystem("CustomDeciderSystem")
val supervisor = system.actorOf(Props[Supervisor], "mySupervisor")
supervisor ! "Hello"
supervisor ! "minorError" // Should Resume
Thread.sleep(100)
supervisor ! "Hello again" // Worker should still be active
Thread.sleep(500)
supervisor ! "criticalError" // Should Restart
Thread.sleep(100)
supervisor ! "After critical" // Worker should be restarted
Thread.sleep(1500)
system.terminate()
}Check Your Knowledge
Consider a parent actor supervising two child actors, childA and childB. The parent uses an AllForOneStrategy with the directive Restart for all exceptions.
If childA throws an exception, what will happen?
Recap: Fault Tolerance
Great job! In this lesson, you've learned about Akka's powerful supervision mechanisms:
- Supervision Hierarchy: Parents supervise children.
- Directives:
Resume,Restart,Stop,Escalate. OneForOneStrategy: Applies directives only to the failed child.AllForOneStrategy: Applies directives to all children.- Custom Deciders: For fine-grained control over failure handling.
These tools are essential for building robust and resilient concurrent applications with Akka Actors!
Häufig gestellte Fragen
Ist die Lektion „Überwachung und Fehlertoleranz“ kostenlos?
Ja — der vollständige Text von „Überwachung und Fehlertoleranz“ ist hier im Web kostenlos zu lesen. Um sie interaktiv zu üben (integrierter Code-Editor und 24/7 KI-Tutor) und den Rest des Scala for Backend Engineering & Functional Programming-Kurses freizuschalten, upgrade auf CoddyKit PRO. Der Scala for Backend Engineering & Functional Programming-Kurs umfasst insgesamt 3 Lektionen.
Was lerne ich in „Überwachung und Fehlertoleranz“?
Erkunden Sie Akkas Überwachungsstrategien, um robuste Systeme zu erstellen, die sich angemessen von Fehlern erholen können. Du übst Scala for Backend Engineering & Functional Programming mit praktischem Code, den du direkt im Browser ausführst, und ein 24/7 KI-Tutor beantwortet deine Fragen während du die Lektion bearbeitest.
Brauche ich Erfahrung, um Scala for Backend Engineering & Functional Programming zu starten?
Keine Vorkenntnisse erforderlich. Scala for Backend Engineering & Functional Programming auf CoddyKit ist für Anfänger bis fortgeschrittene Lernende strukturiert, sodass du hier starten oder von Anfang an beginnen und in deinem eigenen Tempo voranschreiten kannst. Dies ist Lektion 3 von 3.
Wie lange dauert die Lektion „Überwachung und Fehlertoleranz“?
Die meisten CoddyKit-Lektionen dauern etwa 5–10 Minuten. Jede ist kompakt und interaktiv, sodass du stetig Fortschritte machst und genau dort weitermachst, wo du aufgehört hast – im Web und in der App.
Kann ich in dieser Scala for Backend Engineering & Functional Programming-Lektion Code schreiben und ausführen?
Ja. Jede Scala for Backend Engineering & Functional Programming-Lektion enthält einen integrierten Code-Editor, sodass du echten Code direkt in deinem Browser schreibst und ausführst und sofort KI-Feedback erhältst — ohne lokale Einrichtung erforderlich.
Alle Lektionen in diesem Kurs
- Grundlagen des Akka Actor-Modells
- Actor-Systeme entwerfen
- Überwachung und Fehlertoleranz