{"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\/de\/blog\/administrirovanie\/stroitelnye-bloki-raspredelennyh-prilozhenij-pervoe-priblizhenie","title":{"rendered":"Bausteine verteilt Anwendungen. Erste N\u00e4herung","gt_translate_keys":[{"key":"rendered","format":"text"}]},"content":{"rendered":"<p><img decoding=\"async\" alt=\"Bausteine verteilt Anwendungen. Erste N\u00e4herung\" src=\"\/wp-content\/uploads\/2019\/04\/7ef485e452075775ce317b557671274c.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Letzte Woche <noindex><a rel=\"nofollow\" href=\"https:\/\/habr.com\/ru\/post\/446028\/\">Artikel<\/a><\/noindex> Wir haben die theoretischen Grundlagen der reaktiven Architektur behandelt. Es ist Zeit, \u00fcber Datenstr\u00f6me, die Implementation von reaktiven Erlang\/Elixir-Systemen und die Kommunikationsmuster zu sprechen:<\/p>\n<p><\/p>\n<ul>\n<li>Request-Response<\/li>\n<li>Request-Chunked Response<\/li>\n<li>Response mit Request<\/li>\n<li>Publish-Subscribe<\/li>\n<li>Inverted Publish-Subscribe<\/li>\n<li>Aufgabenverteilung<noindex><a rel=\"nofollow\" name=\"habracut\"><\/a><\/noindex><\/li>\n<\/ul>\n<p><\/p>\n<h2 id=\"soa-msa-i-obmen-soobscheniyami\">SOA, MSA und Nachrichten\u00fcbermittlung<\/h2>\n<p><\/p>\n<p>SOA und MSA sind Systemarchitekturen, die die Regeln zum Aufbau von Systemen definieren, w\u00e4hrend Messaging Primtivit\u00e4ten f\u00fcr deren Umsetzung bereitstellt.<\/p>\n<p><\/p>\n<p>Ich m\u00f6chte keine bestimmte Architektur propagieren. Ich bef\u00fcrworte die Anwendung der f\u00fcr das jeweilige Projekt und Gesch\u00e4ft effektivsten und n\u00fctzlichsten Praktiken. Welche Paradigmen auch immer wir w\u00e4hlen, es ist besser, systemische Bausteine im Sinne des Unix-Ansatzes zu schaffen: Komponenten mit minimaler Kopplung, die f\u00fcr einzelne Entit\u00e4ten verantwortlich sind. API-Methoden f\u00fchren einfachste Aktionen mit diesen Entit\u00e4ten aus.<\/p>\n<p><\/p>\n<p>Messaging \u2012 wie der Name schon sagt \u2012 ist ein Nachrichtenbroker. Sein Hauptziel ist es, Nachrichten zu empfangen und zu senden. Es ist verantwortlich f\u00fcr die Schnittstellen zur Informations\u00fcbertragung, die Bildung logischer Informationskan\u00e4le innerhalb des Systems, das Routing und die Lastverteilung sowie die Fehlerbehandlung auf Systemebene.<br \/>\nDas entwickelte Messaging versucht nicht, mit RabbitMQ zu konkurrieren oder es zu ersetzen. Seine Hauptmerkmale:<\/p>\n<p><\/p>\n<ul>\n<li>Verteilung.<br \/>\nAustauschpunkte k\u00f6nnen auf allen Knoten des Clusters, m\u00f6glichst nah am Code, der sie verwendet, erstellt werden.<\/li>\n<li>Einfachheit.<br \/>\nFokus auf die Minimierung von Boilerplate-Code und Benutzerfreundlichkeit.<\/li>\n<li>Bessere Leistung.<br \/>\nWir versuchen nicht, die Funktionalit\u00e4t von RabbitMQ zu wiederholen, sondern heben lediglich die architektonische und transporttechnische Schicht hervor, die wir sehr einfach in OTP integrieren, um die Kosten zu minimieren.<\/li>\n<li>Flexibilit\u00e4t.<br \/>\nJeder Dienst kann viele Austauschmuster kombinieren.<\/li>\n<li>Fehlertoleranz, die in das Design integriert ist.<\/li>\n<li>Skalierbarkeit.<br \/>\nMessaging w\u00e4chst mit der Anwendung. Mit zunehmender Last k\u00f6nnen Austauschpunkte auf separate Maschinen ausgelagert werden.<\/li>\n<\/ul>\n<p><\/p>\n<p><em>Anmerkung.<\/em> Aus Sicht der Code-Organisation sind Metaprojekte f\u00fcr komplexe Systeme in Erlang\/Elixir gut geeignet. Der gesamte Code des Projekts befindet sich in einem einzigen Repository \u2013 dem \u00fcbergeordneten Projekt. Dabei sind die Mikrodienste maximal isoliert und f\u00fchren einfache Operationen aus, die f\u00fcr eine einzelne Entit\u00e4t zust\u00e4ndig sind. Mit diesem Ansatz ist es einfach, die API des gesamten Systems zu pflegen, \u00c4nderungen vorzunehmen und Unit- sowie Integrationstests zu schreiben.<\/p>\n<p><\/p>\n<p>Die Komponenten des Systems interagieren entweder direkt oder \u00fcber einen Broker. Aus der Perspektive des Messaging hat jeder Dienst mehrere Lebensphasen:<\/p>\n<p><\/p>\n<ul>\n<li>Initialisierung des Dienstes.<br \/>\nIn diesem Stadium erfolgt die Konfiguration und der Start des ausf\u00fchrenden Dienstprozesses und dessen Abh\u00e4ngigkeiten.<\/li>\n<li>Einrichtung eines Austauschpunkts.<br \/>\nDer Dienst kann einen statischen Austauschpunkt verwenden, der in der Konfiguration des Knotens festgelegt ist, oder er kann Austauschpunkte dynamisch erstellen. <\/li>\n<li>Registrierung des Dienstes.<br \/>\nDamit der Dienst Anfragen bearbeiten kann, muss er am Austauschpunkt registriert werden.<\/li>\n<li>Regelm\u00e4\u00dfiger Betrieb.<br \/>\nDer Dienst f\u00fchrt n\u00fctzliche Arbeiten aus.<\/li>\n<li>Beendigung der Arbeit.<br \/>\nEs gibt zwei Arten der Beendigung: regul\u00e4r und abrupt. Bei regul\u00e4rer Beendigung wird der Dienst vom Austauschpunkt getrennt und gestoppt. In Notf\u00e4llen f\u00fchrt das Messaging eines der Szenarien zur Fehlerbehandlung aus.<\/li>\n<\/ul>\n<p><\/p>\n<p>Es sieht ziemlich kompliziert aus, aber im Code ist nicht alles so schlimm. Codebeispiele mit Kommentaren werden sp\u00e4ter bei der Analyse der Muster vorgestellt.<\/p>\n<p><\/p>\n<h2 id=\"exchanges\">Exchanges<\/h2>\n<p><\/p>\n<p>Der Austauschpunkt ist ein Messaging-Prozess, der die Logik der Interaktion mit den Komponenten im Rahmen des Messaging-Mustertyps umsetzt. In allen unten dargestellten Beispielen interagieren die Komponenten \u00fcber Austauschpunkte, deren Kombination das Messaging bildet.<\/p>\n<p><\/p>\n<h2 id=\"message-exchange-patterns-meps\">Message Exchange Patterns (MEPs)<\/h2>\n<p><\/p>\n<p>Global k\u00f6nnen die Austauschmuster in bidirektionale und unidirektionale unterteilt werden. Erstere setzen eine Antwort auf die eingegangene Nachricht voraus, letztere nicht. Ein klassisches Beispiel f\u00fcr ein bidirektionales Muster in einer Client-Server-Architektur ist das Request-Response-Muster. Lassen Sie uns das Muster und seine Modifikationen untersuchen.<\/p>\n<p><\/p>\n<h3 id=\"requestresponse-ili-rpc\">Request\u2013Response oder RPC<\/h3>\n<p><\/p>\n<p>RPC wird verwendet, wenn wir eine Antwort von einem anderen Prozess ben\u00f6tigen. Dieser Prozess kann auf demselben Knoten oder auf einem anderen Kontinent ausgef\u00fchrt werden. Unten ist das Schema der Interaktion zwischen dem Client und <a class=\"wpil_keyword_link\" href=\"https:\/\/prohoster.info\/de\/server\/dts-los-angeles\/\"   title=\"Server\" data-wpil-keyword-link=\"linked\"  data-wpil-monitor-id=\"3483\">Server<\/a> \u00fcber Messaging.<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Bausteine verteilt Anwendungen. Erste N\u00e4herung\" src=\"\/wp-content\/uploads\/2019\/04\/091725fc108d6ce1a5fc9ae866e2c395.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Da das Messaging vollst\u00e4ndig asynchron ist, wird der Austausch f\u00fcr den Client in zwei Phasen unterteilt:<\/p>\n<p><\/p>\n<ol>\n<li>\n<p>Anfrage senden<\/p>\n<p><\/p>\n<pre><code class=\"erlang\">messaging:request(Exchange, ResponseMatchingTag, RequestDefinition, HandlerProcess).<\/code><\/pre>\n<p><\/p>\n<p><em>Austausch<\/em> \u2012 einzigartiger Name des Austauschpunkts<br \/>\n<em>ResponseMatchingTag<\/em> \u2012 lokales Tag zur Verarbeitung der Antwort. Zum Beispiel im Fall der Sendung mehrerer identischer Anfragen, die verschiedenen Benutzern geh\u00f6ren.<br \/>\n<em>RequestDefinition<\/em> \u2012 Anfragek\u00f6rper<br \/>\n<em>HandlerProcess<\/em> \u2012 PID des Handlers. Dieser Prozess erh\u00e4lt die Antwort vom Server.<\/p>\n<p>\n<\/li>\n<li>\n<p>Antwortverarbeitung<\/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 Serverantwort.<\/p>\n<p>\n<\/li>\n<\/ol>\n<p><\/p>\n<p>F\u00fcr den Server besteht der Prozess ebenfalls aus 2 Phasen:<\/p>\n<p><\/p>\n<ol>\n<li>Initialisierung des Austauschpunkts<\/li>\n<li>Verarbeitung der eingehenden Anfragen<\/li>\n<\/ol>\n<p><\/p>\n<p>Illustrieren wir dieses Muster mit code. Angenommen, wir m\u00fcssen einen einfachen Dienst implementieren, der eine einzige Methode zur genauen Zeit bereitstellt.<\/p>\n<p><\/p>\n<h4 id=\"kod-servera\">Servercode<\/h4>\n<p><\/p>\n<p>Lass uns die API-Definition des Dienstes in api.hrl auslagern:<\/p>\n<p><\/p>\n<pre><code class=\"erlang\">%% =====================================================\n%%  entities\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%%  methods\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>Definieren wir den Dienst-Controller in time_controller.erl<\/p>\n<p><\/p>\n<pre><code class=\"erlang\">%% Im Beispiel wird nur der wesentliche Code gezeigt. Indem wir ihn in das gen_server-Muster einf\u00fcgen, k\u00f6nnen wir einen funktionierenden Dienst erhalten.\n\n%% Initialisierung von gen_server\ninit(Args) -&gt;\n  %% Verbindung zum Austauschpunkt\n  messaging:monitor_exchange(req_resp, ?EXCHANGE, default, self())\n  {ok, #{}}.\n\n%% Verarbeitung des Ereignisses eines Verbindungsverlusts zum Austauschpunkt. Dasselbe Ereignis tritt auf, wenn der Austauschpunkt noch nicht gestartet ist.\nhandle_info(#exchange_die{exchange = ?EXCHANGE}, State) -&gt;\n  erlang:send(self(), monitor_exchange),\n  {noreply, State};\n\n%% Verarbeitung der 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%% Beendigung der gen_server-Arbeit\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\">Client-Code<\/h4>\n<p><\/p>\n<p>Um eine Anfrage an den Dienst zu senden, kann an beliebiger Stelle im Client die messaging request API aufgerufen werden:<\/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; %% Wiederholungs- oder Fehlerlogik\nend<\/code><\/pre>\n<p><\/p>\n<p>In einem verteilten System kann die Konfiguration der Komponenten unterschiedlich sein und zum Zeitpunkt der Anfrage kann die messaging noch nicht gestartet sein oder der Dienst-Controller ist m\u00f6glicherweise nicht bereit, die Anfrage zu bearbeiten. Daher m\u00fcssen wir die Antwort der messaging \u00fcberpr\u00fcfen und den Fall eines Fehlers behandeln.<br \/>\nNach erfolgreicher Sendung erh\u00e4lt der Client eine Antwort oder einen Fehler vom Dienst.<br \/>\nBehandeln wir beide F\u00e4lle in 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\">Request-Chunked Response<\/h3>\n<p><\/p>\n<p>Es ist besser, keine riesigen Nachrichten zu \u00fcbermitteln. Das beeinflusst die Reaktionsf\u00e4higkeit und die stabile Funktionsweise des gesamten Systems. Wenn die Antwort auf eine Anfrage viel Speicher ben\u00f6tigt, ist eine Aufteilung in Teile erforderlich.<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Bausteine verteilt Anwendungen. Erste N\u00e4herung\" src=\"\/wp-content\/uploads\/2019\/04\/bd60742a933a8e4e3eeaf7f4adf00f2a.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Hier sind ein paar Beispiele f\u00fcr solche F\u00e4lle:<\/p>\n<p><\/p>\n<ul>\n<li>Komponenten tauschen Bin\u00e4rdaten, wie Dateien, aus. Die Aufteilung der Antwort in kleinere Teile hilft, effizient mit Dateien jeder Gr\u00f6\u00dfe zu arbeiten und ein Speicher\u00fcberlauf zu vermeiden.<\/li>\n<li>Listen. Zum Beispiel m\u00fcssen wir alle Datens\u00e4tze aus einer riesigen Tabelle in der Datenbank ausw\u00e4hlen und an eine andere Komponente \u00fcbermitteln.<\/li>\n<\/ul>\n<p><\/p>\n<p>Ich nenne solche Antworten einen Zug. In jedem Fall sind 1024 Nachrichten zu je 1 MB besser als eine einzige Nachricht von 1 GB. <\/p>\n<p><\/p>\n<p>In einem Erlang-Cluster erzielen wir einen zus\u00e4tzlichen Vorteil \u2013 die Reduzierung der Belastung an der Austauschstelle und im Netzwerk, da die Antworten sofort an den Empf\u00e4nger gesendet werden, ohne die Austauschstelle zu passieren.<\/p>\n<p><\/p>\n<h3 id=\"response-with-request\">Response mit Request<\/h3>\n<p><\/p>\n<p>Dies ist eine recht seltene Modifikation des RPC-Musters zum Aufbau dialogorientierter Systeme.<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Bausteine verteilt Anwendungen. Erste N\u00e4herung\" 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\">Publish-Subscribe (Datenverteilung Baum)<\/h3>\n<p><\/p>\n<p>Ereignisgesteuerte Systeme liefern Daten an Verbraucher, sobald sie bereit sind. Dadurch tendieren die Systeme eher zu einem Push-Modell als zu Pull- oder Poll-Modellen. Diese Eigenschaft verhindert, dass Ressourcen unn\u00f6tig verschwendet werden, indem st\u00e4ndig Daten angefordert und erwartet werden.<br \/>\nDie Abbildung zeigt den Prozess der Verbreitung der Nachricht an die Verbraucher, die sich f\u00fcr ein bestimmtes Thema angemeldet haben.<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Bausteine verteilt Anwendungen. Erste N\u00e4herung\" src=\"\/wp-content\/uploads\/2019\/04\/e211d5dcfeb5ce8513699eac8e3b6d84.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Klassische Beispiele f\u00fcr die Verwendung dieses Musters sind die Verbreitung von Zust\u00e4nden: Spielwelten in Computerspielen, Marktdaten an B\u00f6rsen, n\u00fctzliche Informationen in Datenfeeds.<\/p>\n<p><\/p>\n<p>Betrachten wir den Code des Abonnenten:<\/p>\n<p><\/p>\n<pre><code class=\"erlang\">init(_Args) -&gt;\n  %% wir abonnieren den Austausch, Schl\u00fcssel = key\n  messaging:subscribe(?SUBSCRIPTION, key, tag, self()),\n  {ok, #{}}.\n\nhandle_info(#exchange_die{exchange = ?SUBSCRIPTION}, State) -&gt;\n  %% wenn die Austauschstelle nicht verf\u00fcgbar ist, versuchen wir, uns erneut zu verbinden\n  messaging:subscribe(?SUBSCRIPTION, key, tag, self()),\n  {noreply, State};\n\n%% wir verarbeiten die eingehenden Nachrichten\nhandle_info(#'$msg'{exchange = ?SUBSCRIPTION, message = Msg}, State) -&gt;\n  ?debugVal(Msg),\n  {noreply, State};\n\n%% beim Stoppen des Verbrauchers trennen wir uns von der Austauschstelle\nterminate(_Reason, _State) -&gt;\n  messaging:unsubscribe(?SUBSCRIPTION, key, tag, self()),\n  ok.<\/code><\/pre>\n<p><\/p>\n<p>Die Quelle kann die Funktion zum Ver\u00f6ffentlichen von Nachrichten an beliebiger Stelle aufrufen:<\/p>\n<p><\/p>\n<pre><code class=\"erlang\">messaging:publish_message(Exchange, Key, Message).<\/code><\/pre>\n<p><\/p>\n<p><em>Austausch<\/em> \u2012 Name des Austauschpunkts,<br \/>\n<em>Schl\u00fcssel<\/em> \u2012 Routing-Schl\u00fcssel<br \/>\n<em>Nachricht<\/em> \u2012 Payload<\/p>\n<p><\/p>\n<h2 id=\"inverted-publish-subscribe\">Inverted Publish-Subscribe<\/h2>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Bausteine verteilt Anwendungen. Erste N\u00e4herung\" src=\"\/wp-content\/uploads\/2019\/04\/2ef7cd7de459455937bdcfa8a11fd028.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Durch die Einf\u00fchrung von Pub-Sub kann ein Muster erzielt werden, das sich zum Logging eignet. Die Sammlung von Quellen und Verbrauchern kann vollkommen unterschiedlich sein. Im Bild ist ein Fall mit einem Verbraucher und mehreren Quellen dargestellt.<\/p>\n<p><\/p>\n<h2 id=\"task-distribution-pattern\">Task-Verteilungsmuster<\/h2>\n<p><\/p>\n<p>In fast jedem Projekt gibt es Aufgaben zur verz\u00f6gerten Verarbeitung, wie zum Beispiel das Erstellen von Berichten, das Versenden von Benachrichtigungen und das Abrufen von Daten aus externen Systemen. Die Kapazit\u00e4t des Systems, das diese Aufgaben ausf\u00fchrt, kann leicht durch das Hinzuf\u00fcgen von Handlern skaliert werden. Alles, was wir tun m\u00fcssen, ist, einen Cluster von Handlern zu bilden und die Aufgaben gleichm\u00e4\u00dfig zwischen ihnen zu verteilen.<\/p>\n<p><\/p>\n<p>Betrachten wir die auftretenden Situationen am Beispiel von 3 Handlern. Bereits in der Phase der Aufgabenverteilung stellt sich die Frage der Fairness der Verteilung und der \u00dcberlastung der Handler. F\u00fcr die Fairness wird eine Round-Robin-Verteilung sorgen, um \u00dcberlastung der Handler zu vermeiden, f\u00fchren wir eine Begrenzung ein <em>prefetch_limit<\/em>. In \u00dcbergangsmodi <em>prefetch_limit<\/em> wird es einem Handler nicht erm\u00f6glichen, alle Aufgaben zu erhalten.<\/p>\n<p><\/p>\n<p>Messaging verwaltet Warteschlangen und Priorit\u00e4ten bei der Verarbeitung. Handler erhalten Aufgaben, sobald sie anfallen. Die Ausf\u00fchrung einer Aufgabe kann erfolgreich abgeschlossen werden oder fehlschlagen:<\/p>\n<p><\/p>\n<ul>\n<li><code>messaging:ack(Tack)<\/code> \u2012 wird im Falle einer erfolgreichen Verarbeitung der Nachricht aufgerufen<\/li>\n<li><code>messaging:nack(Tack)<\/code> \u2012 wird in allen Ausnahmef\u00e4llen aufgerufen. Nach der R\u00fcckgabe der Aufgabe wird messaging sie an einen anderen Handler weitergeben.<\/li>\n<\/ul>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Bausteine verteilt Anwendungen. Erste N\u00e4herung\" src=\"\/wp-content\/uploads\/2019\/04\/c2c632b6411247ee8b0dcfb3250a4503.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Angenommen, w\u00e4hrend der Verarbeitung von drei Aufgaben tritt ein komplexer Fehler auf: Handler 1 f\u00e4llt nach dem Erhalt der Aufgabe aus, ohne der Austauschstelle etwas mitgeteilt zu haben. In diesem Fall wird die Austauschstelle nach Ablauf der Ack-Timeout die Aufgabe an einen anderen Handler weitergeben. Handler 3 hat aus irgendeinem Grund die Aufgabe abgelehnt und nack gesendet, sodass die Aufgabe ebenfalls an einen anderen Handler \u00fcbergeben wurde, der sie erfolgreich ausgef\u00fchrt hat.<\/p>\n<p><\/p>\n<h2 id=\"predvaritelnyy-itog\">Vorl\u00e4ufiges Ergebnis<\/h2>\n<p><\/p>\n<p>Wir haben die grundlegenden Bausteine verteilter Systeme behandelt und ein grundlegendes Verst\u00e4ndnis ihrer Anwendung in Erlang\/Elixir gewonnen.<\/p>\n<p><\/p>\n<p>Durch die Kombination grundlegender Muster k\u00f6nnen komplexe Paradigmen zum L\u00f6sen auftretender Aufgaben aufgebaut werden.<\/p>\n<p><\/p>\n<p>Im abschlie\u00dfenden Teil des Zyklus werden wir allgemeine Fragen zur Organisation von Diensten, zur Routenf\u00fchrung und zum Lastenausgleich sowie zur praktischen Seite der Skalierbarkeit und Ausfallsicherheit von Systemen er\u00f6rtern.<\/p>\n<p><\/p>\n<p>Ende des zweiten Teils.<\/p>\n<p><\/p>\n<p>Foto <noindex>Marius Christensen<\/noindex><br \/>\nIllustrationen wurden mit Hilfe von websequencediagrams.com erstellt.<\/p>\n<p>Quelle: <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.1.1 - 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\/de\/blog\/administrirovanie\/stroitelnye-bloki-raspredelennyh-prilozhenij-pervoe-priblizhenie\" \/>\n\t<meta name=\"generator\" content=\"All in One SEO (AIOSEO) 5.0.1.1\" \/>\n\t\t<meta property=\"og:locale\" content=\"de_DE\" \/>\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\/de\/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\udd47Bausteine verteilter Anwendungen. Erste Ann\u00e4herung | ProHoster","description":"","canonical_url":"https:\/\/prohoster.info\/de\/blog\/administrirovanie\/stroitelnye-bloki-raspredelennyh-prilozhenij-pervoe-priblizhenie","robots":"max-image-preview:large","keywords":"","webmasterTools":{"miscellaneous":""},"schema":null,"og:locale":"de_DE","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\/de\/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\/de\/wp-json\/wp\/v2\/posts\/30908","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/prohoster.info\/de\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/prohoster.info\/de\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/prohoster.info\/de\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/prohoster.info\/de\/wp-json\/wp\/v2\/comments?post=30908"}],"version-history":[{"count":1,"href":"https:\/\/prohoster.info\/de\/wp-json\/wp\/v2\/posts\/30908\/revisions"}],"predecessor-version":[{"id":162009,"href":"https:\/\/prohoster.info\/de\/wp-json\/wp\/v2\/posts\/30908\/revisions\/162009"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/prohoster.info\/de\/wp-json\/wp\/v2\/media\/22886"}],"wp:attachment":[{"href":"https:\/\/prohoster.info\/de\/wp-json\/wp\/v2\/media?parent=30908"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/prohoster.info\/de\/wp-json\/wp\/v2\/categories?post=30908"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/prohoster.info\/de\/wp-json\/wp\/v2\/tags?post=30908"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}