ورهايل ايپليڪيشنن جي بلڊنگ بلاڪ. پهريون طريقو

ورهايل ايپليڪيشنن جي بلڊنگ بلاڪ. پهريون طريقو

آخري ۾ مضمون اسان رد عمل واري فن تعمير جي نظرياتي بنيادن کي جانچيو. اهو وقت آهي ڊيٽا جي وهڪري بابت ڳالهائڻ جو، رد عمل واري Erlang/Elixir سسٽم کي لاڳو ڪرڻ جا طريقا ۽ انهن ۾ پيغام ڏيڻ جا نمونا:

  • درخواست- جواب
  • گذارش- ٽڪرا جواب
  • درخواست سان جواب ڏيو
  • شايع ڪريو- رڪنيت حاصل ڪريو
  • Inverted Publish- رڪنيت حاصل ڪرڻ
  • ڪم جي تقسيم

SOA، MSA ۽ پيغام

SOA، MSA سسٽم آرڪيٽيڪچر آهن جيڪي سسٽم جي تعمير لاء قاعدن کي بيان ڪن ٿا، جڏهن ته پيغام رسائي انهن جي عمل درآمد لاء ابتدائي مهيا ڪري ٿي.

مان هن يا انهي سسٽم جي فن تعمير کي فروغ ڏيڻ نٿو چاهيان. مان هڪ خاص منصوبي ۽ ڪاروبار لاءِ تمام مؤثر ۽ ڪارائتو طريقا استعمال ڪرڻ لاءِ آهيان. اسان جيڪو به نمونو چونڊون ٿا، اهو بهتر آهي ته سسٽم بلاڪ ٺاهي يونڪس-طريقه تي نظر سان: اجزاء گهٽ ۾ گهٽ رابطي سان، انفرادي ادارن لاء ذميوار. API طريقا ادارن سان آسان ترين ممڪن ڪارناما انجام ڏين ٿا.

پيغام آهي، جيئن نالو مشورو ڏئي ٿو، هڪ پيغام بروکر. ان جو بنيادي مقصد پيغام وصول ڪرڻ ۽ موڪلڻ آهي. اهو معلومات موڪلڻ لاءِ انٽرفيس لاءِ ذميوار آهي، سسٽم اندر معلومات جي منتقلي لاءِ منطقي چينلز جي ٺهڻ، روئٽنگ ۽ بيلنس ڪرڻ، انهي سان گڏ سسٽم جي سطح تي غلطي کي سنڀالڻ.
پيغام جيڪو اسان ترقي ڪري رهيا آهيون rabbitmq سان مقابلو ڪرڻ يا تبديل ڪرڻ جي ڪوشش ناهي. ان جي مکيه خاصيتون:

  • ورهائڻ.
    ايڪسچينج پوائنٽس سڀني ڪلستر نوڊس تي ٺاهي سگھجن ٿيون، جيترو ممڪن طور تي ڪوڊ جي ويجهو جيڪو انهن کي استعمال ڪري ٿو.
  • سادگي.
    بوائلر پليٽ ڪوڊ کي گهٽائڻ ۽ استعمال ۾ آسانيءَ تي ڌيان ڏيو.
  • بهتر ڪارڪردگي.
    اسان rabbitmq جي ڪارڪردگي کي ورجائڻ جي ڪوشش نه ڪري رهيا آهيون، پر صرف آرڪيٽيڪچرل ۽ ٽرانسپورٽ پرت کي نمايان ڪريون ٿا، جنهن کي اسان OTP ۾ مناسب طور تي ممڪن طور تي، گھٽ ۾ گھٽ خرچن کي وڌايو.
  • لچڪدار.
    هر خدمت ڪيترن ئي مٽاسٽا ٽيمپليٽس کي گڏ ڪري سگهي ٿي.
  • ڊيزائن طرفان استحڪام.
  • اسڪاليبلٽي.
    ايپليڪيشن سان پيغام وڌندو آهي. جيئن لوڊ وڌائي ٿو، توهان مٽائي پوائنٽن کي انفرادي مشين ڏانهن منتقل ڪري سگهو ٿا.

تبصرو. ڪوڊ آرگنائيزيشن جي لحاظ کان، ميٽا پروجيڪٽ پيچيده Erlang/Elixir سسٽم لاءِ مناسب آهن. سڀ پروجيڪٽ ڪوڊ هڪ مخزن ۾ واقع آهي - هڪ ڇت وارو منصوبو. ساڳئي وقت، microservices وڌ ۾ وڌ الڳ ٿي ويا آهن ۽ سادي آپريشن انجام ڏين ٿيون جيڪي هڪ الڳ اداري لاءِ ذميوار آهن. هن طريقي سان، سڄي سسٽم جي API کي برقرار رکڻ آسان آهي، تبديليون ڪرڻ آسان آهي، يونٽ ۽ انضمام ٽيسٽ لکڻ لاء آسان آهي.

سسٽم جا حصا سڌو سنئون يا بروکر جي ذريعي. هڪ پيغام رسائيندڙ نقطه نظر کان، هر خدمت ۾ ڪيترائي زندگي جا مرحلا آهن:

  • سروس جي شروعات.
    هن مرحلي تي، عمل کي عمل ڪرڻ جي خدمت ۽ ان جي انحصار کي ترتيب ۽ شروع ڪيو ويو آهي.
  • تبادلي واري نقطي ٺاهڻ.
    خدمت استعمال ڪري سگھي ٿو جامد مٽا سٽا واري پوائنٽ جو بيان ڪيل نوڊ جي ترتيب ۾، يا متحرڪ طور تي ايڪسچينج پوائنٽ ٺاهي سگھي ٿو.
  • سروس رجسٽريشن.
    خدمت لاءِ درخواستن جي خدمت ڪرڻ لاءِ، ان کي مٽائڻ واري پوائنٽ تي رجسٽر ٿيڻ گھرجي.
  • عام ڪم ڪار.
    خدمت مفيد ڪم پيدا ڪري ٿي.
  • بند ڪريو.
    اتي 2 قسم جا بندش ممڪن آھن: عام ۽ ايمرجنسي. عام آپريشن دوران، خدمت مٽا سٽا واري نقطي کان ڌار ٿي وئي آهي ۽ بند ٿي ويندي آهي. ايمرجنسي حالتن ۾، پيغام پهچائڻ هڪ ناڪامي اسڪرپٽ تي عمل ڪري ٿو.

اهو ڪافي پيچيده ڏسڻ ۾ اچي ٿو، پر ڪوڊ تمام خوفناڪ نه آهي. تبصرن سان ڪوڊ جا مثال ٿوري دير بعد ٽيمپليٽ جي تجزيي ۾ ڏنا ويندا.

ايڪسچينج

ايڪسچينج پوائنٽ هڪ پيغام رسائيندڙ عمل آهي جيڪو ميسيجنگ ٽيمپليٽ جي اجزاء سان رابطي جي منطق کي لاڳو ڪري ٿو. هيٺ ڏنل پيش ڪيل سڀني مثالن ۾، اجزاء مٽا سٽا جي پوائنٽن ذريعي لهه وچڙ ۾ اچن ٿا، جنهن جو ميلاپ پيغام رسائي ٿو.

پيغام مٽائڻ جا نمونا (MEPs)

عالمي طور تي، مٽاسٽا جي نمونن کي ٻن طرفن ۽ ھڪڙي طرفي ۾ ورهائي سگھجي ٿو. اڳوڻو مطلب هڪ ايندڙ پيغام جو جواب ڏئي ٿو، بعد ۾ نه. ڪلائنٽ-سرور آرڪيٽيڪچر ۾ ٻه طرفي نموني جو هڪ شاندار مثال درخواست-جواب وارو نمونو آهي. اچو ته ٽيمپليٽ ۽ ان جي تبديلين کي ڏسو.

درخواست-جواب يا RPC

RPC استعمال ڪيو ويندو آهي جڏهن اسان کي ڪنهن ٻئي عمل کان جواب حاصل ڪرڻ جي ضرورت آهي. اهو عمل شايد ساڳئي نوڊ تي هلندڙ هجي يا مختلف براعظم تي واقع هجي. هيٺ ڏنل پيغام ذريعي ڪلائنٽ ۽ سرور جي وچ ۾ رابطي جو هڪ خاڪو آهي.

ورهايل ايپليڪيشنن جي بلڊنگ بلاڪ. پهريون طريقو

جيئن ته پيغام مڪمل طور تي هم وقت سازي آهي، ڪلائنٽ جي بدلي کي 2 مرحلن ۾ ورهايو ويو آهي:

  1. درخواست موڪلڻ

    messaging:request(Exchange, ResponseMatchingTag, RequestDefinition, HandlerProcess).

    مٽا سٽا - مٽا سٽا واري نقطي جو منفرد نالو
    ResponseMatching Tag - جواب جي پروسيسنگ لاءِ مقامي ليبل. مثال طور، موڪلڻ جي صورت ۾ ڪيترن ئي هڪجهڙائي درخواستن جو تعلق مختلف استعمال ڪندڙن سان آهي.
    درخواست جي تعريف - جسم جي درخواست
    سنڀالڻ وارو عمل - سنڀاليندڙ جو PID. اهو عمل سرور کان جواب حاصل ڪندو.

  2. جواب جي پروسيسنگ

    handle_info(#'$msg'{exchange = EXCHANGE, tag = ResponseMatchingTag,message = ResponsePayload}, State)

    جوابي لوڊ - سرور جو جواب.

سرور لاء، پروسيس پڻ 2 مرحلن تي مشتمل آهي:

  1. تبادلي واري نقطي جي شروعات
  2. وصول ٿيل درخواستن جي پروسيسنگ

اچو ته هن ٽيمپليٽ کي ڪوڊ سان بيان ڪريون. اچو ته اسان کي هڪ سادي خدمت لاڳو ڪرڻ جي ضرورت آهي جيڪا هڪ واحد صحيح وقت جو طريقو مهيا ڪري.

سرور ڪوڊ

اچو ته api.hrl ۾ سروس API جي وضاحت ڪريون:

%% =====================================================
%%  entities
%% =====================================================
-record(time, {
  unixtime :: non_neg_integer(),
  datetime :: binary()
}).

-record(time_error, {
  code :: non_neg_integer(),
  error :: term()
}).

%% =====================================================
%%  methods
%% =====================================================
-record(time_req, {
  opts :: term()
}).
-record(time_resp, {
  result :: #time{} | #time_error{}
}).

اچو ته بيان ڪريون سروس ڪنٽرولر کي time_controller.erl ۾

%% В примере показан только значимый код. Вставив его в шаблон gen_server можно получить рабочий сервис.

%% инициализация gen_server
init(Args) ->
  %% подключение к точке обмена
  messaging:monitor_exchange(req_resp, ?EXCHANGE, default, self())
  {ok, #{}}.

%% обработка события потери связи с точкой обмена. Это же событие приходит, если точка обмена еще не запустилась.
handle_info(#exchange_die{exchange = ?EXCHANGE}, State) ->
  erlang:send(self(), monitor_exchange),
  {noreply, State};

%% обработка API
handle_info(#time_req{opts = _Opts}, State) ->
  messaging:response_once(Client, #time_resp{
result = #time{ unixtime = time_utils:unixtime(now()), datetime = time_utils:iso8601_fmt(now())}
  });
  {noreply, State};

%% завершение работы gen_server
terminate(_Reason, _State) ->
  messaging:demonitor_exchange(req_resp, ?EXCHANGE, default, self()),
  ok.

ڪلائنٽ ڪوڊ

خدمت لاءِ درخواست موڪلڻ لاءِ، توھان ڪال ڪري سگھوٿا ميسيجنگ درخواست API کي ڪلائنٽ ۾ ڪٿي به:

case messaging:request(?EXCHANGE, tag, #time_req{opts = #{}}, self()) of
    ok -> ok;
    _ -> %% repeat or fail logic
end

ورهايل سسٽم ۾، اجزاء جي ترتيب بلڪل مختلف ٿي سگهي ٿي ۽ درخواست جي وقت، پيغام اڃا تائين شروع نه ٿي سگھي، يا خدمت سنڀاليندڙ درخواست جي خدمت ڪرڻ لاء تيار نه ٿيندو. تنهن ڪري، اسان کي پيغام جي جواب جي جانچ ڪرڻ ۽ ناڪامي ڪيس کي سنڀالڻ جي ضرورت آهي.
ڪامياب موڪلڻ کان پوء، ڪلائنٽ هڪ جواب يا غلطي وصول ڪندي خدمت کان.
اچو ته ٻنهي ڪيسن کي handle_info ۾ سنڀالون:

handle_info(#'$msg'{exchange = ?EXCHANGE, tag = tag, message = #time_resp{result = #time{unixtime = Utime}}}, State) ->
  ?debugVal(Utime),
  {noreply, State};

handle_info(#'$msg'{exchange = ?EXCHANGE, tag = tag, message = #time_resp{result = #time_error{code = ErrorCode}}}, State) ->
  ?debugVal({error, ErrorCode}),
  {noreply, State};

گذارش- ٽڪرا جواب

اھو بھتر آھي ته وڏا پيغام موڪلڻ کان پاسو ڪجي. سڄي سسٽم جي جوابي ۽ مستحڪم آپريشن هن تي منحصر آهي. جيڪڏهن هڪ سوال جو جواب گهڻو يادگيري وٺي ٿو، پوء ان کي حصن ۾ ورهائڻ لازمي آهي.

ورهايل ايپليڪيشنن جي بلڊنگ بلاڪ. پهريون طريقو

اچو ته توهان کي اهڙن ڪيسن جا ٻه مثال ڏيان:

  • اجزاء بائنري ڊيٽا مٽائي، جهڙوڪ فائلون. جواب کي ننڍن حصن ۾ ٽوڙڻ ۾ مدد ڪري ٿي توهان کي ڪنهن به سائيز جي فائلن سان موثر طريقي سان ڪم ڪرڻ ۽ ميموري اوور فلوز کان بچڻ.
  • لسٽنگ. مثال طور، اسان کي ڊيٽابيس ۾ هڪ وڏي ٽيبل مان سڀئي رڪارڊ چونڊڻ ۽ انهن کي ٻئي جزو ڏانهن منتقل ڪرڻ جي ضرورت آهي.

آئون انهن جوابن کي لوڪوموٽو سڏين ٿا. ڪنهن به صورت ۾، 1024 MB جا 1 پيغام 1 GB جي هڪ پيغام کان بهتر آهن.

Erlang ڪلستر ۾، اسان هڪ اضافي فائدو حاصل ڪندا آهيون - ايڪسچينج پوائنٽ ۽ نيٽ ورڪ تي لوڊ گھٽائڻ، ڇو ته جواب فوري طور تي وصول ڪندڙ ڏانهن موڪليا ويا آهن، ايڪسچينج پوائنٽ کي ختم ڪندي.

درخواست سان جواب ڏيو

هي آر پي سي نموني جي هڪ غير معمولي تبديلي آهي جيڪا ڊائلاگ سسٽم جي تعمير لاء.

ورهايل ايپليڪيشنن جي بلڊنگ بلاڪ. پهريون طريقو

شايع ڪريو-سبسڪرائب ڪريو (ڊيٽا ورهائڻ جو وڻ)

ايونٽ هلائيندڙ سسٽم انهن کي صارفين تائين پهچائي ٿو جيئن ئي ڊيٽا تيار ٿئي ٿي. اهڙيء طرح، سسٽم هڪ پل يا پول ماڊل جي ڀيٽ ۾ هڪ ڌڪ واري ماڊل ڏانهن وڌيڪ فخر آهي. هي خصوصيت توهان کي ڊيٽا جي مسلسل درخواست ۽ انتظار ڪندي وسيلن کي ضايع ڪرڻ کان بچڻ جي اجازت ڏئي ٿي.
انگ اکر ڏيکاري ٿو هڪ پيغام کي ورهائڻ جي عمل کي صارفين کي هڪ مخصوص موضوع جي رڪنيت حاصل ڪرڻ لاء.

ورهايل ايپليڪيشنن جي بلڊنگ بلاڪ. پهريون طريقو

هن نموني کي استعمال ڪرڻ جا شاندار مثال رياست جي تقسيم آهن: ڪمپيوٽر جي راندين ۾ راند جي دنيا، ايڪسچينج تي مارڪيٽ ڊيٽا، ڊيٽا فيڊ ۾ مفيد معلومات.

اچو ته سبسڪرائبر ڪوڊ ڏسو:

init(_Args) ->
  %% подписываемся на обменник, ключ = key
  messaging:subscribe(?SUBSCRIPTION, key, tag, self()),
  {ok, #{}}.

handle_info(#exchange_die{exchange = ?SUBSCRIPTION}, State) ->
  %% если точка обмена недоступна, то пытаемся переподключиться
  messaging:subscribe(?SUBSCRIPTION, key, tag, self()),
  {noreply, State};

%% обрабатываем пришедшие сообщения
handle_info(#'$msg'{exchange = ?SUBSCRIPTION, message = Msg}, State) ->
  ?debugVal(Msg),
  {noreply, State};

%% при остановке потребителя - отключаемся от точки обмена
terminate(_Reason, _State) ->
  messaging:unsubscribe(?SUBSCRIPTION, key, tag, self()),
  ok.

ذريعو ڪنهن به مناسب جڳهه تي پيغام شايع ڪرڻ لاء فنڪشن کي سڏي سگهي ٿو:

messaging:publish_message(Exchange, Key, Message).

مٽا سٽا - مٽا سٽا جو نالو،
چاٻي - رستي جي چاٻي
پيغام - پيل لوڊ

Inverted Publish- رڪنيت حاصل ڪرڻ

ورهايل ايپليڪيشنن جي بلڊنگ بلاڪ. پهريون طريقو

پب-سب کي وڌائڻ سان، توھان حاصل ڪري سگھو ٿا ھڪڙو نمونو لاگنگ لاءِ آسان. ذريعن ۽ صارفين جو سيٽ مڪمل طور تي مختلف ٿي سگهي ٿو. انگ اکر ڏيکاري ٿو هڪ ڪيس هڪ صارف ۽ گهڻن ذريعن سان.

ڪم جي ورڇ جو نمونو

تقريبن هر منصوبي ۾ شامل آهي ملتوي پروسيسنگ ڪم، جهڙوڪ رپورٽون ٺاهڻ، اطلاعن کي پهچائڻ، ۽ ٽئين پارٽي سسٽم مان ڊيٽا حاصل ڪرڻ. انهن ڪمن کي انجام ڏيڻ واري سسٽم جي ذريعي آساني سان هٿي وٺندڙن کي شامل ڪري سگهجي ٿو. اهو سڀ ڪجهه اسان لاءِ رهي ٿو پروسيسرز جو ڪلستر ٺاهڻ ۽ انهن جي وچ ۾ ڪمن کي برابر ورهائڻ.

اچو ته انهن حالتن تي نظر وجهون جيڪي 3 هينڊلر جو مثال استعمال ڪندي پيدا ٿين ٿيون. ايستائين جو ڪم ورهائڻ واري مرحلي ۾ به ورهاست جي منصفاڻي ۽ هينڊلر جي اوور فلو جو سوال اڀري ٿو. گول رابن جي ورڇ منصفاڻي لاءِ ذميوار هوندي، ۽ هينڊلرن جي اوور فلو جي صورتحال کان بچڻ لاءِ، اسان هڪ پابندي متعارف ڪرائينداسين prefetch_limit. عارضي حالتن ۾ prefetch_limit ھڪڙي ھينڊلر کي سڀني ڪمن کي حاصل ڪرڻ کان روڪيندو.

پيغام ڏيڻ قطار ۽ پروسيسنگ جي ترجيح کي منظم ڪري ٿو. پروسيسر ڪم وصول ڪن ٿا جيئن اهي پهچي وڃن. ڪم ڪاميابي سان مڪمل يا ناڪام ٿي سگھي ٿو:

  • messaging:ack(Tack) - سڏيو ويندو آهي جيڪڏهن پيغام ڪاميابي سان عمل ڪيو وڃي
  • messaging:nack(Tack) - سڀني هنگامي حالتن ۾ سڏيو وڃي ٿو. هڪ دفعو ڪم واپس اچي ويو آهي، پيغام رسائي ان کي ٻئي هينڊلر ڏانهن منتقل ڪندو.

ورهايل ايپليڪيشنن جي بلڊنگ بلاڪ. پهريون طريقو

فرض ڪريو ته ٽن ڪمن جي پروسيسنگ دوران هڪ پيچيده ناڪامي ٿي وئي: پروسيسر 1، ٽاسڪ حاصل ڪرڻ کان پوءِ، مٽا سٽا واري نقطي تي ڪنهن به شيءِ جي رپورٽ ڪرڻ جي وقت کان سواءِ تباهه ٿي ويو. انهي صورت ۾، ايڪسچينج پوائنٽ ڪم کي ٻئي هينڊلر ڏانهن منتقل ڪندو جڏهن ack ٽائيم ختم ٿيڻ کان پوء. ڪجهه سببن لاء، هينڊلر 3 ڪم کي ڇڏي ڏنو ۽ نيڪ موڪليو؛ نتيجي طور، ڪم پڻ هڪ ٻئي هينڊلر ڏانهن منتقل ڪيو ويو جيڪو ڪاميابي سان مڪمل ڪيو.

شروعاتي تتري

اسان ورهايل سسٽم جي بنيادي بلڊنگ بلاڪ کي ڍڪي ڇڏيو آهي ۽ Erlang/Elixir ۾ انهن جي استعمال جي بنيادي ڄاڻ حاصل ڪئي آهي.

بنيادي نمونن کي گڏ ڪرڻ سان، توهان اڀرندڙ مسئلا حل ڪرڻ لاءِ پيچيده نمونا ٺاهي سگهو ٿا.

سيريز جي آخري حصي ۾، اسان خدمتن کي منظم ڪرڻ، روٽنگ ۽ توازن جي عام مسئلن تي نظر ڪنداسين، ۽ پڻ اسڪالبلٽي جي عملي پاسي ۽ سسٽم جي غلطي رواداري بابت ڳالهائينداسين.

ٻئي ڀاڱي جي پڄاڻي.

تصوير ماريس ڪرسٽنسن
Websequencediagrams.com استعمال ڪندي تيار ڪيل تصويرون

جو ذريعو: www.habr.com

تبصرو شامل ڪريو