{"id":30908,"date":"2019-10-31T21:38:07","date_gmt":"2019-10-31T18:38:07","guid":{"rendered":"https:\/\/prohoster.info\/blog\/stroitelnye-bloki-raspredelennyh-prilozhenij-pervoe-priblizhenie\/"},"modified":"2019-10-31T21:38:07","modified_gmt":"2019-10-31T18:38:07","slug":"stroitelnye-bloki-raspredelennyh-prilozhenij-pervoe-priblizhenie","status":"publish","type":"post","link":"https:\/\/prohoster.info\/sv\/blog\/administrirovanie\/stroitelnye-bloki-raspredelennyh-prilozhenij-pervoe-priblizhenie","title":{"rendered":"Byggblock f\u00f6r distribuerade applikationer. F\u00f6rsta n\u00e4rmandet","gt_translate_keys":[{"key":"rendered","format":"text"}]},"content":{"rendered":"<p><img decoding=\"async\" alt=\"Byggblock f\u00f6r distribuerade applikationer. F\u00f6rsta n\u00e4rmandet\" src=\"\/wp-content\/uploads\/2019\/04\/7ef485e452075775ce317b557671274c.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Tidigare <noindex><a rel=\"nofollow\" href=\"https:\/\/habr.com\/ru\/post\/446028\/\">artikeln<\/a><\/noindex> Vi har diskuterat de teoretiska grunderna f\u00f6r reaktiv arkitektur. Det \u00e4r dags att prata om datastreams, implementeringsv\u00e4gar f\u00f6r reaktiva Erlang\/Elixir-system och meddelandeutbyte i dem:<\/p>\n<p><\/p>\n<ul>\n<li>Beg\u00e4r-svar<\/li>\n<li>Beg\u00e4r-Chunked Svar<\/li>\n<li>Svar med Beg\u00e4ran<\/li>\n<li>Publicera-prenumerera<\/li>\n<li>Inverterad Publicera-prenumerera<\/li>\n<li>Uppgiftsdistribution<noindex><a rel=\"nofollow\" name=\"habracut\"><\/a><\/noindex><\/li>\n<\/ul>\n<p><\/p>\n<h2 id=\"soa-msa-i-obmen-soobscheniyami\">SOA, MSA och meddelandeutbyte<\/h2>\n<p><\/p>\n<p>SOA, MSA \u2013 systemarkitekturer som definierar reglerna f\u00f6r systemuppbyggnad, medan meddelandeutbyte tillhandah\u00e5ller primitiva verktyg f\u00f6r deras implementering.<\/p>\n<p><\/p>\n<p>Jag vill inte propagera f\u00f6r en viss systemarkitektur. Jag f\u00f6respr\u00e5kar att anv\u00e4nda s\u00e5 effektiva och nyttiga metoder som m\u00f6jligt f\u00f6r ett specifikt projekt och f\u00f6retag. Oavsett vilken paradigm vi v\u00e4ljer, \u00e4r det b\u00e4ttre att skapa systemblock med tanke p\u00e5 Unix-way: komponenter med minimal bindning som ansvarar f\u00f6r individuella enheter. API-metoder utf\u00f6r de enklaste \u00e5tg\u00e4rderna med enheterna.<\/p>\n<p><\/p>\n<p>Meddelandeutbyte \u2012 som namnet antyder \u2012 \u00e4r en meddelandebroker. Dess huvudsakliga syfte \u00e4r att ta emot och skicka meddelanden. Den ansvarar f\u00f6r gr\u00e4nssnitten f\u00f6r att skicka information, bildandet av logiska informations\u00f6verf\u00f6ringskanaler inom systemet, routing och belastningsbalansering, samt hantering av fel p\u00e5 systemniv\u00e5.<br \/>\nDet utvecklade meddelandeutbytet f\u00f6rs\u00f6ker inte konkurrera med rabbitmq eller ers\u00e4tta det. Dess huvuddrag \u00e4r:<\/p>\n<p><\/p>\n<ul>\n<li>Distribuerbarhet.<br \/>\nUtbytespunkter kan skapas p\u00e5 alla noder i klustret, s\u00e5 n\u00e4ra koden som m\u00f6jligt som anv\u00e4nder dem.<\/li>\n<li>Enkelhet.<br \/>\nInriktning p\u00e5 minimering av mallkod och anv\u00e4ndarv\u00e4nlighet.<\/li>\n<li>B\u00e4sta prestanda.<br \/>\nVi f\u00f6rs\u00f6ker inte \u00e5terge funktionaliteten hos rabbitmq, utan lyfter fram only den arkitektoniska och transportlagret, som vi enkelt kan integrera i OTP och minimera kostnaderna.<\/li>\n<li>Flexibilitet.<br \/>\nVarje tj\u00e4nst kan kombinera m\u00e5nga m\u00f6nster f\u00f6r meddelandeutbyte.<\/li>\n<li>Felmotst\u00e5nd, inb\u00e4ddat i designen.<\/li>\n<li>Skalbarhet.<br \/>\nMeddelandeutbytet v\u00e4xer tillsammans med applikationen. Medan belastningen \u00f6kar kan man flytta utbytespunkter till separata maskiner.<\/li>\n<\/ul>\n<p><\/p>\n<p><em>Anm\u00e4rkning.<\/em> Ur kodorganisations synvinkel passar meta-projekt bra f\u00f6r komplexa system p\u00e5 Erlang\/Elixir. All kod i projektet finns i ett gemensamt repository \u2012 ett paraplyprojekt. Samtidigt \u00e4r mikrotj\u00e4nster maximalt isolerade och utf\u00f6r enkla operationer som ansvarar f\u00f6r enskilda entiteter. Med detta tillv\u00e4gag\u00e5ngss\u00e4tt \u00e4r det l\u00e4tt att underh\u00e5lla API:et f\u00f6r hela systemet, enkelt att g\u00f6ra \u00e4ndringar och bekv\u00e4mt att skriva enhets- och integrationstester.<\/p>\n<p><\/p>\n<p>Systemkomponenter interagerar direkt eller via en broker. Ur messaging-synpunkt har varje tj\u00e4nst flera livscykelfaser:<\/p>\n<p><\/p>\n<ul>\n<li>Initiering av tj\u00e4nsten.<br \/>\nI detta skede sker konfiguration och start av den exekverande tj\u00e4nsteprocessen och dess beroenden.<\/li>\n<li>Skapande av en exchange-punkt.<br \/>\nTj\u00e4nsten kan anv\u00e4nda en statisk exchange-punkt som anges i nodens konfiguration, eller skapa exchange-punkter dynamiskt. <\/li>\n<li>Registrering av tj\u00e4nsten.<br \/>\nF\u00f6r att tj\u00e4nsten ska kunna hantera beg\u00e4rningar m\u00e5ste den registreras vid exchange-punkten.<\/li>\n<li>Normal funktionalitet.<br \/>\nTj\u00e4nsten utf\u00f6r nytt arbete.<\/li>\n<li>Avslutning av arbetet.<br \/>\nDet finns tv\u00e5 typer av avslutning: normal och akut. Vid normal avslutning kopplar sig tj\u00e4nsten bort fr\u00e5n exchange-punkten och st\u00e4ngs av. Vid akuta fall utf\u00f6r messaging ett av felhanteringsscenarierna.<\/li>\n<\/ul>\n<p><\/p>\n<p>Det ser ganska komplicerat ut, men i koden \u00e4r det inte s\u00e5 skr\u00e4mmande. Kodexempel med kommentarer kommer att presenteras i analysen av m\u00f6nstren lite senare.<\/p>\n<p><\/p>\n<h2 id=\"exchanges\">Exchanges<\/h2>\n<p><\/p>\n<p>En exchange-punkt \u00e4r en messaging-process som implementerar logiken f\u00f6r interaktion med komponenter inom ramen f\u00f6r meddelandeutbytesm\u00f6nstret. I alla exempel som presenteras nedan interagerar komponenterna via exchange-punkter, vars kombination utg\u00f6r messaging.<\/p>\n<p><\/p>\n<h2 id=\"message-exchange-patterns-meps\">Message exchange patterns (MEPs)<\/h2>\n<p><\/p>\n<p>Globalt kan utbytesmallar delas in i tv\u00e5v\u00e4gs och env\u00e4gs. De f\u00f6rsta inneb\u00e4r ett svar p\u00e5 det mottagna meddelandet, de andra g\u00f6r det inte. Ett klassiskt exempel p\u00e5 en tv\u00e5v\u00e4gs-mall i en klient-server-arkitektur \u00e4r Request-response m\u00f6nstret. L\u00e5t oss granska m\u00f6nstret och dess modifieringar.<\/p>\n<p><\/p>\n<h3 id=\"requestresponse-ili-rpc\">Request\u2013response eller RPC<\/h3>\n<p><\/p>\n<p>RPC anv\u00e4nds n\u00e4r vi beh\u00f6ver f\u00e5 ett svar fr\u00e5n en annan process. Denna process kan k\u00f6ras p\u00e5 samma nod eller befinna sig p\u00e5 en annan kontinent. Nedan visas en skiss \u00f6ver interaktionen mellan klienten och <a class=\"wpil_keyword_link\" href=\"https:\/\/prohoster.info\/sv\/server\/dts-los-angeles\/\"   title=\"servern\" data-wpil-keyword-link=\"linked\"  data-wpil-monitor-id=\"3483\">servern<\/a> via messaging.<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Byggblock f\u00f6r distribuerade applikationer. F\u00f6rsta n\u00e4rmandet\" src=\"\/wp-content\/uploads\/2019\/04\/091725fc108d6ce1a5fc9ae866e2c395.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Eftersom messaging \u00e4r helt asynkront, delas utbytet f\u00f6r klienten in i tv\u00e5 faser:<\/p>\n<p><\/p>\n<ol>\n<li>\n<p>Skicka beg\u00e4ran<\/p>\n<p><\/p>\n<pre><code class=\"erlang\">messaging:request(Exchange, ResponseMatchingTag, RequestDefinition, HandlerProcess).<\/code><\/pre>\n<p><\/p>\n<p><em>Exchange<\/em> \u2012 ett unikt namn f\u00f6r utbytespunkten<br \/>\n<em>ResponseMatchingTag<\/em> \u2012 en lokal etikett f\u00f6r att bearbeta svaret. Till exempel, i fall av att skicka flera samma f\u00f6rfr\u00e5gningar som tillh\u00f6r olika anv\u00e4ndare.<br \/>\n<em>RequestDefinition<\/em> \u2012 kroppen av f\u00f6rfr\u00e5gan<br \/>\n<em>HandlerProcess<\/em> \u2012 PID f\u00f6r hanteraren. Denna process kommer att f\u00e5 svaret fr\u00e5n servern.<\/p>\n<p>\n<\/li>\n<li>\n<p>Bearbetning av svaret<\/p>\n<p><\/p>\n<pre><code class=\"erlang\">handle_info(#'$msg'{exchange = EXCHANGE, tag = ResponseMatchingTag,message = ResponsePayload}, State)<\/code><\/pre>\n<p><\/p>\n<p><em>ResponsePayload<\/em> \u2012 svaret fr\u00e5n servern.<\/p>\n<p>\n<\/li>\n<\/ol>\n<p><\/p>\n<p>F\u00f6r servern best\u00e5r processen ocks\u00e5 av 2 faser:<\/p>\n<p><\/p>\n<ol>\n<li>Initiering av utbytespunkten<\/li>\n<li>Bearbetning av inkommande f\u00f6rfr\u00e5gningar<\/li>\n<\/ol>\n<p><\/p>\n<p>L\u00e5t oss illustrera detta m\u00f6nster med kod. Anta att vi beh\u00f6ver implementera en enkel tj\u00e4nst som tillhandah\u00e5ller en enda metod f\u00f6r exakt tid.<\/p>\n<p><\/p>\n<h4 id=\"kod-servera\">Serverkod<\/h4>\n<p><\/p>\n<p>Vi flyttar definitionen av tj\u00e4nstens API till api.hrl:<\/p>\n<p><\/p>\n<pre><code class=\"erlang\">%% =====================================================\n%%  entiteter\n%% =====================================================\n-record(time, {\n  unixtime :: non_neg_integer(),\n  datetime :: binary()\n}).\n\n-record(time_error, {\n  code :: non_neg_integer(),\n  error :: term()\n}).\n\n%% =====================================================\n%%  metoder\n%% =====================================================\n-record(time_req, {\n  opts :: term()\n}).\n-record(time_resp, {\n  result :: #time{} | #time_error{}\n}).<\/code><\/pre>\n<p><\/p>\n<p>Vi definierar tj\u00e4nstens kontroller i time_controller.erl<\/p>\n<p><\/p>\n<pre><code class=\"erlang\">%% Exemplet visar endast relevant kod. Genom att infoga det i m\u00f6nstret gen_server kan vi f\u00e5 en fungerande tj\u00e4nst.\n\n%% initiering av gen_server\ninit(Args) -&gt;\n  %% anslutning till utbytespunkten\n  messaging:monitor_exchange(req_resp, ?EXCHANGE, default, self())\n  {ok, #{}}.\n\n%% hantering av h\u00e4ndelsen f\u00f6r bortfall av kontakt med utbytespunkten. Denna h\u00e4ndelse skickas ocks\u00e5 om utbytespunkten \u00e4nnu inte har startat.\nhandle_info(#exchange_die{exchange = ?EXCHANGE}, State) -&gt;\n  erlang:send(self(), monitor_exchange),\n  {noreply, State};\n\n%% hantering av API\nhandle_info(#time_req{opts = _Opts}, State) -&gt;\n  messaging:response_once(Client, #time_resp{\nresult = #time{ unixtime = time_utils:unixtime(now()), datetime = time_utils:iso8601_fmt(now())}\n  });\n  {noreply, State};\n\n%% avslutning av gen_server\nterminate(_Reason, _State) -&gt;\n  messaging:demonitor_exchange(req_resp, ?EXCHANGE, default, self()),\n  ok.<\/code><\/pre>\n<p><\/p>\n<h4 id=\"kod-klienta\">Kundkod<\/h4>\n<p><\/p>\n<p>F\u00f6r att skicka en beg\u00e4ran till tj\u00e4nsten kan messaging beg\u00e4ran API anropas var som helst i klienten:<\/p>\n<p><\/p>\n<pre><code class=\"erlang\">case messaging:request(?EXCHANGE, tag, #time_req{opts = #{}}, self()) of\n    ok -&gt; ok;\n    _ -&gt; %% upprepa eller fel logik\nend<\/code><\/pre>\n<p><\/p>\n<p>I ett distribuerat system kan konfigurationen av komponenter vara mycket varierande, och n\u00e4r beg\u00e4ran g\u00f6rs kan messaging \u00e4nnu inte ha startat, eller s\u00e5 kan tj\u00e4nstkontrollern inte vara redo att hantera beg\u00e4ran. D\u00e4rf\u00f6r m\u00e5ste vi kontrollera svaret fr\u00e5n messaging och hantera avvisningsfallet.<br \/>\nEfter en framg\u00e5ngsrik s\u00e4ndning kommer klienten att f\u00e5 ett svar eller ett fel fr\u00e5n tj\u00e4nsten.<br \/>\nVi hanterar b\u00e5da fallen i handle_info:<\/p>\n<p><\/p>\n<pre><code class=\"erlang\">handle_info(#'$msg'{exchange = ?EXCHANGE, tag = tag, message = #time_resp{result = #time{unixtime = Utime}}}, State) -&gt;\n  ?debugVal(Utime),\n  {noreply, State};\n\nhandle_info(#'$msg'{exchange = ?EXCHANGE, tag = tag, message = #time_resp{result = #time_error{code = ErrorCode}}}, State) -&gt;\n  ?debugVal({error, ErrorCode}),\n  {noreply, State};<\/code><\/pre>\n<p><\/p>\n<h3 id=\"request-chunked-response\">Beg\u00e4r-Chunked Svar<\/h3>\n<p><\/p>\n<p>Det \u00e4r b\u00e4st att undvika att skicka stora meddelanden. Detta p\u00e5verkar responsen och stabiliteten hos hela systemet. Om svaret p\u00e5 en beg\u00e4ran tar mycket minne, \u00e4r det n\u00f6dv\u00e4ndigt att dela upp det i delar.<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Byggblock f\u00f6r distribuerade applikationer. F\u00f6rsta n\u00e4rmandet\" src=\"\/wp-content\/uploads\/2019\/04\/bd60742a933a8e4e3eeaf7f4adf00f2a.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Jag ska ge n\u00e5gra exempel p\u00e5 s\u00e5dana fall:<\/p>\n<p><\/p>\n<ul>\n<li>Komponenter byter bin\u00e4ra data, exempelvis filer. Att dela upp svaret i sm\u00e5 delar g\u00f6r det m\u00f6jligt att effektivt hantera filer av alla storlekar utan att f\u00e5 minnes\u00f6verfull.<\/li>\n<li>Listor. Till exempel beh\u00f6ver vi h\u00e4mta alla poster fr\u00e5n en stor tabell i databasen och skicka dem till en annan komponent.<\/li>\n<\/ul>\n<p><\/p>\n<p>Jag kallar s\u00e5dana svar f\u00f6r en lokomotiv. I vilket fall som helst, 1024 meddelanden p\u00e5 1 MB \u00e4r b\u00e4ttre \u00e4n ett enda meddelande som \u00e4r 1 GB. <\/p>\n<p><\/p>\n<p>I en Erlang-kluster f\u00e5r vi ytterligare f\u00f6rdelar - minskad belastning p\u00e5 utbytespunkten och n\u00e4tverket, eftersom svaren skickas direkt till mottagaren utan att g\u00e5 via utbytespunkten.<\/p>\n<p><\/p>\n<h3 id=\"response-with-request\">Svar med Beg\u00e4ran<\/h3>\n<p><\/p>\n<p>Detta \u00e4r en ganska s\u00e4llsynt modifiering av RPC-m\u00f6nstret f\u00f6r att bygga dialogsystem.<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Byggblock f\u00f6r distribuerade applikationer. F\u00f6rsta n\u00e4rmandet\" src=\"\/wp-content\/uploads\/2019\/04\/9b350a0b48ca8acdca973da2f7eadb76.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<h3 id=\"publish-subscribe-data-distribution-tree\">Publicera-prenumerera (datadistributionsstruktur)<\/h3>\n<p><\/p>\n<p>H\u00e4ndelseorienterade system levererar data till konsumenterna s\u00e5 snart de \u00e4r redo. P\u00e5 s\u00e5 s\u00e4tt \u00e4r systemen mer ben\u00e4gna att anv\u00e4nda en push-modell \u00e4n en pull eller poll. Denna egenskap f\u00f6rhindrar sl\u00f6seri med resurser genom att st\u00e4ndigt beg\u00e4ra och v\u00e4nta p\u00e5 data.<br \/>\nP\u00e5 bilden visas processen f\u00f6r distribution av meddelanden till konsumenter som prenumererat p\u00e5 ett visst \u00e4mne.<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Byggblock f\u00f6r distribuerade applikationer. F\u00f6rsta n\u00e4rmandet\" src=\"\/wp-content\/uploads\/2019\/04\/e211d5dcfeb5ce8513699eac8e3b6d84.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Klassiska exempel p\u00e5 anv\u00e4ndning av detta m\u00f6nster \u00e4r distribution av tillst\u00e5nd: spelv\u00e4rldar i datorspel, marknadsdata p\u00e5 b\u00f6rser, anv\u00e4ndbar information i datafl\u00f6den.<\/p>\n<p><\/p>\n<p>L\u00e5t oss titta p\u00e5 koden f\u00f6r prenumeranten:<\/p>\n<p><\/p>\n<pre><code class=\"erlang\">init(_Args) -&gt;\n  %% prenumerera p\u00e5 utbytet, nyckel = key\n  messaging:subscribe(?SUBSCRIPTION, key, tag, self()),\n  {ok, #{}}.\n\nhandle_info(#exchange_die{exchange = ?SUBSCRIPTION}, State) -&gt;\n  %% om utbytet inte \u00e4r tillg\u00e4ngligt, f\u00f6rs\u00f6k att \u00e5teransluta\n  messaging:subscribe(?SUBSCRIPTION, key, tag, self()),\n  {noreply, State};\n\n%% bearbeta inkommande meddelanden\nhandle_info(#'$msg'{exchange = ?SUBSCRIPTION, message = Msg}, State) -&gt;\n  ?debugVal(Msg),\n  {noreply, State};\n\n%% vid stopp av konsumenten - koppla bort fr\u00e5n utbytet\nterminate(_Reason, _State) -&gt;\n  messaging:unsubscribe(?SUBSCRIPTION, key, tag, self()),\n  ok.<\/code><\/pre>\n<p><\/p>\n<p>K\u00e4lla kan anropa publiceringsfunktionen var som helst:<\/p>\n<p><\/p>\n<pre><code class=\"erlang\">messaging:publish_message(Exchange, Key, Message).<\/code><\/pre>\n<p><\/p>\n<p><em>Exchange<\/em> \u2012 namnet p\u00e5 utbytespunkten,<br \/>\n<em>Nyckel<\/em> \u2012 routningsnyckel<br \/>\n<em>Message<\/em> \u2012 nyttolast<\/p>\n<p><\/p>\n<h2 id=\"inverted-publish-subscribe\">Inverterad Publicera-prenumerera<\/h2>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Byggblock f\u00f6r distribuerade applikationer. F\u00f6rsta n\u00e4rmandet\" src=\"\/wp-content\/uploads\/2019\/04\/2ef7cd7de459455937bdcfa8a11fd028.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Genom att rulla ut pub-sub kan man f\u00e5 ett m\u00f6nster som \u00e4r bekv\u00e4mt f\u00f6r loggning. M\u00e4ngden k\u00e4llor och konsumenter kan variera helt. Bilden visar ett fall med en konsument och m\u00e5nga k\u00e4llor.<\/p>\n<p><\/p>\n<h2 id=\"task-distribution-pattern\">Uppgiftf\u00f6rdelningsm\u00f6nster<\/h2>\n<p><\/p>\n<p>I n\u00e4stan varje projekt uppst\u00e5r uppgifter f\u00f6r f\u00f6rdr\u00f6jd behandling, s\u00e5som rapportgenerering, aviseringar och datainsamling fr\u00e5n externa system. Kapaciteten hos systemet som utf\u00f6r dessa uppgifter kan enkelt skalas genom att l\u00e4gga till bearbetare. Det enda vi beh\u00f6ver g\u00f6ra \u00e4r att skapa en kluster av bearbetare och j\u00e4mnt f\u00f6rdela uppgifterna mellan dem.<\/p>\n<p><\/p>\n<p>L\u00e5t oss \u00f6verv\u00e4ga situationer med 3 bearbetare. Redan i automatiseringssteget uppst\u00e5r fr\u00e5gan om r\u00e4ttvis f\u00f6rdelning och \u00f6verbelastning av bearbetarna. R\u00e4ttvisan kommer att s\u00e4kerst\u00e4llas genom round-robin f\u00f6rdelning, och f\u00f6r att undvika \u00f6verbelastningssituationen kommer vi att inf\u00f6ra begr\u00e4nsningen <em>prefetch_limit<\/em>. I \u00f6verg\u00e5ngstillst\u00e5nd <em>prefetch_limit<\/em> kan en bearbetare inte f\u00e5 alla uppgifter.<\/p>\n<p><\/p>\n<p>Messaging hanterar k\u00f6er och prioriteringar f\u00f6r behandling. Bearbetarna f\u00e5r uppgifter i takt med att de kommer in. Uppgiftsutf\u00f6randet kan avslutas antingen med framg\u00e5ng eller med ett fel:<\/p>\n<p><\/p>\n<ul>\n<li><code>messaging:ack(Tack)<\/code> \u2012 anropas vid framg\u00e5ngsrik behandling av meddelandet<\/li>\n<li><code>messaging:nack(Tack)<\/code> \u2012 anropas vid alla onormala situationer. Efter att uppgiften har \u00e5terl\u00e4mnats kommer messaging att vidarebefordra den till en annan bearbetare.<\/li>\n<\/ul>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Byggblock f\u00f6r distribuerade applikationer. F\u00f6rsta n\u00e4rmandet\" src=\"\/wp-content\/uploads\/2019\/04\/c2c632b6411247ee8b0dcfb3250a4503.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Anta att det intr\u00e4ffade ett komplicerat fel vid bearbetning av tre uppgifter: bearbetare 1 kraschade efter att ha f\u00e5tt uppgiften utan att hinna meddela utbytespunkten. I detta fall kommer utbytespunkten, efter att ack timeout har l\u00f6pt ut, att \u00f6verf\u00f6ra uppgiften till en annan bearbetare. Bearbetare 3 avstod fr\u00e5n uppgiften av n\u00e5gon anledning och skickade nack, vilket resulterade i att uppgiften \u00e4ven \u00f6verf\u00f6rdes till en annan bearbetare som framg\u00e5ngsrikt genomf\u00f6rde den.<\/p>\n<p><\/p>\n<h2 id=\"predvaritelnyy-itog\">Prelimin\u00e4rt resultat<\/h2>\n<p><\/p>\n<p>Vi har behandlat de grundl\u00e4ggande byggstenarna i distribuerade system och f\u00e5tt en grundl\u00e4ggande f\u00f6rst\u00e5else f\u00f6r deras till\u00e4mpningar i Erlang\/Elixir.<\/p>\n<p><\/p>\n<p>Genom att kombinera grundl\u00e4ggande mallar kan man bygga komplexa paradigmer f\u00f6r att l\u00f6sa uppkommande problem.<\/p>\n<p><\/p>\n<p>I den avslutande delen av cykeln kommer vi att diskutera allm\u00e4nna fr\u00e5gor om organisation av tj\u00e4nster, ruttningssystem och belastningsbalansering, samt prata om de praktiska aspekterna av skalbarhet och motst\u00e5ndskraft hos system.<\/p>\n<p><\/p>\n<p>Slutet av del tv\u00e5.<\/p>\n<p><\/p>\n<p>Foto <noindex>Marius Christensen<\/noindex><br \/>\nIllustrationer skapade med hj\u00e4lp av websequencediagrams.com<\/p>\n<p>K\u00e4lla: <a content=\"nofollow\" rel=\"nofollow\" href=\"https:\/\/habr.com\/ru\/post\/446108\/\">habr.com<\/a><\/p>","protected":false,"gt_translate_keys":[{"key":"rendered","format":"html"}]},"excerpt":{"rendered":"<p>\u0412 \u043f\u0440\u043e\u0448\u043b\u043e\u0439 \u0441\u0442\u0430\u0442\u044c\u0435 \u043c\u044b \u0440\u0430\u0437\u043e\u0431\u0440\u0430\u043b\u0438 \u0442\u0435\u043e\u0440\u0435\u0442\u0438\u0447\u0435\u0441\u043a\u0438\u0435 \u043e\u0441\u043d\u043e\u0432\u044b \u0440\u0435\u0430\u043a\u0442\u0438\u0432\u043d\u043e\u0439 \u0430\u0440\u0445\u0438\u0442\u0435\u043a\u0442\u0443\u0440\u044b. \u041f\u0440\u0438\u0448\u043b\u043e \u0432\u0440\u0435\u043c\u044f \u043f\u043e\u0433\u043e\u0432\u043e\u0440\u0438\u0442\u044c \u043e \u043f\u043e\u0442\u043e\u043a\u0430\u0445 \u0434\u0430\u043d\u043d\u044b\u0445, \u043f\u0443\u0442\u044f\u0445 \u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u0438 \u0440\u0435\u0430\u043a\u0442\u0438\u0432\u043d\u044b\u0445 Erlang\/Elixir \u0441\u0438\u0441\u0442\u0435\u043c \u0438 \u0448\u0430\u0431\u043b\u043e\u043d\u0430\u0445 \u043e\u0431\u043c\u0435\u043d\u0430 \u0441\u043e\u043e\u0431\u0449\u0435\u043d\u0438\u044f\u043c\u0438 \u0432 \u043d\u0438\u0445: Request-response Request-Chunked Response Response with Request Publish-subscribe Inverted Publish-subscribe Task distribution SOA, MSA \u0438 \u043e\u0431\u043c\u0435\u043d \u0441\u043e\u043e\u0431\u0449\u0435\u043d\u0438\u044f\u043c\u0438 SOA, MSA \u2013 \u0441\u0438\u0441\u0442\u0435\u043c\u043d\u044b\u0435 \u0430\u0440\u0445\u0438\u0442\u0435\u043a\u0442\u0443\u0440\u044b, \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u044f\u044e\u0449\u0438\u0435 \u043f\u0440\u0430\u0432\u0438\u043b\u0430 \u043f\u043e\u0441\u0442\u0440\u043e\u0435\u043d\u0438\u044f \u0441\u0438\u0441\u0442\u0435\u043c, \u0432 \u0442\u043e \u0432\u0440\u0435\u043c\u044f \u043a\u0430\u043a [&hellip;]<\/p>\n","protected":false,"gt_translate_keys":[{"key":"rendered","format":"html"}]},"author":1,"featured_media":22886,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[688],"tags":[],"class_list":["post-30908","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-administrirovanie"],"aioseo_notices":[],"aioseo_head":"\n\t\t<!-- All in One SEO 5.0.4 - aioseo.com -->\n\t<meta name=\"robots\" content=\"max-image-preview:large\" \/>\n\t<meta name=\"author\" content=\"Yuri Gagarin\"\/>\n\t<link rel=\"canonical\" href=\"https:\/\/prohoster.info\/sv\/blog\/administrirovanie\/stroitelnye-bloki-raspredelennyh-prilozhenij-pervoe-priblizhenie\" \/>\n\t\t<meta name=\"generator\" content=\"All in One SEO (AIOSEO) 5.0.4\" \/>\n\t\t<meta property=\"og:locale\" content=\"sv_SE\" \/>\n\t\t<meta property=\"og:site_name\" content=\"ProHoster | \u041a\u0443\u043f\u0438\u0442\u044c \u043d\u0430\u0434\u0435\u0436\u043d\u044b\u0439 \u0445\u043e\u0441\u0442\u0438\u043d\u0433 \u0434\u043b\u044f \u0441\u0430\u0439\u0442\u043e\u0432 \u0441 \u0437\u0430\u0449\u0438\u0442\u043e\u0439 \u043e\u0442 DDoS, VPS VDS \u0441\u0435\u0440\u0432\u0435\u0440\u044b\" \/>\n\t\t<meta property=\"og:type\" content=\"article\" \/>\n\t\t<meta property=\"og:title\" content=\"\ud83e\udd47\u0421\u0442\u0440\u043e\u0438\u0442\u0435\u043b\u044c\u043d\u044b\u0435 \u0431\u043b\u043e\u043a\u0438 \u0440\u0430\u0441\u043f\u0440\u0435\u0434\u0435\u043b\u0435\u043d\u043d\u044b\u0445 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0439. \u041f\u0435\u0440\u0432\u043e\u0435 \u043f\u0440\u0438\u0431\u043b\u0438\u0436\u0435\u043d\u0438\u0435 | ProHoster\" \/>\n\t\t<meta property=\"og:url\" content=\"https:\/\/prohoster.info\/sv\/blog\/administrirovanie\/stroitelnye-bloki-raspredelennyh-prilozhenij-pervoe-priblizhenie\" \/>\n\t\t<meta property=\"og:image\" content=\"https:\/\/prohoster.info\/wp-content\/uploads\/2021\/11\/logo-350.jpg\" \/>\n\t\t<meta property=\"og:image:secure_url\" content=\"https:\/\/prohoster.info\/wp-content\/uploads\/2021\/11\/logo-350.jpg\" \/>\n\t\t<meta property=\"og:image:width\" content=\"350\" \/>\n\t\t<meta property=\"og:image:height\" content=\"350\" \/>\n\t\t<meta property=\"article:published_time\" content=\"2019-10-31T18:38:07+00:00\" \/>\n\t\t<meta property=\"article:modified_time\" content=\"2019-10-31T18:38:07+00:00\" \/>\n\t\t<meta property=\"article:publisher\" content=\"https:\/\/www.facebook.com\/prohoster\" \/>\n\t\t<meta property=\"article:author\" content=\"https:\/\/www.facebook.com\/prohoster\" \/>\n\t\t<!-- All in One SEO -->\n\n","aioseo_head_json":{"title":"\ud83e\udd47Byggblock f\u00f6r distribuerade applikationer. F\u00f6rsta approximationen | ProHoster","description":"","canonical_url":"https:\/\/prohoster.info\/sv\/blog\/administrirovanie\/stroitelnye-bloki-raspredelennyh-prilozhenij-pervoe-priblizhenie","robots":"max-image-preview:large","keywords":"","webmasterTools":{"miscellaneous":""},"schema":null,"og:locale":"sv_SE","og:site_name":"ProHoster | \u041a\u0443\u043f\u0438\u0442\u044c \u043d\u0430\u0434\u0435\u0436\u043d\u044b\u0439 \u0445\u043e\u0441\u0442\u0438\u043d\u0433 \u0434\u043b\u044f \u0441\u0430\u0439\u0442\u043e\u0432 \u0441 \u0437\u0430\u0449\u0438\u0442\u043e\u0439 \u043e\u0442 DDoS, VPS VDS \u0441\u0435\u0440\u0432\u0435\u0440\u044b","og:type":"article","og:title":"\ud83e\udd47\u0421\u0442\u0440\u043e\u0438\u0442\u0435\u043b\u044c\u043d\u044b\u0435 \u0431\u043b\u043e\u043a\u0438 \u0440\u0430\u0441\u043f\u0440\u0435\u0434\u0435\u043b\u0435\u043d\u043d\u044b\u0445 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0439. \u041f\u0435\u0440\u0432\u043e\u0435 \u043f\u0440\u0438\u0431\u043b\u0438\u0436\u0435\u043d\u0438\u0435 | ProHoster","og:url":"https:\/\/prohoster.info\/sv\/blog\/administrirovanie\/stroitelnye-bloki-raspredelennyh-prilozhenij-pervoe-priblizhenie","og:image":"https:\/\/prohoster.info\/wp-content\/uploads\/2021\/11\/logo-350.jpg","og:image:secure_url":"https:\/\/prohoster.info\/wp-content\/uploads\/2021\/11\/logo-350.jpg","og:image:width":350,"og:image:height":350,"article:published_time":"2019-10-31T18:38:07+00:00","article:modified_time":"2019-10-31T18:38:07+00:00","article:publisher":"https:\/\/www.facebook.com\/prohoster","article:author":"https:\/\/www.facebook.com\/prohoster"},"aioseo_meta_data":{"post_id":"30908","title":null,"description":null,"keywords":null,"keyphrases":null,"primary_term":null,"canonical_url":null,"og_title":null,"og_description":null,"og_object_type":"default","og_image_type":"default","og_image_url":null,"og_image_width":null,"og_image_height":null,"og_image_custom_url":null,"og_image_custom_fields":null,"og_video":null,"og_custom_url":null,"og_article_section":null,"og_article_tags":null,"twitter_use_og":false,"twitter_card":"default","twitter_image_type":"default","twitter_image_url":null,"twitter_image_custom_url":null,"twitter_image_custom_fields":null,"twitter_title":null,"twitter_description":null,"schema":{"blockGraphs":[],"customGraphs":[],"default":{"data":{"Article":[],"Course":[],"Dataset":[],"FAQPage":[],"Movie":[],"Person":[],"Product":[],"ProductReview":[],"Car":[],"Recipe":[],"Service":[],"SoftwareApplication":[],"WebPage":[]},"graphName":"","isEnabled":true},"graphs":[]},"schema_type":null,"schema_type_options":null,"pillar_content":false,"robots_default":true,"robots_noindex":false,"robots_noarchive":false,"robots_nosnippet":false,"robots_nofollow":false,"robots_noimageindex":false,"robots_noodp":false,"robots_notranslate":false,"robots_max_snippet":null,"robots_max_videopreview":null,"robots_max_imagepreview":"large","priority":null,"frequency":null,"local_seo":null,"seo_analyzer_scan_date":"2026-02-22 15:33:36","breadcrumb_settings":null,"limit_modified_date":false,"reviewed_by":null,"ai":null,"created":"2021-03-01 03:27:06","updated":"2026-02-22 15:33:36","focus_keyword":null,"additional_keywords":null,"truseo_locale":null},"gt_translate_keys":[{"key":"link","format":"url"}],"_links":{"self":[{"href":"https:\/\/prohoster.info\/sv\/wp-json\/wp\/v2\/posts\/30908","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/prohoster.info\/sv\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/prohoster.info\/sv\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/prohoster.info\/sv\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/prohoster.info\/sv\/wp-json\/wp\/v2\/comments?post=30908"}],"version-history":[{"count":1,"href":"https:\/\/prohoster.info\/sv\/wp-json\/wp\/v2\/posts\/30908\/revisions"}],"predecessor-version":[{"id":162009,"href":"https:\/\/prohoster.info\/sv\/wp-json\/wp\/v2\/posts\/30908\/revisions\/162009"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/prohoster.info\/sv\/wp-json\/wp\/v2\/media\/22886"}],"wp:attachment":[{"href":"https:\/\/prohoster.info\/sv\/wp-json\/wp\/v2\/media?parent=30908"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/prohoster.info\/sv\/wp-json\/wp\/v2\/categories?post=30908"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/prohoster.info\/sv\/wp-json\/wp\/v2\/tags?post=30908"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}