ฮอลลีวูดเป็นเครื่องยนต์นักแสดงที่รวดเร็วเป็นพิเศษสำหรับการใช้งานความเร็วและความล่าช้าต่ำ ลองนึกถึงเซิร์ฟเวอร์เกมโบรกเกอร์โฆษณาเครื่องยนต์ซื้อขาย ฯลฯ ... สามารถจัดการได้ 10 ล้านข้อความในเวลาไม่ถึง 1 วินาที
โมเดลนักแสดงเป็นแบบจำลองการคำนวณที่ใช้ในการสร้างระบบที่เกิดขึ้นพร้อมกันและกระจายอย่างมาก มันได้รับการแนะนำโดย Carl Hewitt ในปี 1973 เพื่อจัดการระบบที่ซับซ้อนในลักษณะที่ปรับขนาดได้และทนต่อความผิดได้มากขึ้น
ในโมเดลนักแสดงการสร้างขั้นพื้นฐานเป็นนักแสดงบางครั้งเรียกว่าผู้รับในฮอลลีวูดซึ่งเป็นหน่วยการคำนวณอิสระที่สื่อสารกับนักแสดงคนอื่น ๆ โดยการแลกเปลี่ยนข้อความ นักแสดงแต่ละคนมีสถานะและพฤติกรรมของตัวเองและสามารถสื่อสารกับนักแสดงคนอื่นได้โดยการส่งข้อความ กระบวนทัศน์การผ่านข้อความนี้ช่วยให้ระบบที่มีการกระจายอำนาจและทนต่อความผิดพลาดสูงเนื่องจากนักแสดงสามารถดำเนินการต่อไปได้อย่างอิสระแม้ว่านักแสดงคนอื่นจะล้มเหลวหรือไม่พร้อมใช้งาน
นักแสดงสามารถจัดเป็นลำดับชั้นได้โดยมีนักแสดงระดับสูงกว่าที่ดูแลและประสานงานนักแสดงระดับล่าง สิ่งนี้ช่วยให้การสร้างระบบที่ซับซ้อนซึ่งสามารถจัดการกับความล้มเหลวและข้อผิดพลาดในวิธีที่สง่างามและคาดเดาได้
ด้วยการใช้โมเดลนักแสดงในแอปพลิเคชันของคุณคุณสามารถสร้างระบบที่ปรับขนาดได้และทนต่อความผิดพลาดสูงซึ่งสามารถจัดการกับผู้ใช้ที่เกิดขึ้นพร้อมกันจำนวนมากและการโต้ตอบที่ซับซ้อน
รับประกันการส่งข้อความเกี่ยวกับความล้มเหลวของนักแสดง (กลไกบัฟเฟอร์)
Fire & Forget หรือ Request & Response Messaging หรือทั้งสองอย่าง
DRPC ประสิทธิภาพสูงเป็นชั้นการขนส่ง
บัฟเฟอร์โปรโตที่เหมาะสมโดยไม่มีการสะท้อนกลับ
น้ำหนักเบาและปรับแต่งได้สูง
การสนับสนุนคลัสเตอร์สำหรับการเขียนนักแสดงที่ค้นพบตัวเองแบบกระจาย
make bench
spawned 10 engines spawned 2000 actors per engine Send storm starting, will send for 10s using 20 workers Messages sent per second 3244217 .. Messages sent per second 3387478 Concurrent senders: 20 messages sent 35116641, messages received 35116641 - duration: 10s messages per second: 3511664 deadletters: 0
go get github.com/anthdm/hollywood/...
ฮอลลีวูดต้องการ Golang เวอร์ชัน
1.21
เราขอแนะนำให้คุณเริ่มต้นด้วยการเขียนตัวอย่างบางส่วนที่ทำงานในพื้นที่ การทำงานในพื้นที่นั้นง่ายกว่าเล็กน้อยเนื่องจากคอมไพเลอร์สามารถหาประเภทที่ใช้ได้ เมื่อทำงานจากระยะไกลคุณจะต้องให้คำจำกัดความของ protobuffer สำหรับคอมไพเลอร์
มาดูข้อความสวัสดีโลกกันเถอะ ตัวอย่างที่สมบูรณ์มีอยู่ในโฟลเดอร์ Hello World เริ่มต้นกันในหลัก:
Engine, Err: = Actor.NewEngine (Actor.NewenginConfig ())
สิ่งนี้สร้างเครื่องยนต์ใหม่ เครื่องยนต์เป็นแกนหลักของฮอลลีวูด มันรับผิดชอบในการวางไข่นักแสดงส่งข้อความและจัดการวงจรชีวิตของนักแสดง หากฮอลลีวูดล้มเหลวในการสร้างเครื่องยนต์มันจะส่งคืนข้อผิดพลาด สำหรับการพัฒนาคุณไม่ควรใช้เพื่อส่งตัวเลือกใด ๆ ไปยังเครื่องยนต์เพื่อให้คุณสามารถผ่าน NIL ได้ เราจะดูตัวเลือกในภายหลัง
ต่อไปเราจะต้องสร้างนักแสดง เหล่านี้เป็นบางครั้งที่เรียกว่า Receivers หลังจากอินเทอร์เฟซที่พวกเขาต้องใช้ มาสร้างนักแสดงใหม่ที่จะพิมพ์ข้อความเมื่อได้รับข้อความ
pid: = engine.spawn (Newhelloer, "Hello")
สิ่งนี้จะทำให้เครื่องยนต์วางไข่นักแสดงด้วย ID "สวัสดี" นักแสดงจะถูกสร้างขึ้นโดยฟังก์ชั่น newHelloer ID ต้องไม่ซ้ำกัน มันจะส่งคืนตัวชี้ไปยัง PID PID เป็นตัวระบุกระบวนการ มันเป็นตัวระบุที่ไม่เหมือนใครสำหรับนักแสดง เวลาส่วนใหญ่ที่คุณจะใช้ PID เพื่อส่งข้อความถึงนักแสดง เทียบกับระบบระยะไกลคุณจะใช้ ID เพื่อส่งข้อความ แต่ในระบบท้องถิ่นคุณจะใช้ PID เป็นส่วนใหญ่
ลองดูฟังก์ชั่น newHelloer และนักแสดงที่กลับมา
พิมพ์ helloer struct {} func newhelloer () actor.receiver {return & helloer {}
- ง่ายพอ. ฟังก์ชั่น newHelloer ส่งคืนนักแสดงใหม่ นักแสดงเป็นโครงสร้างที่ใช้นักแสดง ให้ดูที่วิธี Receive
พิมพ์ข้อความ {} func (h *helloer) รับ (ctx *actor.context) {switch msg: = ctx.message (). (พิมพ์) {case actor.initialized: fmt.println ("helloer ได้เริ่มต้น") กรณี ") นักแสดงเริ่มต้น: fmt.println ("helloer ได้เริ่มต้น") กรณีนักแสดง stopped: fmt.println ("helloer หยุด") กรณี *ข้อความ: fmt.println ("Hello World", msg.data)
-
-คุณสามารถเห็นเรากำหนดโครงสร้างข้อความ นี่คือข้อความที่เราจะส่งไปยังนักแสดงในภายหลัง วิธีการรับยังจัดการข้อความอื่น ๆ อีกสองสามข้อความ ข้อความวงจรชีวิตเหล่านี้จะถูกส่งไปยังนักแสดงคุณจะใช้สิ่งเหล่านี้เพื่อเริ่มต้นนักแสดงของคุณ
เครื่องยนต์ผ่านนักแสดง context ไปยังวิธี Receive บริบทนี้มีข้อความ PID ของผู้ส่งและการพึ่งพาอื่น ๆ ที่คุณสามารถใช้ได้
ตอนนี้ให้ส่งข้อความถึงนักแสดง เราจะส่ง message แต่คุณสามารถส่งข้อความประเภทใดก็ได้ที่คุณต้องการ ข้อกำหนดเพียงอย่างเดียวคือนักแสดงจะต้องสามารถจัดการกับข้อความได้ เพื่อให้ข้อความสามารถข้ามสายไฟได้พวกเขาจะต้องเป็นอนุกรม เพื่อให้ Protobuf สามารถทำให้ข้อความเป็นอนุกรมมันจะต้องเป็นตัวชี้ ข้อความท้องถิ่นสามารถเป็นประเภทใดก็ได้
ในที่สุดให้ส่งข้อความถึงนักแสดง
Engine.Send (PID, "Hello World!")
สิ่งนี้จะส่งข้อความถึงนักแสดง ฮอลลีวูดจะกำหนดเส้นทางข้อความไปยังนักแสดงที่ถูกต้อง จากนั้นนักแสดงจะพิมพ์ข้อความไปยังคอนโซล
โฟลเดอร์ ตัวอย่าง เป็นสถานที่ที่ดีที่สุดในการเรียนรู้และสำรวจฮอลลีวูดต่อไป
เมื่อคุณวางไข่นักแสดงคุณจะต้องจัดทำฟังก์ชั่นที่ส่งคืนนักแสดงใหม่ เนื่องจากนักแสดงวางไข่มีตัวเลือกที่ปรับได้สองสามตัวที่คุณสามารถให้ได้
E.Spawn (newfoo, "myactorname")
บางครั้งคุณจะต้องผ่านข้อโต้แย้งไปยังตัวสร้างนักแสดง สามารถทำได้โดยใช้การปิด มีตัวอย่างนี้ในตัวอย่างคำขอ ดูรหัสกันเถอะ
ตัวสร้างเริ่มต้นจะมีลักษณะเช่นนี้:
func newnameresponder () actor.receiver {return & nameresponder {ชื่อ: "noname"}
-ในการสร้างนักแสดงใหม่ที่มีชื่อที่คุณสามารถทำได้ต่อไปนี้:
func newcustomnameresponder (ชื่อสตริง) นักแสดง Producer {return func () actor.receiver {return & nameresponder {name}
-
-จากนั้นคุณสามารถวางไข่นักแสดงด้วยรหัสต่อไปนี้:
PID: = engine.spawn (Newcustomnameresponder ("Anthony"), "Name-Responder")) E.Spawn (newfoo, "myactorname", นักแสดง. withMaxRestarts (4), นักแสดง. withInboxSize (1024 * 2), actor.witid ("bar"),
-
-ตัวเลือกควรอธิบายตัวเองค่อนข้างดี คุณสามารถตั้งค่าจำนวนการรีสตาร์ทสูงสุดซึ่งบอกเครื่องยนต์ว่านักแสดงที่กำหนดควรรีสตาร์ทกี่ครั้งในกรณีที่มีความตื่นตระหนกขนาดของกล่องจดหมายซึ่งกำหนดขีด จำกัด เกี่ยวกับวิธีการและข้อความที่ไม่ผ่านการประมวลผลกล่องจดหมาย เพื่อบล็อก
นักแสดงที่ไม่มีสถานะสามารถวางไข่เป็นฟังก์ชั่นเพราะมันง่ายและรวดเร็ว
E.spawnfunc (func (c *actor.context) {สวิตช์ผงชูรส
-
}, "foo")นักแสดงสามารถสื่อสารกันผ่านเครือข่ายด้วยแพ็คเกจระยะไกล สิ่งนี้ใช้งานได้เช่นเดียวกับนักแสดงท้องถิ่น แต่ "เหนือสาย" ฮอลลีวูดรองรับการทำให้เป็นอนุกรมด้วย protobuf
Remote.new () ใช้ที่อยู่ฟังและ remote.config struct
คุณจะยกตัวอย่างรีโมทใหม่ด้วยรหัสต่อไปนี้:
tlsconfig: = tlsconfig: & tls.config {ใบรับรอง: [] tls.certificate {ใบรับรอง},
} config: = remote.newconfig (). withtls (tlsconfig) ระยะไกล: = remote.new ("0.0.0.0:2222", config) เครื่องยนต์, err: = actor.newEngine )ดูตัวอย่างนักแสดงระยะไกลและไคลเอนต์แชทและเซิร์ฟเวอร์สำหรับข้อมูลเพิ่มเติม
ในระบบการผลิตในที่สุดก็จะผิดพลาด นักแสดงจะชนเครื่องจะล้มเหลวข้อความจะจบลงในคิว Deadletter คุณสามารถสร้างซอฟต์แวร์ที่สามารถจัดการกับเหตุการณ์เหล่านี้ได้อย่างสง่างามและคาดเดาได้โดยใช้สตรีมเหตุการณ์
EventsTream เป็นนามธรรมที่ทรงพลังที่ช่วยให้คุณสามารถสร้างระบบที่ยืดหยุ่นและเสียบได้โดยไม่ต้องพึ่งพา
สมัครสมาชิกนักแสดงใด ๆ ในรายการต่างๆของระบบระบบ
ออกอากาศกิจกรรมที่กำหนดเองของคุณไปยังสมาชิกทั้งหมด
โปรดทราบว่าเหตุการณ์ที่ไม่ได้รับการจัดการโดยนักแสดงคนใดจะถูกทิ้ง คุณควรมีนักแสดงที่สมัครรับกระแสเหตุการณ์เพื่อรับกิจกรรม เป็นขั้นต่ำที่เปลือยเปล่าคุณจะต้องจัดการ DeadLetterEvent หากฮอลลีวูดล้มเหลวในการส่งข้อความถึงนักแสดงมันจะส่ง DeadLetterEvent ไปยังสตรีมเหตุการณ์
เหตุการณ์ใด ๆ ที่เติมเต็มอินเทอร์เฟซ actor.LogEvent จะถูกบันทึกไปยังเครื่องบันทึกเริ่มต้นด้วยระดับความรุนแรงข้อความและแอตทริบิวต์ของเหตุการณ์ที่กำหนดโดยวิธี actor.LogEvent log()
actor.ActorInitializedEvent นักแสดงได้เริ่มต้น แต่ไม่ได้ประมวล actor.Started message
actor.ActorStartedEvent นักแสดงได้เริ่มต้นขึ้น
actor.ActorStoppedEvent นักแสดงได้หยุดลง
actor.DeadLetterEvent ข้อความไม่ได้ส่งไปยังนักแสดง
actor.ActorRestartedEvent นักแสดงได้เริ่มต้นใหม่หลังจากเกิดความผิดพลาด/ตื่นตระหนก
actor.RemoteUnreachableEvent ส่งข้อความข้ามสายไปยังรีโมทที่ไม่สามารถเข้าถึงได้
cluster.MemberJoinEvent สมาชิกใหม่เข้าร่วมกลุ่ม
cluster.MemberLeaveEvent สมาชิกใหม่ออกจากคลัสเตอร์
cluster.ActivationEvent นักแสดงใหม่เปิดใช้งานบนคลัสเตอร์
cluster.DeactivationEvent นักแสดงจะถูกปิดการใช้งานบนคลัสเตอร์
มีตัวอย่างการตรวจสอบเหตุการณ์ที่แสดงวิธีการใช้สตรีมเหตุการณ์ มันมีนักแสดงสองคนคนหนึ่งไม่เสถียรและจะพังทุกวินาที นักแสดงคนอื่น ๆ จะสมัครสมาชิกสตรีมเหตุการณ์และดูแลเคาน์เตอร์สองสามตัวสำหรับเหตุการณ์ต่าง ๆ เช่นการล่ม ฯลฯ
แอปพลิเคชันจะทำงานเป็นเวลาไม่กี่วินาทีและเป็นพิษต่อนักแสดงที่ไม่มั่นคง จากนั้นจะสอบถามจอภาพด้วยคำขอ ในขณะที่นักแสดงลอยอยู่ในเครื่องยนต์นี่คือวิธีที่คุณโต้ตอบกับพวกเขา หลักจะพิมพ์ผลลัพธ์ของการสืบค้นและแอปพลิเคชันจะออก
เราใช้รูปแบบตัวเลือกฟังก์ชัน ตัวเลือกฟังก์ชั่นทั้งหมดอยู่ในแพ็คเกจนักแสดงและเริ่มต้นชื่อด้วย "EngineOpt" ปัจจุบันตัวเลือกเดียวคือการจัดเตรียมรีโมท ทำโดย
r: = remote.new (remote.config {listenaddr: addr}) เครื่องยนต์, err: = actor.newEngine (นักแสดง. engineoptremote (r))Addr เป็นสตริงที่มีรูปแบบ "โฮสต์: พอร์ต"
คุณสามารถเพิ่มมิดเดิลแวร์ที่กำหนดเองให้กับผู้รับของคุณ สิ่งนี้มีประโยชน์สำหรับการจัดเก็บตัวชี้วัดการบันทึกและการโหลดข้อมูลสำหรับผู้รับของคุณใน actor.Started และ actor.Stopped Stopped
สำหรับตัวอย่างเกี่ยวกับวิธีการใช้มิดเดิลแวร์ที่กำหนดเองลองดูโฟลเดอร์มิดเดิลแวร์ใน ตัวอย่าง
ฮอลลีวูดมีการตัดไม้ในตัว มันจะใช้ตัวบันทึกเริ่มต้นจากแพ็คเกจ log/slog คุณสามารถกำหนดค่าตัวบันทึกตามความชอบของคุณโดยการตั้งค่าตัวบันทึกเริ่มต้นโดยใช้ slog.SetDefaultLogger() สิ่งนี้จะช่วยให้คุณสามารถปรับแต่งระดับบันทึกรูปแบบและเอาต์พุต โปรดดูแพ็คเกจ slog สำหรับข้อมูลเพิ่มเติม
โปรดทราบว่าเหตุการณ์บางอย่างอาจถูกบันทึกไปยังเครื่องบันทึกเริ่มต้นเช่น DeadLetterEvent และ ActorStartedEvent เนื่องจากเหตุการณ์เหล่านี้เติมเต็มอินเตอร์เฟส actor.LogEvent ดูส่วน EventStream ด้านบนสำหรับข้อมูลเพิ่มเติม
make test
เข้าร่วมชุมชน Discord ของเรากับสมาชิกกว่า 2,000 คนสำหรับคำถามและการแชทที่ดี
โครงการนี้ใช้ในการผลิตโดยองค์กร/โครงการต่อไปนี้:
Sensora IoT
ฮอลลีวูดได้รับใบอนุญาตภายใต้ใบอนุญาต MIT