Blok bangunan aplikasi sing disebarake. Pendekatan pisanan

Blok bangunan aplikasi sing disebarake. Pendekatan pisanan

Ing pungkasan artikel Kita nliti dhasar teoretis arsitektur reaktif. Wektu kanggo ngomong babagan aliran data, cara kanggo ngetrapake sistem Erlang / Elixir reaktif lan pola olahpesen ing kono:

  • Njaluk-respon
  • Request-Chunked Response
  • Respon karo Request
  • Nerbitake-langganan
  • Inverted Publish-langganan
  • Distribusi tugas

SOA, MSA lan Pesen

SOA, MSA minangka arsitektur sistem sing nemtokake aturan kanggo sistem bangunan, nalika olahpesen nyedhiyakake primitif kanggo implementasine.

Aku ora pengin ningkatakΓ© arsitektur sistem iki utawa sing. Aku nggunakake praktik sing paling efektif lan migunani kanggo proyek lan bisnis tartamtu. Punapa mawon paradigma kita milih, iku luwih apik kanggo nggawe pamblokiran sistem karo mripat ing Unix-cara: komponen karo panyambungan minimal, tanggung jawab kanggo entitas individu. Cara API nindakake tumindak sing paling gampang karo entitas.

Olahpesen, kaya jeneng kasebut, broker pesen. Tujuan utamane yaiku kanggo nampa lan ngirim pesen. Tanggung jawab kanggo antarmuka kanggo ngirim informasi, pambentukan saluran logis kanggo ngirim informasi ing sistem, nuntun lan imbangan, uga penanganan kesalahan ing tingkat sistem.
Pesen sing dikembangake ora nyoba saingan utawa ngganti rabbitmq. Fitur utama:

  • Distribusi.
    Titik ijol-ijolan bisa digawe ing kabeh kelenjar kluster, sabisa-bisa kode sing digunakake.
  • Kesederhanaan
    Fokus kanggo nyilikake kode boilerplate lan gampang digunakake.
  • Kinerja sing luwih apik.
    Kita ora nyoba mbaleni fungsi rabbitmq, nanging mung nyorot lapisan arsitektur lan transportasi, sing pas karo OTP kanthi gampang, nyuda biaya.
  • Fleksibilitas.
    Saben layanan bisa nggabungake akeh template ijol-ijolan.
  • Resiliensi dening desain.
  • Skalabilitas.
    Olahpesen tuwuh kanthi aplikasi. Nalika beban mundhak, sampeyan bisa mindhah titik ijol-ijolan menyang mesin individu.

Cathetan. Ing babagan organisasi kode, meta-proyek cocog kanggo sistem Erlang / Elixir sing kompleks. Kabeh kode proyek dumunung ing siji gudang - proyek payung. Ing wektu sing padha, layanan mikro diisolasi kanthi maksimal lan nindakake operasi prasaja sing tanggung jawab kanggo entitas sing kapisah. Kanthi pendekatan iki, gampang kanggo njaga API kabeh sistem, gampang nggawe owah-owahan, trep kanggo nulis tes unit lan integrasi.

Komponen sistem interaksi langsung utawa liwat makelar. Saka perspektif olahpesen, saben layanan duwe sawetara fase urip:

  • Inisialisasi layanan.
    Ing tahap iki, proses lan dependensi sing nglakokake layanan dikonfigurasi lan diluncurake.
  • Nggawe titik ijol-ijolan.
    Layanan kasebut bisa nggunakake titik ijol-ijolan statis sing ditemtokake ing konfigurasi simpul, utawa nggawe titik ijol-ijolan kanthi dinamis.
  • Registrasi layanan.
    Supaya layanan bisa nglayani panjalukan, kudu didaftar ing titik ijol-ijolan.
  • Fungsi normal.
    Layanan kasebut ngasilake karya sing migunani.
  • mateni.
    Ana 2 jinis mati bisa: normal lan darurat. Sajrone operasi normal, layanan kasebut pedhot saka titik ijol-ijolan lan mandheg. Ing kahanan darurat, olahpesen nglakokake salah sawijining skrip failover.

Iku katon cukup rumit, nanging kode ora kabeh sing medeni. Conto kode karo komentar bakal diwenehi ing analisis cithakan mengko.

Exchanges

Exchange point minangka proses olahpesen sing ngetrapake logika interaksi karo komponen ing cithakan olahpesen. Ing kabeh conto sing ditampilake ing ngisor iki, komponen kasebut sesambungan liwat titik ijol-ijolan, kombinasi sing dadi olahpesen.

Pola tukar pesan (MEPs)

Sacara global, pola ijol-ijolan bisa dipΓ©rang dadi rong arah lan siji arah. Tilas nuduhake respon kanggo pesen sing mlebu, sing terakhir ora. Conto klasik saka pola rong arah ing arsitektur klien-server yaiku pola Request-response. Ayo katon ing cithakan lan modifikasi.

Request-respon utawa RPC

RPC digunakake nalika kita kudu nampa respon saka proses liyane. Proses iki bisa uga mlaku ing simpul sing padha utawa dumunung ing bawana sing beda. Ing ngisor iki diagram interaksi antarane klien lan server liwat olahpesen.

Blok bangunan aplikasi sing disebarake. Pendekatan pisanan

Amarga olahpesen pancen ora sinkron, kanggo klien ijol-ijolan dipΓ©rang dadi 2 fase:

  1. Kirim request

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

    Exchange β€’ jeneng unik saka titik ijol-ijolan
    ResponseMatchingTag - label lokal kanggo ngolah respon. Contone, ing kasus ngirim sawetara panjalukan sing padha karo pangguna sing beda.
    RequestDefinition - njaluk awak
    Proses Handler - PID saka pawang. Proses iki bakal nampa respon saka server.

  2. Ngolah respon

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

    ResponsePayload - respon server.

Kanggo server, proses kasebut uga kalebu 2 fase:

  1. Initializing titik ijol-ijolan
  2. Pangolahan panjalukan sing ditampa

Ayo digambarake cithakan iki nganggo kode. Ayo kita kudu ngleksanakake layanan prasaja sing nyedhiyakake metode wektu sing tepat.

Kode server

Ayo nambah definisi API layanan kanggo 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{}
}).

Ayo dadi netepake controller layanan ing 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

Kanggo ngirim panjalukan menyang layanan kasebut, sampeyan bisa nelpon API panjalukan olahpesen ing ngendi wae ing klien:

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

Ing sistem sing disebarake, konfigurasi komponen bisa beda banget lan nalika panyuwunan, olahpesen bisa uga durung diwiwiti, utawa pengontrol layanan ora bakal siyap kanggo nglayani panyuwunan kasebut. Mulane, kita kudu mriksa respon olahpesen lan nangani kasus kegagalan.
Sawise sukses ngirim, klien bakal nampa respon utawa kesalahan saka layanan.
Ayo nangani loro kasus ing 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 Response

Sing paling apik supaya ora ngirim pesen gedhe. Responsiveness lan operasi stabil kabeh sistem gumantung iki. Yen nanggepi pitakonan mbutuhake akeh memori, banjur dibagi dadi bagean wajib.

Blok bangunan aplikasi sing disebarake. Pendekatan pisanan

Ayo kula menehi sawetara conto kasus kasebut:

  • Komponen kasebut ngganti data binar, kayata file. Mbusak respon dadi bagean cilik mbantu sampeyan nggarap file kanthi ukuran apa wae lan ngindhari overflows memori.
  • Listings. Contone, kita kudu milih kabeh cathetan saka tabel ageng ing database lan nransfer menyang komponen liyane.

Aku nelpon respon iki lokomotif. Ing kasus apa wae, 1024 pesen 1 MB luwih apik tinimbang pesen siji 1 GB.

Ing kluster Erlang, entuk manfaat tambahan - nyuda beban ing titik ijol-ijolan lan jaringan, amarga tanggapan langsung dikirim menyang panampa, ngliwati titik ijol-ijolan.

Respon karo Request

Iki minangka modifikasi pola RPC sing rada langka kanggo mbangun sistem dialog.

Blok bangunan aplikasi sing disebarake. Pendekatan pisanan

Publish-subscribe (pohon distribusi data)

Sistem sing didorong acara ngirim menyang konsumen sanalika data wis siyap. Mangkono, sistem luwih rentan kanggo model push tinimbang model tarik utawa polling. Fitur iki ngidini sampeyan supaya ora mbuang sumber daya kanthi terus-terusan njaluk lan ngenteni data.
Tokoh kasebut nuduhake proses nyebarake pesen menyang konsumen sing langganan topik tartamtu.

Blok bangunan aplikasi sing disebarake. Pendekatan pisanan

Conto klasik nggunakake pola iki distribusi negara: donya game ing game komputer, data pasar ing ijol-ijolan, informasi migunani ing feed data.

Ayo ndeleng kode langganan:

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.

Sumber bisa nelpon fungsi kasebut kanggo nerbitake pesen ing papan sing trep:

messaging:publish_message(Exchange, Key, Message).

Exchange - jeneng titik ijol-ijolan,
Key - tombol nuntun
Pesen - muatan

Inverted Publish-langganan

Blok bangunan aplikasi sing disebarake. Pendekatan pisanan

Kanthi ngembangake pub-sub, sampeyan bisa entuk pola sing trep kanggo logging. Kumpulan sumber lan konsumen bisa beda-beda. Tokoh kasebut nuduhake kasus karo siji konsumen lan macem-macem sumber.

Pola distribusi tugas

Meh saben proyek kalebu tugas pangolahan sing ditundha, kayata ngasilake laporan, ngirim kabar, lan njupuk data saka sistem pihak katelu. Output saka sistem sing nindakake tugas kasebut bisa gampang diukur kanthi nambah panangan. Kabeh sing isih ana kanggo kita yaiku mbentuk kluster pemroses lan nyebarake tugas kanthi rata ing antarane.

Ayo ndeleng kahanan sing muncul nggunakake conto 3 pawang. Malah ing tataran distribusi tugas, pitakonan babagan keadilan distribusi lan kebanjiran pawang muncul. Distribusi round-robin bakal tanggung jawab kanggo keadilan, lan kanggo ngindhari kahanan kebanjiran pawang, kita bakal ngenalake watesan. prefetch_limit. Ing kahanan sementara prefetch_limit bakal nyegah siji handler saka nampa kabeh tugas.

Pesen ngatur antrian lan prioritas pangolahan. Prosesor nampa tugas nalika teka. Tugas bisa rampung kanthi sukses utawa gagal:

  • messaging:ack(Tack) - disebut yen pesen wis kasil diproses
  • messaging:nack(Tack) - disebut ing kabeh kahanan darurat. Sawise tugas kasebut bali, olahpesen bakal dikirim menyang pawang liyane.

Blok bangunan aplikasi sing disebarake. Pendekatan pisanan

Upamane ana kegagalan kompleks nalika ngolah telung tugas: prosesor 1, sawise nampa tugas kasebut, tabrakan tanpa wektu kanggo nglaporake apa wae menyang titik ijol-ijolan. Ing kasus iki, titik ijol-ijolan bakal nransfer tugas kanggo handler liyane sawise wektu entek ack wis kadaluwarsa. Kanggo sawetara alasan, pawang 3 nilar tugas kasebut lan ngirim nack; minangka asil, tugas kasebut uga ditransfer menyang pawang liyane sing kasil ngrampungake.

Ringkesan awal

Kita wis nutupi blok bangunan dhasar sistem sing disebarake lan entuk pangerten dhasar babagan panggunaan ing Erlang / Elixir.

Kanthi nggabungake pola dhasar, sampeyan bisa mbangun paradigma rumit kanggo ngatasi masalah sing muncul.

Ing bagΓ©an pungkasan saka seri, kita bakal katon ing masalah umum ngatur layanan, nuntun lan imbangan, lan uga ngomong bab sisih praktis saka kaukur lan toleransi fault saka sistem.

Pungkasan bagean kapindho.

Photography Marius Christensen
Ilustrasi disiapake nggunakake websequencediagrams.com

Source: www.habr.com

Add a comment