Blok wangunan aplikasi disebarkeun. Pendekatan munggaran

Blok wangunan aplikasi disebarkeun. Pendekatan munggaran

Di tempo anu kalangkung artikel Urang nalungtik yayasan téoritis arsitektur réaktif. Waktosna pikeun ngobrol ngeunaan aliran data, cara pikeun nerapkeun sistem Erlang/Elixir réaktif sareng pola olahtalatah di antarana:

  • Ménta-réspon
  • Request-Chunked Tanggapan
  • Tanggapan kalawan Request
  • Nyebarkeun-ngalanggan
  • Inverted Nyebarkeun-ngalanggan
  • Distribusi tugas

SOA, MSA sareng Olahtalatah

SOA, MSA mangrupikeun arsitéktur sistem anu nangtukeun aturan pikeun ngawangun sistem, sedengkeun olahtalatah nyayogikeun primitif pikeun palaksanaanna.

Abdi henteu hoyong ngamajukeun ieu atanapi arsitéktur sistem éta. Kami pikeun ngagunakeun prakték anu paling efektif sareng mangpaat pikeun proyék sareng bisnis khusus. Naon paradigma kami milih, éta hadé pikeun nyieun blok sistem kalawan panon on Unix-jalan: komponén kalawan konektipitas minimal, jawab entitas individu. Métode API ngalakukeun tindakan pangbasajanna sareng éntitas.

Olahtalatah téh, sakumaha ngaranna nunjukkeun, hiji calo pesen. Tujuan utamina nyaéta pikeun nampi sareng ngirim pesen. Éta tanggung jawab pikeun antarmuka pikeun ngirim inpormasi, formasi saluran logis pikeun ngirimkeun inpormasi dina sistem, routing sareng balancing, ogé penanganan kasalahan dina tingkat sistem.
Olahtalatah anu kami kembangkeun henteu nyobian bersaing sareng atanapi ngagentos rabbitmq. Fitur utama na:

  • Distribusi.
    Titik bursa tiasa diciptakeun dina sadaya titik kluster, sacaket mungkin sareng kode anu ngagunakeunana.
  • Kesederhanaan.
    Fokus kana ngaminimalkeun kode boilerplate sareng betah dianggo.
  • Performa langkung saé.
    Kami henteu nyobian ngulang pungsionalitas rabbitmq, tapi nyorot ukur lapisan arsitéktur sareng angkutan, anu kami pas kana OTP sabisa-bisa, ngaminimalkeun biaya.
  • Kalenturan.
    Unggal jasa bisa ngagabungkeun loba témplat bursa.
  • Resiliency ku desain.
  • Skalabilitas.
    Olahtalatah tumuwuh kalayan aplikasi. Salaku beban naek, Anjeun bisa mindahkeun titik bursa ka mesin individu.

Catet. Dina hal organisasi kode, meta-proyék cocog pisan pikeun sistem Erlang / Elixir kompléks. Sadaya kode proyék aya dina hiji gudang - hiji proyék payung. Dina waktos anu sami, jasa mikro diisolasi sacara maksimal sareng ngalaksanakeun operasi saderhana anu tanggung jawab pikeun éntitas anu misah. Kalayan pendekatan ieu, éta gampang pikeun ngajaga API tina sakabéh sistem, éta gampang nyieun parobahan, éta merenah pikeun nulis Unit sarta integrasi tés.

Komponén sistem berinteraksi langsung atanapi ngalangkungan calo. Tina sudut pandang olahtalatah, unggal layanan ngagaduhan sababaraha fase hirup:

  • Initialization jasa.
    Dina tahap ieu, prosés sareng katergantungan ngalaksanakeun jasa dikonpigurasi sareng diluncurkeun.
  • Nyieun hiji titik bursa.
    Palayanan tiasa nganggo titik tukeur statik anu ditunjuk dina konfigurasi node, atanapi nyiptakeun titik bursa sacara dinamis.
  • Pendaptaran jasa.
    Dina raraga pikeun layanan pikeun ngalayanan requests, éta kudu didaptarkeun di titik bursa.
  • Fungsi normal.
    jasa ngahasilkeun karya mangpaat.
  • Pareuman.
    Aya 2 jinis shutdown anu mungkin: normal sareng darurat. Salila operasi normal, layanan ieu dipegatkeun tina titik bursa sarta eureun. Dina kaayaan darurat, olahtalatah ngalaksanakeun salah sahiji skrip failover.

Sigana rada pajeulit, tapi kode nu teu kabeh nu pikasieuneun. Conto kode sareng koméntar bakal dipasihkeun dina analisa témplat sakedik engké.

séntral

Exchange point mangrupikeun prosés olahtalatah anu ngalaksanakeun logika interaksi sareng komponén dina template olahtalatah. Dina sagala conto dibere handap, komponén interaksi ngaliwatan titik bursa, kombinasi nu ngabentuk olahtalatah.

Pola pertukaran pesen (MEPs)

Sacara global, pola bursa bisa dibagi jadi dua arah jeung hiji arah. Anu mimiti nunjukkeun réspon kana pesen anu datang, anu terakhir henteu. Conto klasik tina pola dua arah dina arsitektur klien-server nyaéta pola Request-response. Hayu urang nempo template jeung modifikasi na.

Paménta-réspon atanapi RPC

RPC dianggo nalika urang kedah nampi réspon tina prosés anu sanés. Proses ieu tiasa dijalankeun dina titik anu sami atanapi lokasina di buana anu béda. Di handap ieu diagram interaksi antara klien jeung server via olahtalatah.

Blok wangunan aplikasi disebarkeun. Pendekatan munggaran

Kusabab olahtalatah lengkep asynchronous, pikeun klien bursa dibagi kana 2 fase:

  1. Ngirim pamundut

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

    nukeuran ‒ ngaran unik tina titik bursa
    ResponseMatchingTag - labél lokal pikeun ngolah réspon. Contona, dina kasus ngirim sababaraha requests idéntik milik pamaké béda.
    RequestDefinition - pamundut awak
    PananganProsés - PID tina pawang. Proses ieu bakal nampi réspon ti server.

  2. Ngolah réspon

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

    ResponsePayload - respon server.

Pikeun server, prosésna ogé diwangun ku 2 fase:

  1. Initializing titik bursa
  2. Ngolah pamundut anu ditampi

Hayu urang ngagambarkeun template ieu kalawan kode. Sebutkeun urang kedah nerapkeun jasa saderhana anu nyayogikeun metode waktos pasti tunggal.

Kode server

Hayu urang ngartikeun API jasa dina 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{}
}).

Hayu urang ngartikeun controller jasa dina 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.

Kode klien

Pikeun ngirim pamenta ka jasa, anjeun tiasa nyauran API pamundut olahtalatah dimana waé dina klien:

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

Dina sistem anu disebarkeun, konfigurasi komponén tiasa bénten pisan sareng dina waktos pamundut, olahtalatah henteu acan ngamimitian, atanapi pengontrol jasa henteu siap pikeun ngalayanan pamundut. Ku alatan éta, urang kudu pariksa respon olahtalatah jeung nanganan kasus gagalna.
Saatos kiriman suksés, klien bakal nampi réspon atanapi kasalahan tina jasa éta.
Hayu urang nanganan duanana kasus di 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};

Request-Chunked Tanggapan

Hadé pisan pikeun nyingkahan ngirim pesen anu ageung. Responsiveness sareng operasi stabil sadaya sistem gumantung kana ieu. Upami réspon kana pamundut butuh seueur mémori, teras ngabagi kana sababaraha bagian wajib.

Blok wangunan aplikasi disebarkeun. Pendekatan munggaran

Hayu atuh masihan anjeun sababaraha conto kasus sapertos:

  • Komponén tukeur data binér, sapertos file. Megatkeun réspon kana bagian-bagian leutik ngabantosan anjeun damel éfisién sareng file tina ukuran naon waé sareng ngahindarkeun mémori anu overflows.
  • Listing. Salaku conto, urang kedah milih sadaya rékaman tina méja ageung dina pangkalan data sareng mindahkeun kana komponén anu sanés.

Kuring nelepon respon ieu lokomotif. Dina naon waé, 1024 pesen 1 MB langkung saé tibatan pesen 1 GB.

Dina klaster Erlang, urang meunang hiji kauntungan tambahan - ngurangan beban dina titik bursa jeung jaringan, saprak réspon langsung dikirim ka panarima, bypassing titik bursa.

Tanggapan kalawan Request

Ieu mangrupikeun modifikasi anu jarang tina pola RPC pikeun ngawangun sistem dialog.

Blok wangunan aplikasi disebarkeun. Pendekatan munggaran

Publish-subscribe (pohon distribusi data)

Sistem anu didorong acara nganteurkeun aranjeunna ka konsumén pas data parantos siap. Ku kituna, sistem leuwih rawan kana model push batan model tarikan atawa polling. Fitur ieu ngamungkinkeun anjeun pikeun ngahindarkeun sumber daya ku terus-terusan menta sareng ngantosan data.
Gambar nunjukkeun prosés nyebarkeun pesen ka konsumén anu ngalanggan topik khusus.

Blok wangunan aplikasi disebarkeun. Pendekatan munggaran

Conto klasik ngagunakeun pola ieu distribusi kaayaan: dunya kaulinan dina kaulinan komputer, data pasar dina bursa, informasi mangpaat dina feed data.

Hayu urang tingali kode palanggan:

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.

Sumberna tiasa nyauran fungsi pikeun nyebarkeun pesen dina tempat anu merenah:

messaging:publish_message(Exchange, Key, Message).

nukeuran - ngaran titik bursa,
konci - konci routing
pesen - muatan

Inverted Nyebarkeun-ngalanggan

Blok wangunan aplikasi disebarkeun. Pendekatan munggaran

Ku ngalegaan pub-sub, anjeun tiasa kéngingkeun pola anu cocog pikeun logging. Susunan sumber sareng konsumen tiasa bénten pisan. Angka éta nunjukkeun kasus hiji konsumen sareng sababaraha sumber.

Pola distribusi tugas

Ampir unggal proyék ngalibatkeun tugas pamrosésan anu ditunda, sapertos ngahasilkeun laporan, ngirimkeun béwara, sareng nyandak data tina sistem pihak katilu. The throughput tina sistem ngajalankeun tugas ieu bisa gampang diskalakeun ku nambahkeun pawang. Sadaya anu tetep pikeun urang nyaéta ngabentuk gugusan prosesor sareng ngadistribusikaeun tugas anu merata antara aranjeunna.

Hayu urang tingali kaayaan anu timbul ngagunakeun conto 3 pawang. Malah dina tahap panyaluran tugas, sual keadilan distribusi sareng limpahan pawang timbul. Distribusi round-robin bakal tanggung jawab kaadilan, sareng pikeun ngahindarkeun kaayaan limpahan pawang, kami bakal ngenalkeun larangan. prefetch_limit. Dina kaayaan samentara prefetch_limit bakal nyegah hiji Handler tina narima sagala tugas.

Olahtalatah ngatur antrian jeung prioritas processing. Prosesor nampi tugas nalika aranjeunna sumping. Tugas tiasa suksés atanapi gagal:

  • messaging:ack(Tack) - disebut lamun pesen geus hasil diolah
  • messaging:nack(Tack) - disebut dina sagala kaayaan darurat. Sakali tugas dipulangkeun, olahtalatah bakal dikirimkeun ka pawang anu sanés.

Blok wangunan aplikasi disebarkeun. Pendekatan munggaran

Anggap hiji kagagalan kompléks lumangsung nalika ngolah tilu pancén: processor 1, sanggeus narima tugas, nabrak tanpa ngabogaan waktu pikeun ngalaporkeun nanaon ka titik bursa. Dina hal ieu, titik bursa bakal mindahkeun tugas ka Handler sejen sanggeus ack timeout geus kadaluwarsa. Kanggo sababaraha alesan, pawang 3 ngantunkeun tugas sareng ngirim nack; salaku hasilna, tugas éta ogé dialihkeun ka pawang anu sanés anu suksés réngsé.

Ringkesan awal

Kami parantos nutupan blok wangunan dasar sistem anu disebarkeun sareng nampi pamahaman dasar ngeunaan panggunaanana dina Erlang / Elixir.

Ku ngagabungkeun pola dasar, anjeun tiasa ngawangun paradigma kompléks pikeun ngajawab masalah munculna.

Dina bagian ahir séri, urang bakal kasampak di isu umum ngeunaan jasa pangatur, routing na balancing, sarta ogé ngobrol ngeunaan sisi praktis scalability jeung kasabaran lepat sistem.

Tungtung bagian kadua.

poto Marius Christensen
Ilustrasi disusun nganggo websequencediagrams.com

sumber: www.habr.com

Tambahkeun komentar