Hollywood هي عبارة عن محرك ممثل سريع فائق لتطبيقات السرعة والتطبيقات المنخفضة للوصول. فكر في خوادم الألعاب ، وسطاء الإعلان ، والمحركات التجارية ، وما إلى ذلك ... يمكنه التعامل مع 10 ملايين رسالة في أقل من ثانية واحدة .
نموذج الممثل هو نموذج حسابي يستخدم لبناء أنظمة متزامنة للغاية وموزعة. تم تقديمه من قبل كارل هيويت في عام 1973 كوسيلة للتعامل مع الأنظمة المعقدة بطريقة أكثر قابلية للتطوير وتتحمل الأخطاء.
في نموذج الممثل ، فإن لبنة البناء الأساسية هي ممثل ، يشار إليه أحيانًا على أنه جهاز استقبال في هوليوود ، وهي وحدة مستقلة من الحساب تتواصل مع الجهات الفاعلة الأخرى من خلال تبادل الرسائل. كل ممثل له حالته وسلوكه الخاص ، ويمكنه التواصل مع الجهات الفاعلة الأخرى فقط عن طريق إرسال الرسائل. يسمح هذا النموذج الذي يمرر الرسائل بنظام لا مركزي للغاية ويتحمل الأخطاء ، حيث يمكن للجهات الفاعلة الاستمرار في العمل بشكل مستقل حتى لو فشل الجهات الفاعلة الأخرى أو تصبح غير متوفرة.
يمكن تنظيم الجهات الفاعلة في التسلسلات الهرمية ، حيث تشرف الجهات الفاعلة ذات المستوى الأعلى وتنسيق الجهات الفاعلة ذات المستوى الأدنى. يسمح ذلك بإنشاء أنظمة معقدة يمكنها التعامل مع الفشل والأخطاء بطريقة رشيقة ويمكن التنبؤ بها.
باستخدام نموذج الممثل في التطبيق الخاص بك ، يمكنك إنشاء أنظمة قابلة للتطوير وتتحمل الأعطال والتي يمكنها التعامل مع عدد كبير من المستخدمين المتزامنين والتفاعلات المعقدة.
تسليم الرسائل المضمون على فشل الممثل (آلية العازلة)
النار والنساء أو الطلب والاستجابة المراسلة ، أو كليهما
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. المثال الكامل متاح في مجلد Hello World. لنبدأ بشكل رئيسي:
Engine ، ERR: = Actor.NewEngine (Actor.Newengineconfig ())
هذا يخلق محرك جديد. المحرك هو جوهر هوليوود. إنها مسؤولة عن تفريغ الجهات الفاعلة وإرسال الرسائل والتعامل مع دورة حياة الممثلين. إذا فشلت هوليوود في إنشاء المحرك ، فسوف يعيد خطأ. للتطوير ، يجب ألا تستخدم لتمرير أي خيارات إلى المحرك حتى تتمكن من تمرير NIL. سننظر في الخيارات لاحقًا.
بعد ذلك سنحتاج إلى إنشاء ممثل. هذه في بعض الأحيان يشار إليها على أنها Receivers بعد الواجهة التي يجب أن تنفذها. دعنا نقوم بإنشاء ممثل جديد يقوم بطباعة رسالة عندما يتلقى رسالة.
PID: = engine.spawn (Newhelloer ، "Hello")
سيؤدي ذلك إلى أن يولد المحرك ممثلًا بالمعرف "Hello". سيتم إنشاء الممثل بواسطة وظيفة المقدمة newHelloer . يجب أن تكون IDS فريدة من نوعها. سوف يعيد مؤشر إلى pid. PID هو معرف العملية. إنه معرف فريد للممثل. في معظم الأوقات ، ستستخدم PID لإرسال الرسائل إلى الممثل. ضد الأنظمة البعيدة ، ستستخدم المعرف لإرسال الرسائل ، ولكن على الأنظمة المحلية ، ستستخدم في الغالب PID.
دعونا نلقي نظرة على وظيفة newHelloer والممثل الذي يعود.
اكتب Helloer struct {} func newhelloer () Actor.Receiver {return & helloer {}
} بسيطة بما فيه الكفاية. تُرجع وظيفة newHelloer ممثلًا جديدًا. الممثل هو بنية تنفذ الممثل. لنلقي نظرة على طريقة Receive .
اكتب Message struct {} func (h *helloer) تلقي (ctx *Actor.Context) {switch msg: = ctx.message (). (type) {case Actor.Initialized: fmt.println ( الممثل. العمل: fmt.println ("Helloer لقد بدأ") ممثل الحالة. fmt.println ("Helloer qued") الحالة *الرسالة: fmt.println ("Hello World" ، msg.data)
}
}يمكنك أن ترى نحدد بنية الرسائل. هذه هي الرسالة التي سنرسلها إلى الممثل لاحقًا. تتولى طريقة الاستلام أيضًا بعض الرسائل الأخرى. يتم إرسال رسائل دورة الحياة هذه بواسطة المحرك إلى الممثل ، وسوف تستخدمها لتهيئة الممثل الخاص بك
يقوم المحرك بتمرير Actor.Context إلى طريقة Receive . يحتوي هذا السياق على الرسالة ، و PID للمرسل وبعض التبعيات الأخرى التي يمكنك استخدامها.
الآن ، دعنا نرسل رسالة إلى الممثل. سنرسل message ، ولكن يمكنك إرسال أي نوع من الرسائل التي تريدها. الشرط الوحيد هو أن يكون الممثل قادرًا على التعامل مع الرسالة. لكي تكون الرسائل قادرة على عبور السلك ، يجب أن تكون قابلة للتسلسل. لكي يكون Protobuf قادرًا على إجراء تسلسل للرسالة ، يجب أن يكون مؤشرًا. يمكن أن تكون الرسائل المحلية من أي نوع.
أخيرًا ، دعنا نرسل رسالة إلى الممثل.
محرك.
هذا سوف يرسل رسالة إلى الممثل. سوف توجه هوليوود الرسالة إلى الممثل الصحيح. سيقوم الممثل بعد ذلك بطباعة رسالة إلى وحدة التحكم.
مجلد الأمثلة هو أفضل مكان للتعلم واستكشاف هوليوود أكثر.
عندما تفرخ ممثلًا ، فستحتاج إلى توفير وظيفة تُرجع ممثلًا جديدًا. نظرًا لأن الممثل يفرخ ، فهناك بعض الخيارات القابلة للضبط التي يمكنك توفيرها.
E.Spawn (Newfoo ، "MyActorname")
في بعض الأحيان ، سترغب في نقل الحجج إلى مُنشئ الممثل. يمكن القيام بذلك باستخدام الإغلاق. هناك مثال على ذلك في مثال الطلب. دعونا نلقي نظرة على الكود.
سيبدو المنشئ الافتراضي مثل هذا:
func newnameresponder () Actor.Receiver {return & nameresponder {name: "noname"}
}لبناء ممثل جديد يحمل اسمًا يمكنك القيام بما يلي:
func newCustomNeMeSponder (name string) Actor.Producer {return func () Actor.Receiver {return & nameresponder {name}
}
}يمكنك بعد ذلك تفرخ الممثل بالرمز التالي:
PID: = engine.spawn (NewCustomNameSponder ("Anthony") ، "Name-ResponderE.Spawn (newfoo ، "myactorname" ، ممثل. withmaxrestarts (4) ، ممثل. ) )
يجب أن تكون الخيارات توضيحية ذاتية. يمكنك تعيين الحد الأقصى لعدد عمليات إعادة التشغيل ، والتي تخبر المحرك بعدد مرات إعادة تشغيل الممثل المعطى في حالة الذعر ، وحجم صندوق الوارد ، والذي يضع حدًا لكيفية ورسائل الوارد غير المجهزة قبل أن تبدأ قبل أن تبدأ لحظر.
يمكن أن تولد الجهات الفاعلة بدون حالة كدالة ، لأنها سريعة وبسيطة.
e.spawnfunc (func (c *Actor.Context) {switch msg: = c.message (). (type) {case Actor.Started:
}
} ، "فو")يمكن للممثلين التواصل مع بعضهم البعض عبر الشبكة مع الحزمة عن بُعد. هذا يعمل مثل الممثلين المحليين ولكن "فوق السلك". هوليوود تدعم التسلسل مع protobuf.
Remote.new () يأخذ عنوان الاستماع و remote.config struct.
ستستند إلى جهاز تحكم عن بعد جديد مع الكود التالي:
tlsconfig: = tlsconfig: & tls.config {الشهادات: [] tls.certificate {cert} ،
} config: = remote.newconfig (). withtls (tlsconfig) عن بعد: = remote.new ("0.0.0.0:2222" ، config) محرك ، err: = Actor.NewEngine (Actor.NewengineConfig (). withRemote (REMOTE) )انظر إلى أمثلة الممثل عن بُعد وعملاء الدردشة والخادم لمزيد من المعلومات.
في نظام الإنتاج سوف يحدث خطأ في النهاية. ستعطل الممثلون ، ستفشل الآلات ، ستنتهي الرسائل في قائمة انتظار Deadletter. يمكنك إنشاء برامج يمكنها التعامل مع هذه الأحداث بطريقة رشيقة يمكن التنبؤ بها باستخدام دفق الحدث.
ActionStream هو تجريد قوي يسمح لك ببناء أنظمة مرنة وقابلة للتوصيل دون تبعيات.
اشترك في أي ممثل في قائمة مختلفة من أحداث النظام
بث أحداثك المخصصة لجميع المشتركين
لاحظ أنه سيتم إسقاط الأحداث التي لم يتم التعامل معها من قبل أي ممثل. يجب أن يكون لديك ممثل مشترك في دفق الحدث من أجل تلقي الأحداث. كحد أدنى ، سترغب في التعامل مع DeadLetterEvent . إذا فشلت هوليوود في إيصال رسالة إلى ممثل ، فسوف ترسل DeadLetterEvent إلى دفق الحدث.
سيتم log() أي حدث يفي بواجهة actor.LogEvent actor.LogEvent
actor.ActorInitializedEvent actor.Started message
actor.ActorStartedEvent
actor.ActorStoppedEvent
actor.DeadLetterEvent
actor.ActorRestartedEvent
actor.RemoteUnreachableEvent ، إرسال رسالة عبر السلك إلى جهاز تحكم عن بعد لا يمكن الوصول إليه.
cluster.MemberJoinEvent ، عضو جديد ينضم إلى الكتلة
cluster.MemberLeaveEvent ، غادر عضو جديد الكتلة
cluster.ActivationEvent ، يتم تنشيط ممثل جديد على الكتلة
cluster.DeactivationEvent ، ممثل يتم إلغاء تنشيطه على الكتلة
هناك مثال مراقبة EventStream الذي يوضح لك كيفية استخدام دفق الحدث. يضم ممثلين ، أحدهما غير مستقر وسيتعطل كل ثانية. تم اشترك الممثل الآخر في تيار الحدث ويحافظ على عدد قليل من العدادات لأحداث مختلفة مثل الحوادث ، إلخ.
سيتم تشغيل التطبيق لبضع ثوان والسم الممثل غير المستقر. بعد ذلك سوف يستفسر الشاشة مع طلب. نظرًا لأن الجهات الفاعلة تطفو داخل المحرك ، فهذه هي الطريقة التي تتفاعل بها معهم. سيقوم الرئيسي بعد ذلك بطباعة نتيجة الاستعلام وسيخرج التطبيق.
نحن نستخدم نمط خيار الوظيفة. جميع خيارات الوظائف موجودة في حزمة الممثل وبدء اسمها باستخدام "Engineopt". حاليا ، الخيار الوحيد هو توفير جهاز تحكم عن بعد. يتم ذلك بواسطة
R: = REMOTE.NEW (REMOTE.CONFIG {annistaddr: addr}) محرك ، err: = ACTOR.NewEngine (ACTOR.ENGINEOPTREMOTE (R))Addr هي سلسلة مع تنسيق "المضيف: المنفذ".
يمكنك إضافة برامج وسيطة مخصصة إلى أجهزة الاستقبال الخاصة بك. يمكن أن يكون هذا مفيدًا لتخزين المقاييس وحفظ البيانات وتحميلها لأجهزة الاستقبال الخاصة بك على actor.Started . started and actor.Stopped .
للحصول على أمثلة حول كيفية تنفيذ البرامج الوسيطة المخصصة ، تحقق من مجلد الوسيطة في الأمثلة
هوليوود لديها بعض في قطع الأشجار. سوف يستخدم المسجل الافتراضي من حزمة log/slog . يمكنك تكوين المسجل حسب رغبتك عن طريق إعداد المسجل الافتراضي باستخدام slog.SetDefaultLogger() . سيسمح لك ذلك بتخصيص مستوى السجل والتنسيق والإخراج. يرجى الاطلاع على حزمة slog لمزيد من المعلومات.
لاحظ أنه قد يتم تسجيل بعض الأحداث إلى المسجل الافتراضي ، مثل DeadLetterEvent و ActorStartedEvent لأن هذه الأحداث تفي بواجهة actor.LogEvent . انظر قسم الأحداث أعلاه لمزيد من المعلومات.
make test
انضم إلى مجتمع Discord مع أكثر من 2000 عضوًا للأسئلة والدردشة الرائعة.
يستخدم هذا المشروع حاليًا في الإنتاج من قبل المؤسسات/المشاريع التالية:
Sensora IOT
هوليوود مرخصة بموجب ترخيص معهد ماساتشوستس للتكنولوجيا.