portaldacalheta.pt
  • หลัก
  • ทีมแบบกระจาย
  • เคล็ดลับและเครื่องมือ
  • ชีวิตนักออกแบบ
  • นวัตกรรม
เทคโนโลยี

ภาวะพร้อมกันและความคลาดเคลื่อนทำได้ง่าย: บทช่วยสอน Akka พร้อมตัวอย่าง



ความท้าทาย

การเขียน โปรแกรมพร้อมกัน เป็นเรื่องยาก การต้องจัดการกับเธรดการล็อกเงื่อนไขการแข่งขันและอื่น ๆ มีโอกาสเกิดข้อผิดพลาดสูงและอาจนำไปสู่รหัสที่ยากต่อการอ่านทดสอบและบำรุงรักษา

หลายคนจึงชอบที่จะหลีกเลี่ยงการอ่านแบบมัลติเธรดโดยสิ้นเชิง แต่พวกเขาใช้กระบวนการแบบเธรดเดียวโดยอาศัยบริการภายนอก (เช่นฐานข้อมูลคิว ฯลฯ ) เพื่อจัดการการดำเนินการพร้อมกันหรือแบบอะซิงโครนัสที่จำเป็น แม้ว่าแนวทางนี้จะเป็นทางเลือกที่ถูกต้องในบางกรณี แต่ก็มีหลายสถานการณ์ที่ไม่ใช่ทางเลือกที่เป็นไปได้ ระบบเรียลไทม์จำนวนมากเช่นแอปพลิเคชันการซื้อขายหรือการธนาคารหรือเกมแบบเรียลไทม์ไม่ต้องรอให้กระบวนการเธรดชุดเดียวเสร็จสมบูรณ์ (พวกเขาต้องการคำตอบเดี๋ยวนี้!) ระบบอื่น ๆ มีการคำนวณหรือใช้ทรัพยากรมากจนอาจต้องใช้เวลามากเกินไป (หลายชั่วโมงหรือหลายวันในบางกรณี) ในการทำงานโดยไม่ต้องนำการขนานเข้ากับโค้ด



วิธีการแบบเธรดเดียวที่ค่อนข้างใช้กันทั่วไป (ใช้กันอย่างแพร่หลายใน โหนด js โลกเป็นต้น) คือการใช้กระบวนทัศน์ที่อิงตามเหตุการณ์และไม่ปิดกั้น แม้ว่าสิ่งนี้จะช่วยเพิ่มประสิทธิภาพโดยหลีกเลี่ยงการสลับบริบทการล็อกและการบล็อก แต่ก็ยังไม่ได้แก้ไขปัญหาของการใช้โปรเซสเซอร์หลายตัวพร้อมกัน (การดำเนินการดังกล่าวจะต้องมีการเปิดใช้งานและการประสานงานระหว่างกระบวนการอิสระหลาย ๆ กระบวนการ)



ทำความเข้าใจรหัส c ++

นั่นหมายความว่าคุณไม่มีทางเลือกอื่นนอกจากต้องเดินทางลึกเข้าไปในส่วนลึกของเธรดล็อคและเงื่อนไขการแข่งขันเพื่อสร้างแอปพลิเคชันพร้อมกันหรือไม่?



ขอบคุณกรอบ Akka คำตอบคือไม่ บทช่วยสอนนี้แนะนำตัวอย่างของ Akka และสำรวจวิธีที่อำนวยความสะดวกและลดความยุ่งยากในการใช้งานแอปพลิเคชันแบบกระจายพร้อมกัน

Akka Framework คืออะไร?

โพสต์นี้แนะนำ Akka และสำรวจวิธีที่อำนวยความสะดวกและลดความยุ่งยากในการใช้งานแอปพลิเคชันแบบกระจายพร้อมกัน

Akka เป็นชุดเครื่องมือและรันไทม์สำหรับการสร้างแอปพลิเคชั่นที่รองรับการทำงานพร้อมกันกระจายและทนต่อข้อผิดพลาดบน JVM Akka เขียนใน บันได โดยมีการผูกภาษาสำหรับทั้ง Scala และ Java



แนวทางของ Akka ในการจัดการการทำงานพร้อมกันนั้นขึ้นอยู่กับ นักแสดงรุ่น . ในระบบที่อิงตามนักแสดงทุกอย่างคือนักแสดงในลักษณะเดียวกับที่ทุกอย่างเป็นวัตถุในการออกแบบเชิงวัตถุ แม้ว่าความแตกต่างที่สำคัญ - เกี่ยวข้องกับการสนทนาของเราโดยเฉพาะ - คือโมเดลนักแสดงได้รับการออกแบบมาโดยเฉพาะและออกแบบมาเพื่อใช้เป็นโมเดลพร้อมกันในขณะที่โมเดลเชิงวัตถุไม่ได้ โดยเฉพาะอย่างยิ่งในระบบนักแสดง Scala นักแสดงโต้ตอบและแบ่งปันข้อมูลโดยไม่ต้องมีการคาดเดาถึงลำดับ กลไกที่นักแสดงแบ่งปันข้อมูลซึ่งกันและกันและทำงานซึ่งกันและกันคือการส่งผ่านข้อความ

ความซับซ้อนทั้งหมดของการสร้างและกำหนดเวลาเธรดการรับและการส่งข้อความและการจัดการเงื่อนไขการแข่งขันและการซิงโครไนซ์จะถูกส่งไปยังกรอบงานเพื่อจัดการอย่างโปร่งใส

Akka สร้างเลเยอร์ระหว่างนักแสดงและระบบพื้นฐานเพื่อให้นักแสดงต้องประมวลผลข้อความ ความซับซ้อนทั้งหมดของการสร้างและกำหนดเวลาเธรดการรับและการส่งข้อความและการจัดการเงื่อนไขการแข่งขันและการซิงโครไนซ์จะถูกส่งไปยังกรอบงานเพื่อจัดการอย่างโปร่งใส



Akka ปฏิบัติตามไฟล์ แถลงการณ์ปฏิกิริยา . แอ็พพลิเคชันแบบตอบสนองมีเป้าหมายที่การแทนที่แอ็พพลิเคชันแบบมัลติเธรดแบบดั้งเดิมด้วยสถาปัตยกรรมที่ตรงตามข้อกำหนดต่อไปนี้อย่างน้อยหนึ่งข้อ:

  • ขับเคลื่อนด้วยเหตุการณ์ การใช้ Actors เราสามารถเขียนโค้ดที่จัดการคำขอแบบอะซิงโครนัสและใช้การดำเนินการที่ไม่ปิดกั้นโดยเฉพาะ
  • ปรับขนาดได้ ใน Akka การเพิ่มโหนดโดยไม่ต้องแก้ไขโค้ดทำได้ด้วยทั้งการส่งข้อความและความโปร่งใสของตำแหน่ง
  • ยืดหยุ่น. แอปพลิเคชันใด ๆ จะพบข้อผิดพลาดและล้มเหลวในบางช่วงเวลา Akka จัดเตรียมกลยุทธ์ 'การกำกับดูแล' (การยอมรับความผิดพลาด) เพื่ออำนวยความสะดวกให้กับระบบบำบัดตนเอง
  • ตอบสนอง แอปพลิเคชันที่มีประสิทธิภาพสูงและตอบสนองอย่างรวดเร็วจำนวนมากในปัจจุบันจำเป็นต้องให้ข้อเสนอแนะอย่างรวดเร็วแก่ผู้ใช้ดังนั้นจึงจำเป็นต้องตอบสนองต่อเหตุการณ์ต่างๆอย่างทันท่วงที กลยุทธ์ที่ใช้ข้อความแบบไม่ปิดกั้นของ Akka ช่วยให้บรรลุเป้าหมายนี้

นักแสดงใน Akka คืออะไร?

โดยพื้นฐานแล้วนักแสดงไม่ได้เป็นอะไรมากไปกว่าวัตถุที่รับข้อความและดำเนินการเพื่อจัดการกับพวกเขา ข้อความนี้แยกออกจากแหล่งที่มาของข้อความและความรับผิดชอบเพียงอย่างเดียวคือการรับรู้ประเภทของข้อความที่ได้รับอย่างเหมาะสมและดำเนินการตามนั้น



เมื่อได้รับข้อความนักแสดงอาจดำเนินการอย่างน้อยหนึ่งอย่างต่อไปนี้:

  • ดำเนินการบางอย่างด้วยตัวเอง (เช่นการคำนวณข้อมูลที่มีอยู่การเรียกใช้บริการเว็บภายนอกเป็นต้น)
  • ส่งต่อข้อความหรือข้อความที่ได้รับไปยังนักแสดงคนอื่น
  • กระตุ้นนักแสดงหน้าใหม่และส่งต่อข้อความไปให้

หรืออีกวิธีหนึ่งนักแสดงอาจเลือกที่จะเพิกเฉยต่อข้อความทั้งหมด (กล่าวคืออาจเลือกที่จะเพิกเฉย) หากเห็นว่าเหมาะสมที่จะทำเช่นนั้น



ในการใช้นักแสดงจำเป็นต้องขยาย akka.actor ลักษณะของนักแสดงและใช้วิธีการรับ ระบบจะเรียกใช้วิธีการรับของนักแสดง (โดย Akka) เมื่อมีการส่งข้อความถึงนักแสดงคนนั้น การใช้งานโดยทั่วไปประกอบด้วยการจับคู่รูปแบบดังที่แสดงในตัวอย่าง Akka ต่อไปนี้เพื่อระบุประเภทข้อความและตอบสนองตามนั้น:

import akka.actor.Actor import akka.actor.Props import akka.event.Logging class MyActor extends Actor { def receive = { case value: String => doSomething(value) case _ => println('received unknown message') } }

การจับคู่รูปแบบเป็นเทคนิคที่ค่อนข้างหรูหราในการจัดการข้อความซึ่งมีแนวโน้มที่จะสร้างโค้ดที่ 'สะอาด' และง่ายต่อการนำทางมากกว่าการใช้งานแบบเทียบเคียงตามการเรียกกลับ พิจารณาตัวอย่างเช่นการดำเนินการตามคำขอ / การตอบกลับ HTTP ที่เรียบง่าย



ก่อนอื่นให้นำสิ่งนี้ไปใช้โดยใช้กระบวนทัศน์แบบเรียกกลับใน JavaScript:

route(url, function(request){ var query = buildQuery(request); dbCall(query, function(dbResponse){ var wsRequest = buildWebServiceRequest(dbResponse); wsCall(wsRequest, function(wsResponse) { sendReply(wsResponse); }); }); });

ตอนนี้เรามาเปรียบเทียบสิ่งนี้กับการใช้งานตามรูปแบบ:

msg match { case HttpRequest(request) => { val query = buildQuery(request) dbCall(query) } case DbResponse(dbResponse) => { var wsRequest = buildWebServiceRequest(dbResponse); wsCall(dbResponse) } case WsResponse(wsResponse) => sendReply(wsResponse) }

แม้ว่าโค้ด JavaScript แบบเรียกกลับจะมีขนาดกะทัดรัด แต่ก็ยากที่จะอ่านและนำทาง ในการเปรียบเทียบรหัสตามการจับคู่รูปแบบทำให้เห็นได้ชัดขึ้นทันทีว่ากรณีใดบ้างที่กำลังพิจารณาและวิธีจัดการแต่ละกรณี

ระบบนักแสดง

การแก้ปัญหาที่ซับซ้อนและแยกเป็นปัญหาย่อย ๆ ซ้ำ ๆ เป็นเทคนิคการแก้ปัญหาเสียงโดยทั่วไป แนวทางนี้สามารถเป็นประโยชน์อย่างยิ่งในวิทยาการคอมพิวเตอร์ (สอดคล้องกับ หลักการความรับผิดชอบเดียว ) เนื่องจากมีแนวโน้มที่จะให้รหัสที่สะอาดและเป็นโมดูลาร์โดยมีความซ้ำซ้อนเพียงเล็กน้อยหรือไม่มีเลยซึ่งค่อนข้างง่ายต่อการบำรุงรักษา

ในการออกแบบตามนักแสดงการใช้เทคนิคนี้ช่วยให้องค์กรเชิงตรรกะของนักแสดงกลายเป็นโครงสร้างลำดับชั้นที่เรียกว่า ระบบนักแสดง . ระบบนักแสดงจัดเตรียมโครงสร้างพื้นฐานที่นักแสดงโต้ตอบซึ่งกันและกัน

ตัวอย่างวิธีการทำงานของระบบนักแสดงในกรอบ Akka

ใน Akka วิธีเดียวที่จะสื่อสารกับนักแสดงคือ ActorRef อัน ActorRef แสดงถึงการอ้างอิงถึงนักแสดงที่กีดกันวัตถุอื่น ๆ จากการเข้าถึงโดยตรงหรือจัดการกับภายในและสถานะของนักแสดงคนนั้น อาจมีการส่งข้อความถึงนักแสดงผ่านทาง ActorRef โดยใช้หนึ่งในโปรโตคอลไวยากรณ์ต่อไปนี้:

  • ! (“ บอก”) - ส่งข้อความและส่งกลับทันที
  • ? (“ ask”) - ส่งข้อความและส่งกลับ a อนาคต แทนคำตอบที่เป็นไปได้

นักแสดงแต่ละคนมีกล่องจดหมายสำหรับส่งข้อความขาเข้า มีการใช้งานกล่องจดหมายหลายแบบให้เลือกโดยการใช้งานเริ่มต้นคือ FIFO

นักแสดงมีตัวแปรอินสแตนซ์จำนวนมากเพื่อรักษาสถานะขณะประมวลผลข้อความหลายข้อความ Akka ช่วยให้มั่นใจได้ว่าอินสแตนซ์ของนักแสดงแต่ละคนทำงานในเธรดที่มีน้ำหนักเบาของตัวเองและข้อความจะถูกประมวลผลทีละรายการ ด้วยวิธีนี้จะรักษาสถานะของนักแสดงแต่ละคนได้อย่างน่าเชื่อถือโดยที่นักพัฒนาไม่จำเป็นต้องกังวลอย่างชัดเจนเกี่ยวกับการซิงโครไนซ์หรือเงื่อนไขการแข่งขัน

นักแสดงแต่ละคนจะได้รับข้อมูลที่เป็นประโยชน์ต่อไปนี้สำหรับการปฏิบัติงานผ่าน Akka Actor API:

  • sender: อัน ActorRef ไปยังผู้ส่งข้อความที่กำลังดำเนินการ
  • context: ข้อมูลและวิธีการที่เกี่ยวข้องกับบริบทที่นักแสดงกำลังทำงานอยู่ (รวมถึงวิธีการ actorOf สำหรับการสร้างอินสแตนซ์นักแสดงใหม่)
  • supervisionStrategy: กำหนดกลยุทธ์ที่จะใช้สำหรับการกู้คืนจากข้อผิดพลาด
  • self: the ActorRef สำหรับนักแสดงเอง
Akka ช่วยให้มั่นใจได้ว่าอินสแตนซ์ของนักแสดงแต่ละคนทำงานในเธรดที่มีน้ำหนักเบาของตัวเองและข้อความจะถูกประมวลผลทีละรายการ ด้วยวิธีนี้สถานะของนักแสดงแต่ละคนสามารถรักษาไว้ได้อย่างน่าเชื่อถือโดยที่นักพัฒนาไม่จำเป็นต้องกังวลอย่างชัดเจนเกี่ยวกับการซิงโครไนซ์หรือเงื่อนไขการแข่งขัน

เพื่อช่วยรวมบทช่วยสอนเหล่านี้เข้าด้วยกันลองพิจารณาตัวอย่างง่ายๆของการนับจำนวนคำในไฟล์ข้อความ

สำหรับวัตถุประสงค์ของตัวอย่าง Akka เราจะแยกปัญหาออกเป็นสองงานย่อย กล่าวคือ (1) งาน 'เด็ก' ในการนับจำนวนคำในบรรทัดเดียวและ (2) งาน 'หลัก' ในการสรุปจำนวนคำต่อบรรทัดเพื่อให้ได้จำนวนคำทั้งหมดในไฟล์

ผู้แสดงหลักจะโหลดแต่ละบรรทัดจากไฟล์จากนั้นมอบหมายให้นักแสดงเด็กทำหน้าที่นับจำนวนคำในบรรทัดนั้น เมื่อเด็กทำเสร็จแล้วก็จะส่งข้อความกลับไปยังผู้ปกครองพร้อมผลลัพธ์ ผู้ปกครองจะได้รับข้อความที่มีจำนวนคำ (สำหรับแต่ละบรรทัด) และมีตัวนับสำหรับจำนวนคำทั้งหมดในไฟล์ทั้งหมดซึ่งจะส่งกลับไปยังผู้เรียกใช้เมื่อเสร็จสิ้น

(โปรดทราบว่าตัวอย่างโค้ดบทช่วยสอน Akka ที่ให้ไว้ด้านล่างมีไว้เพื่อการสอนเท่านั้นดังนั้นจึงไม่จำเป็นต้องเกี่ยวข้องกับเงื่อนไขขอบทั้งหมดการเพิ่มประสิทธิภาพการทำงานและอื่น ๆ นอกจากนี้ตัวอย่างโค้ดเวอร์ชันที่รวบรวมได้ทั้งหมดที่แสดงด้านล่างมีอยู่ใน นี้ สาระสำคัญ .)

ก่อนอื่นมาดูตัวอย่างการใช้งานเด็ก StringCounterActor ชั้น:

case class ProcessStringMsg(string: String) case class StringProcessedMsg(words: Integer) class StringCounterActor extends Actor { def receive = { case ProcessStringMsg(string) => { val wordsInLine = string.split(' ').length sender ! StringProcessedMsg(wordsInLine) } case _ => println('Error: message not recognized') } }

นักแสดงคนนี้มีภารกิจที่ง่ายมาก: บริโภค ProcessStringMsg ข้อความ (ประกอบด้วยบรรทัดข้อความ) นับจำนวนคำในบรรทัดที่ระบุและส่งคืนผลลัพธ์ไปยังผู้ส่งผ่านทาง StringProcessedMsg ข้อความ. โปรดทราบว่าเราได้นำคลาสของเราไปใช้กับ ! (“ บอก”) วิธีการส่ง StringProcessedMsg ข้อความ (เช่นเพื่อส่งข้อความและส่งกลับทันที)

ตกลงตอนนี้เรามาสนใจผู้ปกครองกันเถอะ WordCounterActor ชั้น:

ทำงานหมายเลขบัตรเครดิต 2017 กับเงิน
1. case class StartProcessFileMsg() 2. 3. class WordCounterActor(filename: String) extends Actor { 4. 5. private var running = false 6. private var totalLines = 0 7. private var linesProcessed = 0 8. private var result = 0 9. private var fileSender: Option[ActorRef] = None 10. 11. def receive = { 12. case StartProcessFileMsg() => { 13. if (running) { 14. // println just used for example purposes; 15. // Akka logger should be used instead 16. println('Warning: duplicate start message received') 17. } else { 18. running = true 19. fileSender = Some(sender) // save reference to process invoker 20. import scala.io.Source._ 21. fromFile(filename).getLines.foreach { line => 22. context.actorOf(Props[StringCounterActor]) ! ProcessStringMsg(line) 23. totalLines += 1 24. } 25. } 26. } 27. case StringProcessedMsg(words) => { 28. result += words 29. linesProcessed += 1 30. if (linesProcessed == totalLines) { 31. fileSender.map(_ ! result) // provide result to process invoker 32. } 33. } 34. case _ => println('message not recognized!') 35. } 36. }

มีหลายสิ่งเกิดขึ้นที่นี่เรามาดูรายละเอียดแต่ละข้อกันดีกว่า (โปรดทราบว่าหมายเลขบรรทัดที่อ้างถึงในการสนทนาที่ตามมาเป็นไปตามตัวอย่างโค้ดด้านบน) ...

ขั้นแรกให้สังเกตว่าชื่อของไฟล์ที่จะประมวลผลถูกส่งไปยัง WordCounterActor ตัวสร้าง (บรรทัดที่ 3) สิ่งนี้บ่งชี้ว่านักแสดงจะถูกใช้เพื่อประมวลผลไฟล์เดียวเท่านั้น นอกจากนี้ยังช่วยลดความซับซ้อนของงานการเข้ารหัสสำหรับนักพัฒนาโดยหลีกเลี่ยงความจำเป็นในการรีเซ็ตตัวแปรสถานะ (running, totalLines, linesProcessed และ result) เมื่องานเสร็จสิ้น เนื่องจากอินสแตนซ์ถูกใช้เพียงครั้งเดียว (กล่าวคือเพื่อประมวลผลไฟล์เดียว) จากนั้นจึงทิ้ง

ถัดไปสังเกตว่า WordCounterActor จัดการข้อความสองประเภท:

  • StartProcessFileMsg (บรรทัดที่ 12)
    • ได้รับจากนักแสดงภายนอกที่เริ่มต้น WordCounterActor.
    • เมื่อได้รับข้อความ WordCounterActor ก่อนอื่นให้ตรวจสอบว่าไม่ได้รับคำขอซ้ำซ้อน
    • หากคำขอซ้ำซ้อน WordCounterActor สร้างคำเตือนและไม่มีอะไรทำอีกแล้ว (บรรทัดที่ 16)
    • หากคำขอไม่ซ้ำซ้อน:
      • WordCounterActor จัดเก็บข้อมูลอ้างอิงถึงผู้ส่งใน fileSender ตัวแปรอินสแตนซ์ (โปรดทราบว่านี่คือ Option[ActorRef] แทนที่จะเป็น Option[Actor] - ดูบรรทัดที่ 9) นี้ ActorRef จำเป็นเพื่อเข้าถึงและตอบสนองในภายหลังเมื่อประมวลผลขั้นสุดท้าย StringProcessedMsg (ซึ่งได้รับจาก StringCounterActor เด็กตามที่อธิบายไว้ด้านล่าง)
      • WordCounterActor จากนั้นอ่านไฟล์และเมื่อโหลดแต่ละบรรทัดในไฟล์ a StringCounterActor เด็กถูกสร้างขึ้นและข้อความที่มีบรรทัดที่จะประมวลผลจะถูกส่งผ่านไป (บรรทัดที่ 21-24)
  • StringProcessedMsg (บรรทัดที่ 27)
    • รับตั้งแต่เด็ก StringCounterActor เมื่อประมวลผลบรรทัดที่กำหนดให้เสร็จสิ้น
    • เมื่อได้รับข้อความ WordCounterActor เพิ่มตัวนับบรรทัดสำหรับไฟล์และหากทุกบรรทัดในไฟล์ได้รับการประมวลผล (เช่นเมื่อ totalLines และ linesProcessed เท่ากัน) จะส่งผลลัพธ์สุดท้ายไปยังต้นฉบับ fileSender (บรรทัดที่ 28-31)

สังเกตอีกครั้งว่าใน Akka กลไกเดียวสำหรับการสื่อสารระหว่างนักแสดงคือการส่งข้อความ ข้อความเป็นสิ่งเดียวที่นักแสดงแบ่งปันและเนื่องจากนักแสดงสามารถเข้าถึงข้อความเดียวกันได้ในเวลาเดียวกันสิ่งสำคัญคือต้องไม่เปลี่ยนรูปเพื่อหลีกเลี่ยงสภาพการแข่งขันและพฤติกรรมที่ไม่คาดคิด

ทำไมกรีซถึงเป็นหนี้
คลาสเคส ใน Scala เป็นคลาสปกติที่มีกลไกการสลายตัวแบบวนซ้ำผ่านการจับคู่รูปแบบ

ดังนั้นจึงเป็นเรื่องปกติที่จะส่งผ่านข้อความในรูปแบบของคลาสเคสเนื่องจากไม่เปลี่ยนรูปตามค่าเริ่มต้นและเนื่องจากการรวมเข้ากับการจับคู่รูปแบบได้อย่างราบรื่น

มาสรุปตัวอย่างกับตัวอย่างโค้ดเพื่อเรียกใช้แอปทั้งหมด

object Sample extends App { import akka.util.Timeout import scala.concurrent.duration._ import akka.pattern.ask import akka.dispatch.ExecutionContexts._ implicit val ec = global override def main(args: Array[String]) { val system = ActorSystem('System') val actor = system.actorOf(Props(new WordCounterActor(args(0)))) implicit val timeout = Timeout(25 seconds) val future = actor ? StartProcessFileMsg() future.map { result => println('Total number of words ' + result) system.shutdown } } } ในการเขียนโปรแกรมพร้อมกัน 'อนาคต' เป็นวัตถุตัวยึดสำหรับผลลัพธ์ที่ยังไม่ทราบแน่ชัด

สังเกตว่าเวลานี้ ? ใช้วิธีการส่งข้อความ ด้วยวิธีนี้ผู้โทรสามารถใช้การส่งคืน อนาคต เพื่อพิมพ์ผลลัพธ์สุดท้ายเมื่อพร้อมใช้งานและออกจากโปรแกรมโดยปิด ActorSystem

Akka ความอดทนต่อความผิดพลาดและกลยุทธ์ของหัวหน้างาน

ในระบบนักแสดงนักแสดงแต่ละคนเป็นผู้ดูแลลูก ๆ หากนักแสดงไม่สามารถจัดการกับข้อความได้นักแสดงจะระงับตัวเองและลูก ๆ ทั้งหมดและส่งข้อความโดยปกติจะอยู่ในรูปแบบของการยกเว้นไปยังหัวหน้างาน

ใน Akka กลยุทธ์ของหัวหน้างานเป็นกลไกหลักและตรงไปตรงมาในการกำหนดพฤติกรรมการยอมรับข้อผิดพลาดของระบบของคุณ

ใน Akka วิธีที่หัวหน้างานตอบสนองและจัดการกับข้อยกเว้นที่ซึมผ่านมาจากเด็ก ๆ เรียกว่ากลยุทธ์ของหัวหน้างาน กลยุทธ์ของหัวหน้างาน เป็นกลไกหลักและตรงไปตรงมาที่คุณกำหนดพฤติกรรมการยอมรับความผิดพลาดของระบบของคุณ

เมื่อข้อความที่แสดงถึงความล้มเหลวไปถึงหัวหน้างานอาจดำเนินการอย่างใดอย่างหนึ่งต่อไปนี้:

  • ดำเนินการต่อเด็ก (และลูก ๆ ) โดยรักษาสภาพภายใน กลยุทธ์นี้สามารถใช้ได้เมื่อสถานะลูกไม่ได้รับความเสียหายจากข้อผิดพลาดและสามารถทำงานต่อไปได้อย่างถูกต้อง
  • รีสตาร์ทลูก (และลูกของมัน) ล้างสถานะภายใน กลยุทธ์นี้สามารถใช้ได้ในสถานการณ์ตรงกันข้ามกับที่อธิบายไว้ หากสถานะลูกได้รับความเสียหายจากข้อผิดพลาดจำเป็นต้องรีเซ็ตสถานะก่อนจึงจะสามารถใช้งานได้ในอนาคต
  • หยุดเด็ก (และลูกของมัน) อย่างถาวร กลยุทธ์นี้สามารถใช้ได้ในกรณีที่ไม่เชื่อว่าเงื่อนไขข้อผิดพลาดจะแก้ไขได้ แต่ไม่เป็นอันตรายต่อการดำเนินการที่เหลือที่กำลังดำเนินการซึ่งสามารถทำได้ในกรณีที่ไม่มีลูกที่ล้มเหลว
  • หยุดตัวเองและส่งต่อข้อผิดพลาด ทำงานเมื่อหัวหน้างานไม่ทราบวิธีจัดการกับความล้มเหลวจึงส่งต่อไปยังหัวหน้างานของตนเอง

ยิ่งไปกว่านั้นนักแสดงสามารถตัดสินใจที่จะใช้การกระทำกับเด็กที่ล้มเหลวหรือพี่น้องได้เช่นกัน มีสองกลยุทธ์ที่กำหนดไว้ล่วงหน้าสำหรับสิ่งนี้:

  • OneForOneStrategy: ใช้การดำเนินการที่ระบุกับเด็กที่ล้มเหลวเท่านั้น
  • AllForOneStrategy: ใช้การกระทำที่ระบุกับลูก ๆ ทั้งหมด

นี่คือตัวอย่างง่ายๆโดยใช้ OneForOneStrategy:

import akka.actor.OneForOneStrategy import akka.actor.SupervisorStrategy._ import scala.concurrent.duration._ override val supervisorStrategy = OneForOneStrategy() { case _: ArithmeticException => Resume case _: NullPointerException => Restart case _: IllegalArgumentException => Stop case _: Exception => Escalate }

หากไม่มีการระบุกลยุทธ์จะใช้กลยุทธ์เริ่มต้นต่อไปนี้:

  • หากเกิดข้อผิดพลาดขณะเริ่มต้นนักแสดงหรือหากนักแสดงถูกฆ่านักแสดงจะหยุดทำงาน
  • หากมีข้อยกเว้นประเภทอื่นนักแสดงจะเริ่มต้นใหม่

การใช้กลยุทธ์เริ่มต้นนี้โดย Akka มีดังต่อไปนี้:

final val defaultStrategy: SupervisorStrategy = { def defaultDecider: Decider = { case _: ActorInitializationException ⇒ Stop case _: ActorKilledException ⇒ Stop case _: Exception ⇒ Restart } OneForOneStrategy()(defaultDecider) }

Akka อนุญาตให้ใช้ กลยุทธ์ของหัวหน้างานที่กำหนดเอง แต่ตามที่เอกสาร Akka เตือนโปรดดำเนินการด้วยความระมัดระวังเนื่องจากการใช้งานที่ไม่ถูกต้องอาจนำไปสู่ปัญหาเช่นระบบนักแสดงที่ถูกบล็อก (เช่นนักแสดงที่ถูกระงับถาวร)

ความโปร่งใสของสถานที่

สถาปัตยกรรม Akka รองรับ ความโปร่งใสของสถานที่ ทำให้นักแสดงไม่เชื่อเรื่องพระเจ้าโดยสิ้นเชิงว่าข้อความที่พวกเขาได้รับมานั้นมาจากที่ใด ผู้ส่งข้อความอาจอยู่ใน JVM เดียวกันกับผู้แสดงหรือใน JVM แยกต่างหาก (รันบนโหนดเดียวกันหรือโหนดอื่น) Akka ช่วยให้แต่ละกรณีสามารถจัดการในลักษณะที่โปร่งใสสำหรับนักแสดง (และดังนั้นผู้พัฒนา) ข้อแม้เดียวคือข้อความที่ส่งข้ามหลายโหนดจะต้องต่ออนุกรมกันได้

สถาปัตยกรรม Akka รองรับความโปร่งใสของสถานที่ทำให้นักแสดงไม่เชื่อเรื่องพระเจ้าอย่างสิ้นเชิงว่าข้อความที่ได้รับมาจากที่ใด

ระบบ Actor ได้รับการออกแบบให้ทำงานในสภาพแวดล้อมแบบกระจายโดยไม่ต้องใช้รหัสพิเศษใด ๆ Akka ต้องการเฉพาะไฟล์คอนฟิกูเรชัน (application.conf) ที่ระบุโหนดที่จะส่งข้อความถึง ตัวอย่างง่ายๆของไฟล์การกำหนดค่ามีดังนี้

akka { actor { provider = 'akka.remote.RemoteActorRefProvider' } remote { transport = 'akka.remote.netty.NettyRemoteTransport' netty { hostname = '127.0.0.1' port = 2552 } } }

เคล็ดลับการแยกทาง ...

เราได้เห็นว่ากรอบงาน Akka ช่วยให้เกิดการทำงานพร้อมกันและประสิทธิภาพสูงได้อย่างไร อย่างไรก็ตามตามที่บทช่วยสอนนี้ชี้ให้เห็นมีบางประเด็นที่ควรคำนึงถึงเมื่อออกแบบและใช้ระบบของคุณเพื่อใช้ประโยชน์จากพลังของ Akka อย่างเต็มที่:

  • ในระดับที่มากที่สุดนักแสดงแต่ละคนควรได้รับมอบหมายงานที่เล็กที่สุดเท่าที่จะเป็นไปได้ (ตามที่กล่าวไว้ก่อนหน้านี้ตาม หลักการความรับผิดชอบเดียว )
  • นักแสดงควรจัดการกับเหตุการณ์ต่างๆ (เช่นข้อความประมวลผล) แบบอะซิงโครนัสและไม่ควรปิดกั้นมิฉะนั้นการสลับบริบทจะเกิดขึ้นซึ่งอาจส่งผลเสียต่อประสิทธิภาพ โดยเฉพาะอย่างยิ่งควรดำเนินการบล็อก (IO ฯลฯ ) ในอนาคตเพื่อไม่ให้ปิดกั้นนักแสดง เช่น:

    case evt => blockingCall() // BAD case evt => Future { blockingCall() // GOOD }
  • ตรวจสอบให้แน่ใจว่าข้อความของคุณไม่เปลี่ยนรูปเนื่องจากนักแสดงที่ส่งต่อกันจะทำงานพร้อมกันในชุดข้อความของตนเอง ข้อความที่ไม่แน่นอนอาจส่งผลให้เกิดพฤติกรรมที่ไม่คาดคิด
  • เนื่องจากข้อความที่ส่งระหว่างโหนดจะต้องสามารถต่ออนุกรมกันได้จึงเป็นสิ่งสำคัญที่ต้องจำไว้ว่ายิ่งข้อความมีขนาดใหญ่ก็จะยิ่งใช้เวลาในการทำให้เป็นอนุกรมส่งและยกเลิกการกำหนดค่าสถานะนานขึ้นซึ่งอาจส่งผลเสียต่อประสิทธิภาพการทำงาน

สรุป

Akka เขียนใน บันได ลดความซับซ้อนและอำนวยความสะดวกในการพัฒนาแอปพลิเคชั่นที่มีการกระจายและทนต่อความผิดพลาดสูงพร้อมกันโดยซ่อนความซับซ้อนจากผู้พัฒนา การทำความยุติธรรมอย่างเต็มที่ของ Akka จะต้องใช้มากกว่าแบบฝึกหัดเดียวนี้ แต่หวังว่าบทนำและตัวอย่างนี้จะน่าดึงดูดพอที่จะทำให้คุณอยากอ่านเพิ่มเติม

Amazon, VMWare และ CSC เป็นเพียงตัวอย่างของ บริษัท ชั้นนำที่ใช้งาน Akka อย่างจริงจัง เยี่ยมชม เว็บไซต์ Akka อย่างเป็นทางการ เพื่อเรียนรู้เพิ่มเติมและสำรวจว่า Akka อาจเป็นคำตอบที่เหมาะสมสำหรับโครงการของคุณหรือไม่

สถานะของหุ้นเอกชนในปี 2020

นักลงทุนและเงินทุน

สถานะของหุ้นเอกชนในปี 2020
สร้างเครือข่ายสิ่งพิมพ์ด้วย Pandoc และ Docker

สร้างเครือข่ายสิ่งพิมพ์ด้วย Pandoc และ Docker

เทคโนโลยี

โพสต์ยอดนิยม
เอกสาร Agile: การปรับสมดุลความเร็วและการรักษาความรู้
เอกสาร Agile: การปรับสมดุลความเร็วและการรักษาความรู้
ทำลายหลักการออกแบบ (ด้วยอินโฟกราฟิก)
ทำลายหลักการออกแบบ (ด้วยอินโฟกราฟิก)
วิธีจัดโครงสร้างลำดับชั้นการพิมพ์ที่มีประสิทธิภาพ
วิธีจัดโครงสร้างลำดับชั้นการพิมพ์ที่มีประสิทธิภาพ
ฮาร์ดแวร์ที่คล่องตัวพร้อมการพัฒนาซอฟต์แวร์ในตัว
ฮาร์ดแวร์ที่คล่องตัวพร้อมการพัฒนาซอฟต์แวร์ในตัว
วิธีการรวม OAuth 2 เข้ากับ Django / DRF Back-end ของคุณโดยไม่บ้า
วิธีการรวม OAuth 2 เข้ากับ Django / DRF Back-end ของคุณโดยไม่บ้า
 
GWT Toolkit: สร้างส่วนหน้า JavaScript ที่มีประสิทธิภาพโดยใช้ Java
GWT Toolkit: สร้างส่วนหน้า JavaScript ที่มีประสิทธิภาพโดยใช้ Java
แหล่งข้อมูลสำหรับธุรกิจขนาดเล็กสำหรับ COVID-19: เงินกู้เงินช่วยเหลือและสินเชื่อ
แหล่งข้อมูลสำหรับธุรกิจขนาดเล็กสำหรับ COVID-19: เงินกู้เงินช่วยเหลือและสินเชื่อ
Libation Frontiers: เจาะลึกอุตสาหกรรมไวน์โลก
Libation Frontiers: เจาะลึกอุตสาหกรรมไวน์โลก
เรียนรู้ Markdown: เครื่องมือการเขียนสำหรับนักพัฒนาซอฟต์แวร์
เรียนรู้ Markdown: เครื่องมือการเขียนสำหรับนักพัฒนาซอฟต์แวร์
พบกับ Phoenix: กรอบงานคล้ายรางสำหรับเว็บแอปสมัยใหม่บน Elixir
พบกับ Phoenix: กรอบงานคล้ายรางสำหรับเว็บแอปสมัยใหม่บน Elixir
โพสต์ยอดนิยม
  • aws Solutions Architect เตรียมสอบ
  • โหนด js ใช้สำหรับ
  • บอทที่ไม่ลงรอยกันคืออะไร
  • ความแตกต่างระหว่าง s corp และ corp
  • บทที่ 11 หมายถึงอะไร
  • ซีเอฟโอทำอะไร
หมวดหมู่
  • ทีมแบบกระจาย
  • เคล็ดลับและเครื่องมือ
  • ชีวิตนักออกแบบ
  • นวัตกรรม
  • © 2022 | สงวนลิขสิทธิ์

    portaldacalheta.pt