فرآیند اکسیر، چیست؟ چگونه کار می کند؟ فرآیند مرتبط و نظارت شده

یکی از دشواریهایی که از زبانهای دیگر به اکسیر میروند، فرآیند است و افراد معمولاً برای استفاده از کتابخانه آن را نادیده میگیرند.
در واقع، فرآیند اکسیر چیز بسیار قدرتمندی است، اگر با سیستم مقیاس بزرگ وارد کار شویم، باید کارهای زیادی را با فرآیند انجام دهیم.
من مدت زیادی با Erlang (همچنین Golang) کار کرده ام و روند یکی از جالب ترین چیزها برای من است.
از نظر من فرآیند اکسیر 3 نکته مهم برای مراقبت دارد.
- فرآیند کد ایزوله است (مانند یک جزیره) و ارسال/دریافت پیام راهی برای تعامل با دنیای خارج است. اگر فرآیند از بین برود، بر سایر فرآیندها تأثیر نمی گذارد (به جز یک مورد فرآیند مرتبط است).
- فرآیند را می توان برای دانستن نحوه خروج از فرآیند (:normal, :error,..) مانیتور کرد.
- فرآیند را می توان پیوند داد (با هم گروه بندی کرد) و تمام فرآیندهای مرتبط با فرآیند ناموفق از بین خواهند رفت (به جز این که فرآیند trap_exit را به true تبدیل کند).
از 3 مورد بالا، ما میتوانیم چیزهای زیادی را با فرآیندهایی بسازیم: ایجاد یک مدل سرپرست/کارگر سفارشی، ساختن فرآیندهای استخری ساده برای به اشتراک گذاشتن حجم کار، ایجاد یک پردازش داده زنجیرهای، و…
اکنون برای درک مفهوم فرآیند اکسیر یکی یکی مرور می کنیم.
کد ایزوله در حال پردازش است
اگر نحوه عملکرد آن را درک کنیم، کار در اکسیر بسیار آسان تر است. از به اشتراک گذاری متغیرها (متغیرهای قابل تغییر) کمی احساس سختی برای آوردن الگوریتم ها به نظر می رسد (همچنین حلقه واقعی / در حالی که برای اکسیر). فقط تصور کنید که در یک جزیره تنها زندگی می کنید و فقط با یک راه ارتباط با بیرون از طریق ارسال پیام به یک بطری، اقیانوس به هر چیز دیگری اهمیت می دهد.
(در واقع، ما می توانیم حالت را به اشتراک بگذاریم :ets
، :persistent_term
یا پایگاه داده دیگری).
هنگامی که می خواهید پیامی ارسال کنید، پیامی را با آدرس به بطری قرار می دهید، سپس به ساحل بروید و بطری را به اقیانوس پرتاب کنید. با کمی زمان برای دوست خود پیامی دریافت خواهید کرد.
و هنگامی که می خواهید از جزایر دیگر پیامی دریافت کنید، به ساحل می روید و می بینید که آیا بطری در ساحل وجود دارد، بررسی کنید و سپس فقط پیامی را دریافت کنید که می خواهید دریافت کنید.
برای اقداماتی مانند سرور/مشتری، ما پیامی ارسال می کنیم و با گذشت زمان (یا برای همیشه) در ساحل می مانیم تا نتیجه بگیریم.
برای ارسال کد استفاده می کنیم send/2
تابع:
send(pid, {:get, :user_info, self()})
برای دریافت پیام (از قبل در صندوق پستی یا منتظر پیام جدید) استفاده می کنیم receive do
نحو درست مثل case do
:
receive do
{:user_info, data} ->
IO.puts "user data: #{inspect data}"
other ->
IO.puts "other data: #{inspect other}"
end
می توانید قرار دهید receive do
به یک تابع برای رفتن دوباره به حلقه اگر می خواهید مانند یک سرور پردازش کنید.
در صورتی که پیام با هیچ الگوی مطابقت نداشته باشد receive do
آن را تا در صندوق پستی فرآیند باقی بماند. میتوانید در آینده آن را دریافت کنید، اما باید مطمئن شوید که پیامهای ناهمسان زیادی را برای پردازش فشار ندهید زیرا میتواند یک OMM ایجاد کند.
فرآیندهای پیوند
این ویژگی ویژگی بسیار قدرتمند اکسیر است. ما می توانیم گروهی از فرآیندها را برای انجام وظایف گروهی یا زنجیره ای از وظایف کنترل کنیم.
مثال:
فرآیند A –linked–> B –linked–> C
IO.puts "I'm A"
fun = fn ->
receive do
:shutdown ->
IO.puts "exited"
{:ping, from} ->
IO.puts "got a ping from #{inspect from}"
send(from, :pong)
message ->
IO.puts "Got a message: #{inspect message}"
end
end
# spawn and link process B
spawn_link(fn ->
IO.puts "I'm B"
spawn_link(fn ->
IO.puts "I'm C"
fun.()
end)
fun.()
end)
از این کد، فرآیندها را در وظیفه زنجیره ای پیوند می دهیم. اگر هر فرآیندی با شکست مواجه شود، سایر فرآیندها نیز از بین خواهند رفت. ما نیازی به مراقبت برای تشخیص وظیفه دم/تمیز نداریم.
همه ما گروهی مانند:
رهبر فرآیند –linked–> worker1, worker2, …, workerN
و هر فرآیندی با شکست مواجه شود، تمام فرآیندهای دیگر به دنبال آن خواهند مرد.
trap_exit
در صورتی که نمی خواهیم فرآیندی از بین برود و به دنبال روند شکست خورده خود برویم، میتوانیم آن را تغییر دهیم trap_exit
روشن است (پرچم را روی true تنظیم کنید) و فرآیند یک پیام ناموفق دریافت می کند به جای اینکه به دنبال فرآیند ناموفق باشد.
Process.flag(:trap_exit, true)
هنگامی که فرآیند شما با شکست مواجه شد، پیامی مانند زیر دریافت خواهد کرد.
{:EXIT, #PID<0.192.0>, {%RuntimeError{message: "#PID<0.192.0>, raise a RuntimeError :D"}, []}}
نظارت بر فرآیند
در موارد دیگر، ما فقط میخواهیم از این که چرا فرآیند دیگر از کار افتاده است، میتوانیم استفاده کنیم monitor
روند.
عملکردی برای فرآیند مانیتور داشته باشید: spawn_monitor
، Process.monitor
برای ساخت یک مانیتور به فرآیند دیگر.
برای حذف مانیتور می توانیم استفاده کنیم Process.demonitor
.
اگر فرآیند نظارت شده با شکست مواجه شود، یک مانیتور فرآیند ساختن آن فرآیند پیامی مانند:
{:DOWN, #Reference<...>, :process, #PID<...>, reason}
از فرآیند پیوند/مانیتور می توانیم چیزهای زیادی برای سیستم خود بسازیم و می توانیم خوب بخوابیم! ما می توانیم یک سرپرست خاص، کارگران استخر خود،…
در این زمان من فقط یک توضیح اساسی دارم، در آینده جزئیات بیشتری را توضیح خواهم داد.
من LiveBook را برای مشابه آن دارم که می توانید یک نسخه نمایشی محتوا + منبع را در مخزن Github ما بررسی کنید