OTP تعني منصة Open Telecom . لقد حدث ذلك تاريخياً ، لأنه تم إنشاء النظام لتلبية الاحتياجات ولأموال إريكسون . ولكن ، من حيث المبدأ ، يحتوي هذا الاسم على العديد من الدلالات المتعلقة بوظائفه مثل تفاح بهواتف بجودة متوسطة.
السمة المميزة الرئيسية لمكتب المدعي العام ، وفقا للمؤلفين ، هو التسامح مع الخطأ. لا تعدد مؤشرات الترابط ، وليس نموذجًا فاعلًا ، ولا ميزات غنية لمطابقة الأنماط ، ولا حتى التجميع الشفاف وليس ترقيات الكود الساخن. خطأ التسامح.
الجهاز الظاهري Erlang المثبت على السطح بسيط للغاية في الهيكل: هناك مجموعة من "العمليات" (وليس عمليات النظام ، وعمليات Erlang) مع ذاكرة معزولة يمكنها تبادل الرسائل. هذا كل شيء. إليكم ما قاله جو أرمسترونغ حول هذا:
في مدونتي ، قلت إن العمليات يجب أن تتصرف إلى حد كبير مثل الأشخاص. الناس لديهم ذكريات خاصة وتبادل البيانات عن طريق تمرير الرسائل.
- لماذا لا أحب الذاكرة المشتركة
المراسلة داخل OTP بسيطة للغاية: تقوم إحدى العمليات بإرسال رسالة إلى أخرى (أو مجموعة من العمليات الأخرى) ، بشكل متزامن أو غير متزامن. لكن لهذا عليك أن تعرف من ترسل هذه الرسائل. وهذا هو ، المرسل هو مدير الصرف. ولكن ماذا لو كنا نريد فقط إرسال البث وتمكين جميع العمليات المهتمة من الاشتراك في هذه الرسالة؟
نعم ، هذه عبارة عن PubSub عادي ، لكن خارج نطاق التطبيق في OTP ، لم يتم تنفيذها. حسنًا ، لا يهم ، لدينا كل الطوب في ساعة واحدة لنركعها. لنبدأ.
خيارات التنفيذ
في الأساس ، يشتمل Elixir على وحدة نمطية Registry
يمكن استخدامها كسقالة لحانة pubsub . رمز homespun قليلاً ، وإلقاء نظرة أنيق على جميع المشاركين (مشرف للجميع) ، ولقد انتهيت. المشكلة الوحيدة هي أن Registry
محلي ولا يعرف كيفية التجميع. وهذا هو ، في بيئة موزعة (العقد الموزعة) هذا الجمال لن يعمل.
Phoenix.PubSub
لنا ، هناك تطبيق موزع لـ Phoenix.PubSub
، والذي يأتي مع تطبيقين جاهزين: Phoenix.PubSub.PG2
و Phoenix.PubSub.Redis
. حسنًا ، تعتبر PG2
رابطًا إضافيًا في PG2
، ولكن PG2
، التي تعمل على رأس مجموعات Erlang لعمليات pg2
، هي كذلك. أيضا ، ومع ذلك ، دون boilerplate لن تفعل.
لذلك ، لدينا كل شيء لتأسيس اشتراكات PubSub مريحة في طلبنا. هل حان الوقت لفتح محرر نصوص؟ "ليس حقا" لا أحب تكرار الشفرة من مشروع إلى آخر ، وكل شيء يمكنني عزله في مكتبة معزول لإعادة استخدامه.
Envío
وهكذا ولدت حزمة Envío
. بما أن الثرثرة ، كما تعلم ، لا يستحق فلساً واحداً ، فسنبدأ مع أمثلة الاستخدام.
النشرة المحلية → Registry
defmodule MyApp.Sub do use Envio.Subscriber, channels: [{MyApp.Pub, :main}] def handle_envio(message, state) do
هذا ، بشكل عام ، هو كل شيء. يبقى MyApp.Sub
إلى شجرة المشرف الخاصة بنا ، وستبدأ هذه العملية في تلقي جميع الرسائل المرسلة باستخدام وظائف من MyApp.Pub
، والتي أيضًا غير محمّلة برمز.
defmodule MyApp.Pub do use Envio.Publisher, channel: :main def publish(channel, what), do: broadcast(channel, what) def publish(what), do: broadcast(what)
النشرة الموزعة → PG2
بالنسبة للأنظمة الموزعة التي تتكون من العديد من العقد ، لن تعمل هذه الطريقة. نحن بحاجة إلى أن نكون قادرين على الاشتراك في رسائل من العقد الأخرى ، Registry
ليس مساعدًا هنا. ولكن هناك PG2
الذي ينفذ نفس behaviour
.
defmodule Pg2Sucker do use Envio.Subscriber, channels: ["main"], manager: :phoenix_pub_sub def handle_envio(message, state) do {:noreply, state} = super(message, state) IO.inspect({message, state}, label: "Received") {:noreply, state} end end
الاختلاف الوحيد من الكود المستقل أعلاه هو المعلمة manager: :phoenix_pub_sub
، والتي use Envio.Subscriber
( use Envio.Publisher
) لإنشاء وحدة نمطية تستند إلى :pg2
بدلاً من Registry
المحلي. الآن الرسائل المرسلة باستخدام هذا Publisher
ستكون متاحة على جميع العقد في الكتلة.
تطبيق
Envío
يدعم ما يسمى الخلفية . يأتي Envio.Slack
مع Envio.Slack
، والذي يتيح لك تبسيط إرسال الرسائل إلى Slack
. كل ما هو مطلوب من التطبيق - إرسال رسالة إلى القناة التي تم تكوينها في config/prod.exs
- سوف يقوم config/prod.exs
Envío
. هنا مثال التكوين:
config :envio, :backends, %{ Envio.Slack => %{ {MyApp.Pub, :slack} => [ hook_url: {:system, "SLACK_ENVIO_HOOK_URL"} ] } }
الآن سيتم تسليم جميع الرسائل المرسلة عن طريق الاتصال بـ MyApp.Pub.publish(:slack, %{foo: :bar})
إلى القناة المقابلة في Slack ، مهيأة بشكل جميل. من أجل إيقاف إرسال الرسائل إلى Slack ، ما Envio.Slack
سوى إيقاف عملية Envio.Slack
. يمكن العثور على مزيد من الأمثلة (على سبيل المثال ، سجل في IO
) في الاختبارات.
لماذا أنا المصلوب ، حاول ذلك بنفسك.
def deps do [ {:envio, "~> 0.8"} ] end
التواصل الجيد!