Блокҳои сохтани барномаҳои тақсимшуда. Муносибати аввал

Блокҳои сохтани барномаҳои тақсимшуда. Муносибати аввал

Дар охир мақола Мо асосҳои назариявии меъмории реактивиро баррасӣ кардем. Вақти он расидааст, ки дар бораи ҷараёни маълумот, роҳҳои татбиқи системаҳои реактивии Erlang/Elixir ва шаклҳои паёмнависӣ дар онҳо сӯҳбат кунем:

  • Дархост - ҷавоб
  • Ҷавоби дархостӣ
  • Ҷавоб бо дархост
  • Нашр кардан-обуна шудан
  • Инвертатсия Интишор-обуна
  • Тақсимоти вазифаҳо

SOA, MSA ва паёмнависӣ

SOA, MSA меъмории системаест, ки қоидаҳои сохтани системаҳоро муайян мекунанд, дар ҳоле ки паёмнависӣ барои татбиқи онҳо ибтидоӣ медиҳад.

Ман намехоҳам ин ё он меъмории системаро пешбарӣ кунам. Ман барои истифодаи таҷрибаҳои муассир ва муфид барои лоиҳа ва тиҷорати мушаххас ҳастам. Новобаста аз он ки мо кадом парадигмаро интихоб кунем, беҳтар аст, ки блокҳои системавиро бо таваҷҷӯҳ ба Unix-way эҷод кунем: ҷузъҳои дорои ҳадди ақали пайвастшавӣ, ки барои субъектҳои инфиродӣ масъуланд. Усулҳои API соддатарин амалҳои имконпазирро бо объектҳо иҷро мекунанд.

Паёмнависӣ, тавре ки аз номаш бармеояд, брокери паём аст. Мақсади асосии он қабул ва фиристодани паёмҳо мебошад. Он барои интерфейсҳои ирсоли иттилоот, ташаккули каналҳои мантиқии интиқоли иттилоот дар дохили система, масир ва мувозинат, инчунин коркарди хатогиҳо дар сатҳи система масъул аст.
Паёмнависие, ки мо таҳия карда истодаем, кӯшиши рақобат кардан ё иваз кардани rabbitmq нест. Хусусиятҳои асосии он:

  • Тақсим.
    Нуқтаҳои мубодила метавонанд дар ҳама гиреҳҳои кластерӣ ба қадри имкон ба коде, ки онҳоро истифода мебарад, наздик сохтан мумкин аст.
  • Содда
    Таваҷҷӯҳ ба кам кардани рамзи дегхона ва осонии истифода.
  • Иҷрои беҳтар.
    Мо кӯшиш намекунем, ки функсияи rabbitmq-ро такрор кунем, балки танҳо қабати меъморӣ ва нақлиётиро қайд кунем, ки мо онро ба OTP то ҳадди имкон соддатар карда, хароҷотро кам мекунем.
  • Мушкилот
    Ҳар як хидмат метавонад бисёр қолабҳои мубодиларо муттаҳид кунад.
  • Муқовимат аз рӯи тарҳ.
  • Миқёспазирӣ.
    Паёмнависӣ бо барнома афзоиш меёбад. Дар баробари зиёд шудани сарборӣ, шумо метавонед нуқтаҳои мубодиларо ба мошинҳои алоҳида интиқол диҳед.

Аҳамият диҳед Дар робита ба ташкили код, мета-лоиҳаҳо барои системаҳои мураккаби Erlang/Elixir мувофиқанд. Ҳама рамзи лоиҳа дар як репозиторий ҷойгир аст - лоиҳаи чатр. Дар айни замон, хидматрасониҳои микроэлементҳо ба ҳадди аксар ҷудо карда шудаанд ва амалиётҳои оддиро иҷро мекунанд, ки барои як субъекти алоҳида масъуланд. Бо ин равиш нигоҳ доштани API-и тамоми система осон аст, ворид кардани тағирот осон аст, навиштани воҳидҳо ва санҷишҳои ҳамгироӣ қулай аст.

Ҷузъҳои система мустақиман ё тавассути брокер ҳамкорӣ мекунанд. Аз нуқтаи назари паёмнависӣ, ҳар як хидмат якчанд марҳилаҳои ҳаёт дорад:

  • Оғозсозии хидмат.
    Дар ин марҳила, раванди иҷрои хидмат ва вобастагии он танзим ва оғоз карда мешавад.
  • Эҷоди нуқтаи мубодила.
    Хидмат метавонад нуқтаи мубодилаи статикиро, ки дар конфигуратсияи гиреҳ нишон дода шудааст, истифода барад ё нуқтаҳои мубодилаи динамикӣ эҷод кунад.
  • Бақайдгирии хидмат.
    Барои он ки хидмат ба дархостҳо хидмат расонад, он бояд дар нуқтаи мубодила ба қайд гирифта шавад.
  • Фаъолияти муқаррарӣ.
    Хизматрасонй кори фоиданок ба вучуд меоварад.
  • Анҷоми кор.
    Ду намуди хомӯшкунӣ вуҷуд дорад: муқаррарӣ ва фавқулодда. Ҳангоми кори муқаррарӣ хидмат аз нуқтаи мубодила ҷудо шуда, қатъ мегардад. Дар ҳолатҳои фавқулодда, паёмнависӣ яке аз скриптҳои нокомиро иҷро мекунад.

Ин хеле мураккаб ба назар мерасад, аммо рамз он қадар даҳшатнок нест. Намунаҳои рамзӣ бо шарҳҳо каме дертар ҳангоми таҳлили қолибҳо дода мешаванд.

мубодилаҳои

Нуқтаи мубодила як раванди паёмнависӣ мебошад, ки мантиқи ҳамкорӣ бо ҷузъҳои дохили қолаби паёмнависиро амалӣ мекунад. Дар ҳамаи мисолҳои дар поён овардашуда, ҷузъҳо тавассути нуқтаҳои мубодила, ки омезиши онҳо паёмнависиро ташкил медиҳад, мутақобила мекунанд.

Намунаҳои мубодилаи паёмҳо (MEPs)

Дар саросари ҷаҳон, шаклҳои мубодиларо метавон ба дутарафа ва яктарафа тақсим кард. Аввалин маънои вокуниш ба паёми воридотро дорад, дуюмаш не. Намунаи классикии намунаи дутарафа дар меъмории муштарӣ-сервер намунаи дархост-ҷавоб мебошад. Биёед ба шаблон ва тағиротҳои он назар андозем.

Дархост-ҷавоб ё RPC

RPC вақте истифода мешавад, ки мо бояд аз раванди дигар посух гирем. Ин раванд метавонад дар як гиреҳ иҷро шавад ё дар қитъаи дигар ҷойгир бошад. Дар зер диаграммаи ҳамкории муштарӣ ва сервер тавассути паёмнависӣ оварда шудааст.

Блокҳои сохтани барномаҳои тақсимшуда. Муносибати аввал

Азбаски паёмнависӣ комилан асинхронӣ аст, барои муштарӣ мубодила ба 2 марҳила тақсим мешавад:

  1. Дархостро пешниҳод кунед

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

    Қурби асъор ‒ номи ягонаи нуқтаи мубодила
    ResponseMatchingTag ‒ тамғаи маҳаллӣ барои коркарди посух. Масалан, дар сурати фиристодани якчанд дархостҳои якхела, ки ба корбарони гуногун тааллуқ доранд.
    Тавсифи дархост - мақоми дархост
    HandlerProcess ‒ PID-и коркардкунанда. Ин раванд аз сервер посух хоҳад гирифт.

  2. Коркарди ҷавоб

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

    ResponsePayload - вокуниши сервер.

Барои сервер, раванд инчунин аз 2 марҳила иборат аст:

  1. Оғоз кардани нуқтаи мубодила
  2. Коркарди дархостҳои қабулшуда

Биёед ин қолабро бо код тасвир кунем. Фарз мекунем, ки мо бояд як хидмати оддиеро татбиқ кунем, ки усули ягонаи вақти дақиқро таъмин мекунад.

Рамзи сервер

Биёед API-и хидматро дар api.hrl муайян кунем:

%% =====================================================
%%  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 паёми 1 МБ беҳтар аз як паёми 1 ГБ аст.

Дар кластери Эрланг, мо фоидаи иловагӣ ба даст меорем - кам кардани сарбории нуқтаи мубодила ва шабака, зеро посухҳо фавран ба қабулкунанда фиристода мешаванд, ки нуқтаи мубодиларо фаро мегиранд.

Ҷавоб бо дархост

Ин як тағироти хеле нодир дар шакли RPC барои сохтани системаҳои муколама аст.

Блокҳои сохтани барномаҳои тақсимшуда. Муносибати аввал

Нашр-обуна (дарахти тақсими маълумот)

Системаҳои ба рӯйдодҳо асосёфта ҳангоми омода шудани маълумот онҳоро ба истеъмолкунандагон мерасонанд. Ҳамин тариқ, системаҳо нисбат ба модели кашида ё пурсиш бештар ба модели тела майл доранд. Ин хусусият ба шумо имкон медиҳад, ки тавассути дархост ва интизории доимии маълумот аз талафи захираҳо пешгирӣ кунед.
Дар расм раванди паҳн кардани паём ба истеъмолкунандагоне, ки ба мавзӯи мушаххас обуна шудаанд, нишон дода шудааст.

Блокҳои сохтани барномаҳои тақсимшуда. Муносибати аввал

Намунаҳои классикии истифодаи ин намуна тақсимоти давлат мебошанд: ҷаҳони бозӣ дар бозиҳои компютерӣ, маълумоти бозор дар бораи мубодила, иттилооти муфид дар каналҳои додаҳо.

Биёед рамзи муштариро бубинем:

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).

Қурби асъор - номи нуқтаи мубодила;
калид - калиди масир
хабар - боркашонӣ

Инвертатсия Интишор-обуна

Блокҳои сохтани барномаҳои тақсимшуда. Муносибати аввал

Бо тавсеаи pub-sub, шумо метавонед намунаи мувофиқ барои сабти ном ба даст оред. Маҷмӯи манбаъҳо ва истеъмолкунандагон метавонанд комилан гуногун бошанд. Дар расм ҳолат бо як истеъмолкунанда ва сарчашмаҳои сершумор нишон дода шудааст.

Намунаи тақсимоти вазифаҳо

Қариб ҳар як лоиҳа вазифаҳои коркарди таъхиршударо дар бар мегирад, ба монанди тавлиди гузоришҳо, расонидани огоҳиҳо ва дарёфти маълумот аз системаҳои тарафи сеюм. Ҳаҷми интиқоли системае, ки ин вазифаҳоро иҷро мекунад, тавассути илова кардани коркардкунандагон ба осонӣ миқёс кардан мумкин аст. Барои мо танҳо ташкили кластери протсессорҳо ва баробар тақсим кардани вазифаҳо дар байни онҳо боқӣ мемонад.

Биёед вазъиятҳоеро, ки бо истифода аз мисоли 3 коркардкунанда ба миён меоянд, бубинем. Хатто дар мархилаи таксимоти вазифахо масъалаи адолати таксим ва пур аз корбарон ба миён меояд. Тақсимоти даври навбатӣ барои адолат масъул хоҳад буд ва барои пешгирӣ кардани ҳолати пур аз корбарон, мо маҳдудият ҷорӣ хоҳем кард prefetch_limit. Дар шароити гузаранда prefetch_limit як коркардкунандаро аз гирифтани ҳама вазифаҳо бозмедорад.

Паёмнависӣ навбатҳо ва афзалияти коркардро идора мекунад. Протсессорҳо ҳангоми расидан вазифаҳоро мегиранд. Вазифа метавонад бомуваффақият иҷро шавад ё ноком шавад:

  • messaging:ack(Tack) - даъват карда мешавад, агар паём бомуваффақият коркард шавад
  • messaging:nack(Tack) - дар ҳама ҳолатҳои фавқулодда даъват карда мешавад. Пас аз баргардонидани супориш, паёмнависӣ онро ба коркарди дигар интиқол медиҳад.

Блокҳои сохтани барномаҳои тақсимшуда. Муносибати аввал

Фарз мекунем, ки ҳангоми коркарди се вазифа нокомии мураккаб рух дод: протсессори 1, пас аз гирифтани супориш, бе вақти ба нуқтаи мубодила хабар додан ба кор афтод. Дар ин ҳолат, нуқтаи мубодила пас аз ба охир расидани мӯҳлати қабулкунӣ вазифаро ба коркарди дигар интиқол медиҳад. Бо баъзе сабабҳо, коркардкунанда 3 супоришро тарк карда, нак фиристод; дар натиҷа, супориш низ ба дигар коркардкунанда гузашт, ки онро бомуваффақият иҷро кард.

Хулосаи пешакӣ

Мо блокҳои асосии сохтани системаҳои тақсимшударо фаро гирифтем ва фаҳмиши асосии истифодаи онҳо дар Erlang/Elixir гирифтем.

Бо омезиши намунаҳои асосӣ, шумо метавонед парадигмаҳои мураккабро барои ҳалли мушкилоти пайдошуда бунёд кунед.

Дар қисми ниҳоии силсила мо масъалаҳои умумии ташкили хадамот, масир ва мувозинатро дида мебароем ва инчунин дар бораи паҳлӯҳои амалии миқёспазирӣ ва таҳаммулпазирии хатогиҳои системаҳо сӯҳбат мекунем.

Охири қисми дуюм.

фото Мариус Кристенсен
Тасвирҳо бо истифода аз websequencediagrams.com омода карда шудаанд

Манбаъ: will.com

Илова Эзоҳ