การควบคุมดูแลและความทนทานต่อความผิดพลาด
สำรวจกลยุทธ์การควบคุมดูแลของ Akka เพื่อสร้างระบบที่ยืดหยุ่นและกู้คืนจากความล้มเหลวได้อย่างเหมาะสม
การควบคุมดูแลและความทนทานต่อความผิดพลาด เป็นบทเรียน Scala for Backend Engineering & Functional Programming ฟรีบน CoddyKit นี่คือบทเรียนที่ 3 จากทั้งหมด 3 บทเรียน คุณสามารถอ่านบทเรียนทั้งหมดด้านล่างฟรี — จากนั้นลองปฏิบัติด้วยตัวคุณเองในเบราว์เซอร์พร้อมตัวแก้ไขโค้ดในตัวและติวเตอร์ AI ตลอด 24/7 บทเรียนนี้เป็นส่วนหนึ่งของเส้นทางการเรียน Scala for Backend Engineering & Functional Programming และความก้าวหน้าของคุณจะซิงค์ข้ามเว็บและแอป CoddyKit คอร์ส Scala for Backend Engineering & Functional Programming มีบทเรียนทั้งหมด 3 บทเรียน
การสร้างระบบที่ทนทาน
ในแอปพลิเคชันที่ทำงานพร้อมกัน อาจเกิดข้อผิดพลาดได้ แอกเตอร์อาจหยุดทำงาน การเรียกเครือข่ายอาจล้มเหลว หรืออาจไม่สามารถเข้าถึงฐานข้อมูลได้
การทนต่อข้อผิดพลาดคือความสามารถของระบบในการทำงานต่อไปได้อย่างถูกต้อง แม้บางส่วนของระบบจะล้มเหลว Akka มีกลไกอันทรงพลังเพื่อให้บรรลุเป้าหมายนี้
การกำกับดูแลระหว่างแม่กับลูก
แอกเตอร์ของ Akka ถูกจัดระเบียบเป็นลำดับชั้น คล้ายกับแผนผังครอบครัว เมื่อแอกเตอร์หนึ่งสร้างแอกเตอร์อีกตัว แอกเตอร์นั้นจะกลายเป็นแอกเตอร์แม่
- แอกเตอร์แม่มีหน้าที่กำกับดูแลแอกเตอร์ลูก
- หากแอกเตอร์ลูกล้มเหลว แอกเตอร์แม่จะได้รับการแจ้งเตือน
- จากนั้นแอกเตอร์แม่จะตัดสินใจว่าจะจัดการกับความล้มเหลวของแอกเตอร์ลูกอย่างไร ซึ่งเรียกว่ากลยุทธ์การกำกับดูแล
การตัดสินใจเมื่อเกิดความล้มเหลว
เมื่อแอกเตอร์ล้มเหลว แอกเตอร์แม่สามารถออกคำสั่งได้หนึ่งในสี่แบบ:
Resume: แอกเตอร์ประมวลผลข้อความต่อไปโดยไม่สนใจความล้มเหลวRestart: แอกเตอร์ถูกหยุด สร้างขึ้นใหม่ แล้วจึงกลับมาประมวลผลต่อ สถานะภายในจะถูกตั้งค่าใหม่Stop: แอกเตอร์ถูกยุติการทำงานอย่างถาวรEscalate: ความล้มเหลวถูกส่งต่อไปยังผู้กำกับดูแลของแอกเตอร์แม่ (แอกเตอร์ปู่)
กลยุทธ์ OneForOne
OneForOneStrategyเป็นกลยุทธ์การกำกับดูแลที่ใช้กันทั่วไป หมายความว่าคำสั่งจะมีผลเฉพาะกับแอกเตอร์ลูกที่ล้มเหลวเท่านั้น
ตัวอย่างเช่น หากแอกเตอร์ลูกตัวหนึ่งหยุดทำงาน แอกเตอร์แม่อาจตัดสินใจเริ่มต้นแอกเตอร์ลูกตัวนั้นใหม่เพียงตัวเดียว โดยไม่ส่งผลกระทบต่อแอกเตอร์ลูกตัวอื่น
OneForOne ในการใช้งานจริง
มาดู OneForOneStrategy กัน เราจะสร้างแอกเตอร์แม่ที่เริ่มต้นแอกเตอร์ลูกใหม่เมื่อเกิด ArithmeticException แต่จะหยุดแอกเตอร์ลูกเมื่อเกิดข้อยกเว้นชนิดอื่น
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()
}สังเกตการทำงานของ OneForOne
คุณได้เรียกใช้โค้ดก่อนหน้านี้หรือไม่ มาดูกันว่าเกิดอะไรขึ้น:
- เมื่อส่ง
"divideByZero"แอกเตอร์ลูกทำให้เกิดArithmeticExceptionแอกเตอร์แม่ใช้คำสั่งRestartคุณจะเห็นบันทึก "Pre-restart" และ "Post-restart" - จากนั้นแอกเตอร์ลูกประมวลผล "Hello again"
- เมื่อส่ง
"nullPointer"แอกเตอร์ลูกทำให้เกิดNullPointerExceptionแอกเตอร์แม่ใช้คำสั่งStopแอกเตอร์ลูกจึงถูกยุติการทำงาน - มีการส่ง "Hello after null" แต่แอกเตอร์ลูกหยุดทำงานไปแล้ว จึงไม่สามารถประมวลผลได้
กลยุทธ์ AllForOne
บางครั้ง ความล้มเหลวของแอกเตอร์ลูกตัวหนึ่งหมายความว่าแอกเตอร์ลูกที่เป็นพี่น้องทั้งหมดอาจได้รับผลกระทบหรือไม่สามารถทำงานได้อย่างถูกต้อง
AllForOneStrategyใช้คำสั่งเดียวกันกับแอกเตอร์ลูกทั้งหมดของผู้กำกับดูแล ไม่ใช่เฉพาะแอกเตอร์ที่ล้มเหลว หากแอกเตอร์ลูกตัวหนึ่งล้มเหลว แอกเตอร์ลูกทั้งหมดจะได้รับผลกระทบจากคำสั่งที่เลือก
AllForOne ในการใช้งานจริง
มาปรับเปลี่ยนแอกเตอร์แม่ให้ใช้ AllForOneStrategy กัน สังเกตว่าความล้มเหลวของแอกเตอร์ลูกตัวหนึ่งส่งผลต่อแอกเตอร์ลูกที่เป็นพี่น้องอย่างไร
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()
}การปรับแต่งตัวตัดสินใจ
คุณสามารถสร้างตรรกะการกำกับดูแลที่ปรับแต่งได้อย่างละเอียดโดยใช้ฟังก์ชันตัวตัดสินใจ ฟังก์ชันนี้รับ Throwable (ข้อยกเว้น) และส่งคืน Directive
วิธีนี้ช่วยให้คุณใช้กฎที่ซับซ้อนโดยอิงจากชนิดของข้อยกเว้น ข้อความที่ทำให้เกิดข้อยกเว้น หรือแม้แต่สถานะของผู้กำกับดูแล
การกำกับดูแลขั้นสูง
ต่อไปนี้คือวิธีกำหนดตัวตัดสินใจแบบกำหนดเองภายในกลยุทธ์การกำกับดูแล เพื่อควบคุมการทำงานได้อย่างละเอียด
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()
}ตรวจสอบความรู้ของคุณ
พิจารณาแอกเตอร์แม่ที่กำกับดูแลแอกเตอร์ลูกสองตัว ได้แก่ childA และ childB แอกเตอร์แม่ใช้ AllForOneStrategy พร้อมคำสั่ง Restart สำหรับข้อยกเว้นทั้งหมด
หาก childA ทำให้เกิดข้อยกเว้น จะเกิดอะไรขึ้น
ทบทวน: การทนต่อข้อผิดพลาด
ทำได้ดีมาก! ในบทเรียนนี้ คุณได้เรียนรู้เกี่ยวกับกลไกการกำกับดูแลอันทรงพลังของ Akka:
- ลำดับชั้นการกำกับดูแล: แอกเตอร์แม่กำกับดูแลแอกเตอร์ลูก
- คำสั่ง:
Resume,Restart,Stop,Escalate OneForOneStrategy: ใช้คำสั่งเฉพาะกับแอกเตอร์ลูกที่ล้มเหลวAllForOneStrategy: ใช้คำสั่งกับแอกเตอร์ลูกทั้งหมด- ตัวตัดสินใจแบบกำหนดเอง: ใช้เพื่อควบคุมการจัดการความล้มเหลวได้อย่างละเอียด
เครื่องมือเหล่านี้จำเป็นต่อการสร้างแอปพลิเคชันที่ทำงานพร้อมกันและแข็งแกร่งทนทานด้วยแอกเตอร์ของ Akka
คำถามที่พบบ่อย
บทเรียน “การควบคุมดูแลและความทนทานต่อความผิดพลาด” ฟรีหรือไม่
ใช่ — ข้อความเต็มของ “การควบคุมดูแลและความทนทานต่อความผิดพลาด” ฟรีให้อ่านที่นี่บนเว็บ เพื่อปฏิบัติแบบโต้ตอบ (ตัวแก้ไขโค้ดในตัวและติวเตอร์ AI ตลอด 24/7) และปลดล็อคส่วนที่เหลือของคอร์ส Scala for Backend Engineering & Functional Programming ให้อัปเกรดเป็น CoddyKit PRO คอร์ส Scala for Backend Engineering & Functional Programming มีบทเรียนทั้งหมด 3 บทเรียน
คุณจะเรียนรู้อะไรในบทเรียน “การควบคุมดูแลและความทนทานต่อความผิดพลาด”
สำรวจกลยุทธ์การควบคุมดูแลของ Akka เพื่อสร้างระบบที่ยืดหยุ่นและกู้คืนจากความล้มเหลวได้อย่างเหมาะสม คุณปฏิบัติ Scala for Backend Engineering & Functional Programming ด้วยโค้ดที่ใช้งานได้จริงที่คุณเรียกใช้โดยตรงในเบราว์เซอร์ และติวเตอร์ AI ตลอด 24/7 ตอบคำถามของคุณขณะที่คุณไปผ่านบทเรียน
คุณต้องมีประสบการณ์ก่อนที่จะเริ่มเรียน Scala for Backend Engineering & Functional Programming หรือไม่
ไม่จำเป็นต้องมีประสบการณ์มาก่อน Scala for Backend Engineering & Functional Programming บน CoddyKit ออกแบบมาสำหรับผู้เริ่มต้นไปจนถึงผู้เรียนขั้นสูง คุณสามารถเริ่มต้นที่นี่หรือเริ่มจากตัวแรกและเรียนด้วยความเร็วของคุณเอง นี่คือบทเรียนที่ 3 จากทั้งหมด 3 บทเรียน
บทเรียน “การควบคุมดูแลและความทนทานต่อความผิดพลาด” ใช้เวลานานแค่ไหน
บทเรียน CoddyKit ส่วนใหญ่ใช้เวลาประมาณ 5–10 นาที แต่ละบทเรียนจึงสั้นและเป็นแบบโต้ตอบ คุณสามารถก้าวหน้าอย่างต่อเนื่องและกลับมาเรียนต่อจากตรงที่เพิ่งหยุดบนเว็บและแอปได้เลย
ฉันเขียนและรันโค้ดในบทเรียน Scala for Backend Engineering & Functional Programming นี้ได้ไหม
ได้ บทเรียน Scala for Backend Engineering & Functional Programming ทุกบทมีตัวแก้ไขโค้ดในตัว คุณจึงเขียนและรันโค้ดจริงได้เลยในเบราว์เซอร์ และได้รับข้อเสนอแนะจาก AI ในทันที — ไม่ต้องติดตั้งในเครื่องของคุณ
บทเรียนทั้งหมดในหลักสูตรนี้
- พื้นฐานโมเดลแอกเตอร์ของ Akka
- การออกแบบระบบแอกเตอร์
- การควบคุมดูแลและความทนทานต่อความผิดพลาด