sadeghhp
sadeghhp
خواندن ۶ دقیقه·۲ سال پیش

اکتور مدل در 10 دقیقه

واقعیت این است که پردازنده ها دیگر از این سریع تر نمی شوند. اتفاقی که افتاده این است که حالا به پردازنده هایی قوی تر با چندین و چند هسته دسترسی داریم.

اگر بخواهیم به تمام قدرت این سخت افزار های دوست داشتنی دسترسی داشته باشیم باید راهی پیدا کنیم. باید کاری کنیم که برنامه ی ما (کد ما) به صورت همزمان به همه هسته های پردازنده دسترسی داشته باشد.

سال هاست که با باگ های غیرقابل ردیابی و توسعه دهنده های افسرده طرفیم که نشان میدهد صرفا استفاده و مدیریت رشته ها (ترد ها) برای رسیدن به تمام توان پردازنده جواب نیست اما جای نگرانی هم نیست! در واقع یک راه حل جایگزین خوب برای این موضوع وجود دارد! اکتور مدل.

اکتور مدل

اکتور مدل در واقع یک مدل مفهومی است برای مواجهه با مسئله پردازش همزمان در توسعه برنامه ها. در این مدل قوانینی برای کامپوننت های سیستم تعریف میشود که چگونه و به چه صورت این اجزا باهم در ارتباط و تعامل باشند و چگونه رفتار کنند. معروف ترین زبانی که بر اساس این مدل طراحی شده erlang است. در این مطلب قصد دارم بیشتر به مدل و عملکرد آن بپردازم و به پیاده سازی ها و کتابخانه های آن کمتر اشاره خواهم کرد.

اکتورها

اکتور ها شهروند های درجه یک این مدل هستند. در واقع اکتور ها اصلی ترین و اساسی ترین اجزای مورد استفاده در اکتور مدل هستند! از اسمش هم پیداست البته.

اکتور ها واحد پردازش اصلی هستند. پردازش چه چیزی ؟ پیام ها. اکتور های قسمتی از سیستم هستند که پیام ها را دریافت کرده و پردازش میکنند.

ایده اصلی خیلی شبیه به برنامه نویسی شی گرا است. یک ابجکت پیام دریافت میکند ( یک متد از آن صدا میشود ) و یک کاری بر اساس پیام دریافت شده انجام میدهد ( بر اساس متدی که صدا شده کاری خاصی انجام میشود )

تفاوت اساسی اینجاست که هر اکتور به صورت کامل از بقیه اکتورها ایزوله است و هیچ حافظه ای را با هم به اشتراک نمیگذارد و جذاب تر اینکه هر اکتوری میتواند یک وضعیت اختصاصی (private state) داشته باشه که هرگز به صورت مستقیم توسط دیگر اکتور ها قابل دسترسی و تغییر نیست.

مورچه ، مورچه نیست

همانطور که یک مورچه معنی واقعی مورچه ها و جمعیت شان را نمی تواند نمایندگی کند ، یک آکتور هم به تنهایی نمیتواند مفهوم اکتور مدل را نمایندگی کند و در واقع تعامل بین اکتور ها هست که به آن ها معنی و ارزش میدهد.

اکتورها در یک سیستم عمل میکنند. در این سیستم هر چیزی یک آکتور است و هر اکتور یک آدرس منحصر به فرد دارد و این باعث میشود که اکتور ها بتوانند به همدیگر از طریق این آدرس پیام ارسال کنند.

اکتور ها صندوق پستی دارند! (Mailbox)

این مطلب خیلی مهم است که بدانیم با اینکه چند اکتور می توانند به صورت همزمان اجرا شوند ولی هر اکتور پیام های دریافتی را به صورت متوالی و به ترتیب پردازش میکند. به این معنی که اگر 3 پیام همزمان به یک اکتور ارسال شود ، اکتور فقط یک پیام را در لحظه اجرا و پردازش میکند و دو پیام بعدی را در لحظات بعدی (هرچند بسیار بسیار کوتاه) پردازش میکند.

اگر بخواهیم این 3 پیام را همزمان پردازش کنیم باید 3 اکتور ایجاد کنیم و به هرکدام یک پیام ارسال کنیم همزمان!

پیام ها به صورت Async به اکتور ارسال می شود ، پس لازم است جایی پیام ها ذخیره شوند تا بتوان آن ها را به ترتیب پردازش کرد. صندوق پستی (mailbox) یک اکتور ، جایی است که پیام ها به صف میشوند.


اکتور ها از طریق ارسال پیام با هم تعامل دارند. پیام هایی که به صورت Async ایجاد و ارسال می شوند. پیام ها در mailbox اکتور منتظر میمانند تا نوبت پردازش آنها فرا برسد.
اکتور ها از طریق ارسال پیام با هم تعامل دارند. پیام هایی که به صورت Async ایجاد و ارسال می شوند. پیام ها در mailbox اکتور منتظر میمانند تا نوبت پردازش آنها فرا برسد.


کاری که اکتور انجام می دهد

وقتی که یک اکتور پیامی را دریافت میکند یکی از این 3 کار را انجام میدهد:

  1. ایجاد اکتور یا اکتور های جدید
  2. ارسال پیام برای دیگر اکتور ها
  3. تصمیم میگیرد با پیام بعدی چه کاری انجام بدهد

دو مورد اول مشخص است که چه کاری انجام میدهند اما مورد سوم جالب تر است.

قبلا اشاره کردم که هر اکتوری میتواند یک وضعیت شخصی (private state) داشته باشد ، تعیین کردن اینکه اکتور با پیام بعدی چه کاری بکند، یعنی اینکه این وضعیت شخصی اکتور به نحوی تغییر کند که مشخص شود برای پیام بعدی چه اتفاقی باید بیفتد و یا ساده تر اینکه چگونه پردازش شود.

فرض کنید یک اکتور داریم که قرار است مانند یک ماشین حساب عمل کند و وضعیت اولیه آن عدد صفر است. وقتی این اکتور پیام (add(1 را دریافت میکند به جای اینکه وضعیت خود را تغییر دهد، تصمیم میگیرد که برای پیام بعدی که دریافت می کند، وضعیت 1 باشد.

تحمل خطا (Fault tolerance)

ارلنگ مبدع فلسفه ی "let it crash" است. ایده ای که پشت این فلسفه بود این است که نمیتوان تمام خطاهایی که ممکن است در سیستم اتفاق بیفتد را پیش بینی کرد و راه حلی برای آنها یافت! چون راهی نیست که بتوان قبل از وقوع تمام آن ها، به آن ها فکر کرد.

کاری که ارلنگ میکند این است که اجازه میدهد crash اتفاق بیفتد به این صورت که این موضوع تحت نظر کسی است که تنها وظیفه اش این است که بداند موقع crash چه کاری باید انجام دهد. مثلا آن قسمت خاص از کد را دوباره انجام دهد تا به وضعیتی پایدار برسد!

چیزی که این را در ارلنگ شدنی کرده چیزی نیست جز اکتور مدل !

هر کدی داخل یک اکتور اجرا می شود و اکتور کاملا ایزوله است. به این معنی که state آن مستقیما توسط اکتور دیگری تغییر نمیکند و تحت تاثیر قرار نمیگیرد. یک ناظر وجود دارد که در واقع آن هم یک اکتور است که هنگامی که اکتور مورد نظارت دچار مشکل و کرش میشود آن را میبیند و از مشکل آن با خبر میشود و در آن هنگام ناظر کاری انجام میدهد.

این قابلیت باعث میشود که بتوان سیستمی ساخت که "خود درمان" (self heal) باشد به این معنی که اگر اکتوری دچار موقعیت خاصی شد و کرش کرد به هر دلیلی ، ناظر آن اکتور میتواند کاری کند که تا آن اکتور دوباره به وضعیت ثابت و پایدار برگردد. استراتژی های مختلفی هم برای این وجود دارد که یکی از معمول ترین آن ها "راه اندازی مجدد" (restart) اکتور به وضعیت ابتدایی آن است.

توزیع (Distribution)

یکی دیگر از جنبه های بسیار جالب اکتور مدل این است که وقتی پیامی ارسال می شود اهمیتی ندارد که اکتور هدف به صورت لوکال اجرا شده یا روی یک نود دیگر در کلاستر! پیام به مخاطب میرسد هر جا که باشد.

اگر اکتور فقط قسمتی از کد است که وظیفه ی آن پردازش پیام های داخل صندوقش است و جواب دادن به آن، دیگر چه اهمیتی دارد که این اکتور کجا و روی چه ماشینی اجرا شده باشد ؟ مادامی که ما میتوانیم پیام را ارسال کنیم و از آن طرف آن را دریافت کنیم همه چیز خوب پیش خواهد رفت.

این موضوع به ما اجازه میدهد تا سیستمی داشته باشیم با چندین ماشین که اگر یکی از ماشین ها را از دست بدهیم به راحتی بتوانیم اکتورها را روی ماشین دیگر اجرا کرده و از آن ها استفاده کنیم.

قدم بعد چیست؟

این مطلب یک نگاه اجمالی به اکتور مدل بود. اما برای استفاده از این مدل و مزایای آن لازم است از زبان هایی که بر اساس این مدل پیاده سازی شده اند مانند Erlang یا Elixir استفاده کنیم یا در زبان های دیگر از کتابخانه هایی که بر اساس آن توسعه داده شده اند استفاده کنیم.

در جاوا و اسکالا کتابخانه Akka وجود دارد که در واقع پیشرو در پیاده سازی این مدل است و کتابخانه Akka.net هم بر اساس آن برای محیط دات نت توسعه داده شده است. همچنین کتابخانه Celluloid برای روبی ارائه شده و همچنین یک پیاده سازی هم توسط مایکروسافت وجود دارد تحت عنوان Orleans که در محیط دات نت قابل استفاده است.

امیدوارم این مطلب شما را با این مفهوم آشنا کرده باشد و برای شما کنجکاوی لازم را ایجاد کرده باشد که به صورت عمیق تر وارد آن شوید و بتوانید برای نیاز های خود از آن استفاده کنید.

http://akka.net/

https://akka.io/

https://dotnet.github.io/orleans/

https://github.com/celluloid/celluloid

https://www.erlang.org/

actor modelakkaakka netnetdotnet
شاید از این پست‌ها خوشتان بیاید