{"id":80035,"date":"2020-05-02T13:42:54","date_gmt":"2020-05-02T11:42:54","guid":{"rendered":"https:\/\/prohoster.info\/blog\/administrirovanie\/udobnye-arhitekturnye-patterny"},"modified":"2020-05-02T13:42:54","modified_gmt":"2020-05-02T11:42:54","slug":"udobnye-arhitekturnye-patterny","status":"publish","type":"post","link":"https:\/\/prohoster.info\/de\/blog\/administrirovanie\/udobnye-arhitekturnye-patterny","title":{"rendered":"Praktische Architektur-Muster","gt_translate_keys":[{"key":"rendered","format":"text"}]},"content":{"rendered":"<p>Hallo, Habra!<\/p>\n<p><\/p>\n<p>Angesichts der aktuellen Ereignisse aufgrund des Coronavirus haben viele Internetdienste eine erh\u00f6hte Nachfrage erfahren. Zum Beispiel <noindex><a rel=\"nofollow\" href=\"https:\/\/www.independent.co.uk\/life-style\/gadgets-and-tech\/news\/coronavirus-ocado-down-app-website-stockpiling-food-online-delivery-a9402216.html\">hat eine der Einzelhandelsketten in Gro\u00dfbritannien einfach die Website f\u00fcr Online-Bestellungen gestoppt<\/a><\/noindex>, da die Kapazit\u00e4ten nicht ausreichten. Und es ist nicht immer m\u00f6glich, einen Server einfach durch leistungsst\u00e4rkere Hardware zu beschleunigen, jedoch m\u00fcssen die Kundenanfragen bearbeitet werden (oder sie wechseln zu den Konkurrenten).<\/p>\n<p><\/p>\n<p>In diesem Artikel werde ich kurz \u00fcber beliebte Praktiken sprechen, die es erm\u00f6glichen, einen schnellen und ausfallsicheren Dienst zu schaffen. Ich habe jedoch nur die Entwicklungsans\u00e4tze ausgew\u00e4hlt, die man jetzt <strong>einfach nutzen kann<\/strong>. F\u00fcr jeden Punkt haben Sie entweder bereits fertige Bibliotheken zur Verf\u00fcgung, oder Sie k\u00f6nnen das Problem mithilfe einer Cloud-Plattform l\u00f6sen.<\/p>\n<p><noindex><a rel=\"nofollow\" name=\"habracut\"><\/a><\/noindex><\/p>\n<h1 id=\"gorizontalnoe-masshtabirovanie\">Horizontale Skalierung<\/h1>\n<p><\/p>\n<p>Der einfachste und allgemein bekannte Punkt. Man kann grob sagen, dass es zwei h\u00e4ufig vorkommende Lastverteilungsans\u00e4tze \u2013 horizontale und vertikale Skalierung \u2013 gibt. <noindex><a rel=\"nofollow\" href=\"https:\/\/ru.wikipedia.org\/wiki\/%D0%9C%D0%B0%D1%81%D1%88%D1%82%D0%B0%D0%B1%D0%B8%D1%80%D1%83%D0%B5%D0%BC%D0%BE%D1%81%D1%82%D1%8C#%D0%93%D0%BE%D1%80%D0%B8%D0%B7%D0%BE%D0%BD%D1%82%D0%B0%D0%BB%D1%8C%D0%BD%D0%BE%D0%B5_%D0%BC%D0%B0%D1%81%D1%88%D1%82%D0%B0%D0%B1%D0%B8%D1%80%D0%BE%D0%B2%D0%B0%D0%BD%D0%B8%D0%B5\">Im ersten Fall<\/a><\/noindex> erlauben Sie es den Diensten, parallel zu arbeiten, wodurch die Last zwischen ihnen verteilt wird. <noindex><a rel=\"nofollow\" href=\"https:\/\/ru.wikipedia.org\/wiki\/%D0%9C%D0%B0%D1%81%D1%88%D1%82%D0%B0%D0%B1%D0%B8%D1%80%D1%83%D0%B5%D0%BC%D0%BE%D1%81%D1%82%D1%8C#%D0%92%D0%B5%D1%80%D1%82%D0%B8%D0%BA%D0%B0%D0%BB%D1%8C%D0%BD%D0%BE%D0%B5_%D0%BC%D0%B0%D1%81%D1%88%D1%82%D0%B0%D0%B1%D0%B8%D1%80%D0%BE%D0%B2%D0%B0%D0%BD%D0%B8%D0%B5\">Im zweiten<\/a><\/noindex> bestellen Sie leistungsst\u00e4rkere Server oder optimieren den Code.<\/p>\n<p><\/p>\n<p>Als Beispiel nehme ich einen abstrakten Cloud-Speicher f\u00fcr Dateien, also eine Art \u00c4quivalent zu OwnCloud, OneDrive und so weiter.<\/p>\n<p><\/p>\n<p>Das Standardbild eines solchen Schemas sehen Sie unten, es zeigt jedoch nur die Komplexit\u00e4t des Systems. Denn wir m\u00fcssen die Dienste irgendwie synchronisieren. Was passiert, wenn ein Benutzer eine Datei von seinem Tablet speichert und sie dann mit seinem Telefon anzeigen m\u00f6chte?<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Praktische Architektur-Muster\" src=\"\/wp-content\/uploads\/2020\/05\/7512c6d8783f5e0a38cc0861b01e54c8.png\" style=\"display:block;margin: 0 auto;\" \/><br \/>\nDer Unterschied zwischen den Ans\u00e4tzen: Bei der vertikalen Skalierung sind wir bereit, die Leistung der Knoten zu steigern, w\u00e4hrend wir bei der horizontalen Skalierung neue Knoten hinzuf\u00fcgen, um die Last zu verteilen.<\/p>\n<p><\/p>\n<h1 id=\"cqrs\">CQRS<\/h1>\n<p><\/p>\n<p><noindex><a rel=\"nofollow\" href=\"https:\/\/martinfowler.com\/bliki\/CQRS.html\">Command Query Responsibility Segregation<\/a><\/noindex> ist ein ziemlich wichtiges Muster, da es verschiedenen Clients nicht nur erm\u00f6glicht, sich mit verschiedenen Diensten zu verbinden, sondern auch gleiche Ereignisstr\u00f6me zu erhalten. Die Vorteile sind f\u00fcr einfache Anwendungen nicht so offensichtlich, aber es ist \u00e4u\u00dferst wichtig (und einfach) f\u00fcr stark ausgelastete Dienste. Das Wesentliche ist: Eingehende und ausgehende Datenstr\u00f6me sollten sich nicht \u00fcberschneiden. Das bedeutet, dass Sie eine Anfrage nicht senden und eine Antwort erwarten k\u00f6nnen; stattdessen senden Sie eine Anfrage an Dienst A, erhalten aber die Antwort von Dienst B.<\/p>\n<p><\/p>\n<p>Der erste Vorteil dieses Ansatzes ist die M\u00f6glichkeit, die Verbindung (im weitesten Sinne) w\u00e4hrend der Ausf\u00fchrung einer langwierigen Anfrage zu unterbrechen. Nehmen wir als Beispiel eine mehr oder weniger Standardabfolge:<\/p>\n<p><\/p>\n<ol>\n<li>Der Client hat eine Anfrage an den Server gesendet.<\/li>\n<li>Der Server hat die langwierige Verarbeitung gestartet.<\/li>\n<li>Der Server hat dem Client das Ergebnis zur\u00fcckgemeldet.<\/li>\n<\/ol>\n<p><\/p>\n<p>Angenommen, es gab in Punkt 2 einen Verbindungsabbruch (entweder wurde das Netzwerk neu verbunden oder der Benutzer wechselte zu einer anderen Seite und unterbrach die Verbindung). In diesem Fall wird es f\u00fcr den Server schwierig sein, dem Benutzer mitzuteilen, was genau verarbeitet wurde. Durch die Anwendung von CQRS wird die Abfolge jedoch etwas anders sein:<\/p>\n<p><\/p>\n<ol>\n<li>Der Client hat sich f\u00fcr Updates angemeldet.<\/li>\n<li>Der Client hat eine Anfrage an den Server gesendet.<\/li>\n<li>Der Server hat mit \"Anfrage akzeptiert\" geantwortet.<\/li>\n<li>Der Server hat das Ergebnis \u00fcber den Kanal aus Punkt \"1\" \u00fcbermittelt.<\/li>\n<\/ol>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Praktische Architektur-Muster\" src=\"\/wp-content\/uploads\/2020\/05\/8a00ea93eecc7cc0754122857c5f90d0.png\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Wie zu sehen ist, ist das Schema etwas komplexer. Dar\u00fcber hinaus fehlt der intuitive Ansatz von Anfrage und Antwort. Doch wie bereits erw\u00e4hnt, wird ein Verbindungsabbruch w\u00e4hrend der Verarbeitung der Anfrage nicht zu einem Fehler f\u00fchren. Au\u00dferdem, falls der Benutzer tats\u00e4chlich von mehreren Ger\u00e4ten mit dem Dienst verbunden ist (z.B. von einem Mobiltelefon und einem Tablet), kann sichergestellt werden, dass die Antwort auf beide Ger\u00e4te kommt.<\/p>\n<p><\/p>\n<p>Interessanterweise wird der Code zur Verarbeitung eingehender Nachrichten fast identisch (nicht zu 100%) f\u00fcr Ereignisse, die vom Client selbst beeinflusst werden, sowie f\u00fcr andere Ereignisse, einschlie\u00dflich solcher von anderen Clients.<\/p>\n<p><\/p>\n<p>In der Praxis erhalten wir jedoch zus\u00e4tzliche Vorteile, da der unidirektionale Fluss im funktionalen Stil verarbeitet werden kann (unter Verwendung von RX und \u00e4hnlichen Technologien). Das ist bereits ein erheblicher Vorteil, da die Anwendung im Grunde vollst\u00e4ndig reaktiv gestaltet werden kann, und das auch mit einem funktionalen Ansatz. F\u00fcr umfangreiche Programme kann dies die Ressourcen f\u00fcr Entwicklung und Wartung erheblich sparen.<\/p>\n<p><\/p>\n<p>Wenn wir diesen Ansatz mit horizontaler Skalierung kombinieren, erhalten wir die M\u00f6glichkeit, Anfragen an einen Server zu senden und die Antworten von einem anderen zu erhalten. Auf diese Weise kann der Client den f\u00fcr ihn passenden Dienst ausw\u00e4hlen, w\u00e4hrend das System innerlich die Ereignisse dennoch korrekt verarbeiten kann.<\/p>\n<p><\/p>\n<h1 id=\"event-sourcing\">Event Sourcing<\/h1>\n<p><\/p>\n<p>Wie Sie wissen, ist eine der Hauptmerkmale eines verteilten Systems das Fehlen einer gemeinsamen Zeit und eines gemeinsamen kritischen Abschnitts. F\u00fcr einen Prozess k\u00f6nnen Sie eine Synchronisation (mit denselben Mutexen) durchf\u00fchren, innerhalb derer Sie sicher sind, dass niemand sonst diesen Code ausf\u00fchrt. F\u00fcr ein verteiltes System ist das jedoch riskant, da dies mit Overhead verbunden ist und die gesamte Sch\u00f6nheit des Skalierens verloren geht \u2013 letzten Endes m\u00fcssen alle Komponenten auf eine warten.<\/p>\n<p><\/p>\n<p>Hieraus ergibt sich eine wichtige Erkenntnis \u2013 ein schnelles verteiltes System kann nicht synchronisiert werden, da wir sonst die Leistung verringern w\u00fcrden. Andererseits ist es oft notwendig, eine bestimmte Konsistenz der Komponenten zu gew\u00e4hrleisten. Und daf\u00fcr kann man den Ansatz mit <noindex><a rel=\"nofollow\" href=\"https:\/\/en.wikipedia.org\/wiki\/Eventual_consistency\">eventual consistency<\/a><\/noindex>, der gew\u00e4hrleistet, dass in Abwesenheit von Daten\u00e4nderungen nach einer bestimmten Zeitspanne nach der letzten Aktualisierung (\"letztlich\") alle Anfragen den zuletzt aktualisierten Wert zur\u00fcckgeben werden.<\/p>\n<p><\/p>\n<p>Es ist wichtig zu verstehen, dass f\u00fcr klassische Datenbanken h\u00e4ufig <noindex><a rel=\"nofollow\" href=\"https:\/\/en.wikipedia.org\/wiki\/Consistency_model#Strict_consistency\">strikte Konsistenz<\/a><\/noindex>, bei der jeder Knoten die gleiche Information besitzt (dies wird oft erreicht, wenn eine Transaktion erst als abgeschlossen betrachtet wird, nachdem der zweite Server geantwortet hat). Hier gibt es einige Erleichterungen durch Isolationsebenen, aber das Grundprinzip bleibt dasselbe \u2013 Sie k\u00f6nnen in einer vollst\u00e4ndig konsistenten Welt leben.<\/p>\n<p><\/p>\n<p>Kommen wir jedoch zur\u00fcck zur urspr\u00fcnglichen Aufgabe. Wenn ein Teil des Systems mit <noindex><a rel=\"nofollow\" href=\"https:\/\/en.wikipedia.org\/wiki\/Eventual_consistency\">eventual consistency<\/a><\/noindex>aufgebaut werden kann, dann kann das folgende Schema erstellt werden.<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Praktische Architektur-Muster\" src=\"\/wp-content\/uploads\/2020\/05\/33c80be6bc33bd897ca9b9e5525f9ae8.png\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Wichtige Merkmale dieses Ansatzes:<\/p>\n<p><\/p>\n<ul>\n<li>Jede eingehende Anfrage wird in eine Warteschlange eingef\u00fcgt.<\/li>\n<li>W\u00e4hrend der Verarbeitung einer Anfrage kann der Dienst auch Aufgaben in andere Warteschlangen einf\u00fcgen.<\/li>\n<li>Jedes eingehende Ereignis hat eine Identifikationsnummer (die f\u00fcr die Deduplication erforderlich ist).<\/li>\n<li>Die Warteschlange arbeitet ideologisch nach dem Prinzip \"append only\". Elemente k\u00f6nnen nicht entfernt oder umgestellt werden.<\/li>\n<li>Die Warteschlange arbeitet nach dem FIFO-Prinzip (entschuldigen Sie die Tautologie). Wenn Parallelverarbeitung erforderlich ist, sollten die Objekte in einer der Phasen in verschiedene Warteschlangen verschoben werden.<\/li>\n<\/ul>\n<p><\/p>\n<p>Ich erinnere daran, dass wir den Fall eines Online-Dateispeichers betrachten. In diesem Fall w\u00fcrde das System ungef\u00e4hr so aussehen:<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Praktische Architektur-Muster\" src=\"\/wp-content\/uploads\/2020\/05\/b95efb29545dcde1db9432d12d00a1b1.png\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Es ist wichtig, dass die in der Diagramm dargestellten Dienste nicht unbedingt einen separaten Server bedeuten. Selbst der Prozess kann derselbe sein. Wichtig ist etwas anderes: Ideologisch sind diese Dinge so getrennt, dass horizontale Skalierung einfach angewendet werden kann.<\/p>\n<p><\/p>\n<p>F\u00fcr zwei Benutzer w\u00fcrde das Diagramm folgenderma\u00dfen aussehen (Dienste, die f\u00fcr verschiedene Benutzer gedacht sind, sind farblich unterschiedlich gekennzeichnet):<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Praktische Architektur-Muster\" src=\"\/wp-content\/uploads\/2020\/05\/4c4aadc8b9dd505c3ad743e69fee4fae.png\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Die Vorteile einer solchen Kombination:<\/p>\n<p><\/p>\n<ul>\n<li>Die Informationsverarbeitungsdienste sind getrennt. Auch die Warteschlangen sind getrennt. Wenn wir die Kapazit\u00e4t des Systems erweitern m\u00fcssen, gen\u00fcgt es, mehr Dienste auf einer gr\u00f6\u00dferen Anzahl von Servern zu starten.<\/li>\n<li>Wenn wir Informationen vom Benutzer erhalten, m\u00fcssen wir nicht unbedingt auf die vollst\u00e4ndige Speicherung der Daten warten. Im Gegenteil, wir k\u00f6nnen einfach mit \"ok\" antworten und dann schrittweise beginnen, zu arbeiten. Gleichzeitig gl\u00e4ttet die Warteschlange die Spitzen, da die Hinzuf\u00fcgung eines neuen Objekts schnell erfolgt und der Benutzer nicht auf den gesamten Durchlauf durch den Zyklus warten muss.<\/li>\n<li>Zum Beispiel habe ich einen Deduplicierungsdienst hinzugef\u00fcgt, der versucht, identische Dateien zu kombinieren. Wenn er lange bei 1 % bleibt, wird der Kunde dies praktisch nicht bemerken (siehe oben), was ein gro\u00dfer Vorteil ist, da von uns nicht mehr eine hundertprozentige Geschwindigkeit und Zuverl\u00e4ssigkeit verlangt wird.<\/li>\n<\/ul>\n<p><\/p>\n<p>Es sind jedoch auch sofortige Nachteile sichtbar:<\/p>\n<p><\/p>\n<ul>\n<li>Unserem System fehlt strikte Konsistenz. Das bedeutet, dass man theoretisch bei der Anmeldung zu verschiedenen Diensten unterschiedliche Zust\u00e4nde erhalten kann (da einer der Dienste m\u00f6glicherweise nicht rechtzeitig die Benachrichtigung von der internen Warteschlange erh\u00e4lt). Ein weiteres Ergebnis davon ist, dass das System jetzt keine gemeinsame Zeit hat. Man kann die Ereignisse also nicht einfach nach der Ankunftszeit sortieren, da die Uhren zwischen den Servern m\u00f6glicherweise nicht synchron sind (dar\u00fcber hinaus ist die gleiche Zeit auf zwei Servern eine Utopie).<\/li>\n<li>Keine Ereignisse k\u00f6nnen jetzt einfach zur\u00fcckgesetzt werden (wie man es mit einer Datenbank tun k\u00f6nnte). Stattdessen muss ein neues Ereignis hinzugef\u00fcgt werden \u2014 <noindex><a rel=\"nofollow\" href=\"https:\/\/stackoverflow.com\/questions\/49451237\/compensating-events-on-cqrs-es-architecture\">compensation event<\/a><\/noindex>, das den letzten Zustand in den erforderlichen \u00e4ndern wird. Ein Beispiel aus einem \u00e4hnlichen Bereich: Ohne die Historie zu \u00fcberschreiben (was in einigen F\u00e4llen schlecht ist) kann man in git einen Commit nicht zur\u00fccksetzen, aber man kann einen speziellen <noindex><a rel=\"nofollow\" href=\"https:\/\/git-scm.com\/docs\/git-revert\">rollback commit<\/a><\/noindex>, der im Grunde nur den alten Zustand wiederherstellt. Allerdings bleibt der fehlerhafte Commit auch in der Historie erhalten und es erfolgt ein Rollback.<\/li>\n<li>Das Datenschema kann von Version zu Version variieren, jedoch k\u00f6nnen alte Ereignisse nun nicht mehr auf den neuen Standard aktualisiert werden (da Ereignisse grunds\u00e4tzlich nicht ge\u00e4ndert werden k\u00f6nnen).<\/li>\n<\/ul>\n<p><\/p>\n<p>Wie zu sehen ist, harmoniert Event Sourcing hervorragend mit CQRS. Dar\u00fcber hinaus ist es schon schwierig, ein System mit effektiven und benutzerfreundlichen Warteschlangen zu implementieren, ohne Datenstr\u00f6me zu trennen, da Synchronisationspunkte hinzugef\u00fcgt werden m\u00fcssen, die den gesamten positiven Effekt der Warteschlangen mindern. Wenn man beide Ans\u00e4tze kombiniert, m\u00fcssen die Programmcode nur geringf\u00fcgig angepasst werden. In unserem Fall erh\u00e4lt man beim Hochladen einer Datei auf den Server lediglich die R\u00fcckmeldung 'ok', was nur bedeutet, dass 'die Datei zum Hinzuf\u00fcgen gespeichert wurde'. Formal bedeutet das nicht, dass die Daten bereits auf anderen Ger\u00e4ten verf\u00fcgbar sind (zum Beispiel kann der Deduplication-Service den Index neu aufbauen). Nach einiger Zeit erh\u00e4lt der Kunde jedoch eine Benachrichtigung im Stil von 'Datei X wurde gespeichert'.<\/p>\n<p><\/p>\n<p>Als Ergebnis:<\/p>\n<p><\/p>\n<ul>\n<li>Die Anzahl der Versandstatus f\u00fcr Dateien steigt: Statt des klassischen 'Datei gesendet' erhalten wir zwei: 'Datei in die Warteschlange auf dem Server eingef\u00fcgt' und 'Datei im Speicher gespeichert'. Letzteres bedeutet, dass andere Ger\u00e4te bereits mit dem Empfang der Datei beginnen k\u00f6nnen (unter Ber\u00fccksichtigung, dass die Warteschlangen mit unterschiedlicher Geschwindigkeit arbeiten).<\/li>\n<li>Da die Informationen \u00fcber den Versand nun \u00fcber verschiedene Kan\u00e4le kommen, m\u00fcssen wir L\u00f6sungen finden, um den Status der Datei Verarbeitung zu erhalten. Dies bedeutet, dass der Client im Gegensatz zum klassischen Request-Response w\u00e4hrend der Verarbeitung der Datei neu gestartet werden kann, der Status dieser Verarbeitung jedoch korrekt bleibt. Und dieser Punkt funktioniert im Grunde genommen 'out of the box'. Als Konsequenz sind wir jetzt fehlertoleranter.<\/li>\n<\/ul>\n<p><\/p>\n<h1 id=\"sharding\">Sharding<\/h1>\n<p><\/p>\n<p>Wie bereits oben beschrieben, gibt es in Systemen mit Event Sourcing keine strikte Konsistenz. Das bedeutet, dass wir mehrere Speicher ohne jegliche Synchronisation zwischen ihnen nutzen k\u00f6nnen. In Anlehnung an unsere Aufgabe k\u00f6nnen wir:<\/p>\n<p><\/p>\n<ul>\n<li>Dateien nach Typen trennen. Zum Beispiel k\u00f6nnen Bilder\/Videos dekodiert und in ein effizienteres Format ausgew\u00e4hlt werden.<\/li>\n<li>Konten nach L\u00e4ndern trennen. Aufgrund vieler Gesetze kann dies erforderlich sein, jedoch bietet diese Architektur die M\u00f6glichkeit, dies automatisch zu tun.<\/li>\n<\/ul>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Praktische Architektur-Muster\" src=\"\/wp-content\/uploads\/2020\/05\/dd310df700bc39c014d0105a3425fece.png\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Wenn Sie Daten von einem Speicherort zu einem anderen \u00fcbertragen m\u00f6chten, sind die Standardmittel nicht ausreichend. Leider muss in diesem Fall die Warteschlange angehalten, die Migration durchgef\u00fchrt und dann erneut gestartet werden. Im Allgemeinen k\u00f6nnen Daten nicht \u201elive\u201c \u00fcbertragen werden, es sei denn, die Ereigniswarteschlange wird vollst\u00e4ndig gespeichert, und Sie haben Kopien fr\u00fcherer Speicherzust\u00e4nde, dann k\u00f6nnen wir Ereignisse wie folgt erneut abspielen:<\/p>\n<p><\/p>\n<ul>\n<li>In Event Source hat jedes Ereignis seine eigene Kennung (idealerweise nicht abnehmend). Das bedeutet, dass wir im Speicher ein Feld hinzuf\u00fcgen k\u00f6nnen \u2013 die ID des letzten verarbeiteten Elements.<\/li>\n<li>Wir duplizieren die Warteschlange, damit alle Ereignisse f\u00fcr mehrere unabh\u00e4ngige Speicherorte verarbeitet werden k\u00f6nnen (das erste ist das, in dem die Daten derzeit gespeichert sind, und das zweite ist neu, jedoch zun\u00e4chst leer). Die zweite Warteschlange wird nat\u00fcrlich vorerst nicht verarbeitet.<\/li>\n<li>Wir starten die zweite Warteschlange (d.h. wir beginnen mit der Wiedergabe der Ereignisse).<\/li>\n<li>Wenn die neue Warteschlange relativ leer ist (d.h. der durchschnittliche Zeitunterschied zwischen dem Hinzuf\u00fcgen eines Elements und dessen Entnahme akzeptabel ist), k\u00f6nnen wir beginnen, die Leser auf den neuen Speicherort umzuschalten.<\/li>\n<\/ul>\n<p><\/p>\n<p>Wie zu sehen ist, gab es in unserem System nie eine strenge Konsistenz. Es gibt nur eventual consistency, d.h. die Garantie, dass Ereignisse in derselben Reihenfolge verarbeitet werden (jedoch m\u00f6glicherweise mit unterschiedlicher Verz\u00f6gerung). Und unter Verwendung dessen k\u00f6nnen wir Daten relativ einfach ohne Stillstand des Systems auf die andere Seite der Welt \u00fcbertragen.<\/p>\n<p><\/p>\n<p>So bietet uns diese Architektur, fortschreitend bei unserem Beispiel f\u00fcr einen Online-Speicher f\u00fcr Dateien, bereits einige Vorteile:<\/p>\n<p><\/p>\n<ul>\n<li>Wir k\u00f6nnen Objekte n\u00e4her an die Benutzer bewegen, und zwar dynamisch. Dadurch kann die Service-Qualit\u00e4t verbessert werden. <\/li>\n<li>Wir k\u00f6nnen einen Teil der Daten innerhalb der Unternehmen speichern. Zum Beispiel verlangen Enterprise-Nutzer h\u00e4ufig, dass ihre Daten in kontrollierten Rechenzentren gespeichert werden (um Datenlecks zu vermeiden). Durch Sharding k\u00f6nnen wir dies problemlos unterst\u00fctzen. Die Aufgabe wird noch einfacher, wenn der Kunde eine kompatible Cloud hat (z.B. <noindex><a rel=\"nofollow\" href=\"https:\/\/docs.microsoft.com\/en-gb\/azure-stack\/asdk\/asdk-what-is?view=azs-1910\">Azure self hosted<\/a><\/noindex>).<\/li>\n<li>Am wichtigsten ist, dass wir das nicht tun m\u00fcssen. Zu Beginn w\u00fcrde uns bereits ein einziges Speichersystem f\u00fcr alle Konten ausreichen (um schneller zu starten). Eine entscheidende Eigenschaft dieses Systems ist, dass es zwar erweiterbar ist, aber in der Anfangsphase ausreichend einfach bleibt. Man muss nicht sofort Code schreiben, der mit Millionen von separaten, unabh\u00e4ngigen Warteschlangen arbeitet usw. Wenn n\u00f6tig, kann man das in der Zukunft erledigen.<\/li>\n<\/ul>\n<p><\/p>\n<h1 id=\"static-content-hosting\">Statisches Content Hosting<\/h1>\n<p><\/p>\n<p>Dieser Punkt mag auf den ersten Blick offensichtlich erscheinen, ist jedoch dennoch notwendig f\u00fcr ein mehr oder weniger standardm\u00e4\u00dfiges, stark ausgelastetes Anwendungssystem. Die Idee ist einfach: S\u00e4mtlicher statischer Inhalt wird nicht vom gleichen Server bereitgestellt, der auch die Anwendung hostet, sondern von speziellen, daf\u00fcr reservierten Servern. Als Folge laufen diese Operationen schneller ab (ein typischer nginx gibt Dateien schneller und kosteng\u00fcnstiger aus als ein Java-Server). Zudem erm\u00f6glicht die Architektur von CDN (<noindex><a rel=\"nofollow\" href=\"https:\/\/en.wikipedia.org\/wiki\/Content_delivery_network\">Content Delivery Network<\/a><\/noindex>) es, unsere Dateien n\u00e4her beim Endnutzer zu platzieren, was die Nutzung des Dienstes verbessert.<\/p>\n<p><\/p>\n<p>Das einfachste und standardm\u00e4\u00dfigste Beispiel f\u00fcr statischen Inhalt ist eine Sammlung von Skripten und Bildern f\u00fcr eine Webseite. Bei ihnen ist alles klar \u2014 sie sind im Voraus bekannt, dann wird das Archiv auf die CDN-Server hochgeladen, von wo aus sie an die Endnutzer verteilt werden.<\/p>\n<p><\/p>\n<p>In der Praxis kann jedoch ein Ansatz \u00e4hnlich der Lambda-Architektur f\u00fcr statischen Inhalt genutzt werden. Lassen Sie uns zu unserem Szenario zur\u00fcckkehren (Online-Dateispeicher), in dem wir Dateien an Benutzer ausgeben m\u00fcssen. Die einfachste L\u00f6sung in der direkten Herangehensweise w\u00e4re es, einen Dienst zu erstellen, der f\u00fcr jede Benutzeranfrage alle notwendigen \u00dcberpr\u00fcfungen vornimmt (Autorisation usw.), und dann die Datei direkt aus unserem Speicher herunterl\u00e4dt. Der Hauptnachteil dieses Ansatzes ist, dass statischer Inhalt (und eine Datei mit einer bestimmten Revision ist in der Tat statischer Inhalt) vom selben Server bereitgestellt wird, der auch die Gesch\u00e4ftslogik enth\u00e4lt. Stattdessen kann man folgendes Schema erstellen:<\/p>\n<p><\/p>\n<ul>\n<li>Der Server gibt eine URL zum Herunterladen aus. Diese kann in der Form file_id + key vorliegen, wobei key eine kleine digitale Signatur ist, die den Zugriff auf die Ressource f\u00fcr die n\u00e4chsten 24 Stunden erlaubt.<\/li>\n<li>Das Bereitstellen der Datei \u00fcbernimmt ein einfacher nginx mit den folgenden Optionen:\n<ul>\n<li>Content-Caching. Da dieser Dienst auf einem separaten Server gespeichert werden kann, haben wir uns die M\u00f6glichkeit f\u00fcr die Zukunft offen gelassen, alle zuletzt heruntergeladenen Dateien auf der Festplatte zu speichern.<\/li>\n<li>\u00dcberpr\u00fcfung des Schl\u00fcssels beim Erstellen der Verbindung<\/li>\n<\/ul>\n<\/li>\n<li>Optional: Streaming von Inhalten. Wenn wir zum Beispiel alle Dateien im Dienst komprimieren, kann die Dekomprimierung direkt in diesem Modul erfolgen. Folglich finden IO-Operationen dort statt, wo sie hingeh\u00f6ren. Ein Archivierungsprogramm in Java k\u00f6nnte viel zus\u00e4tzlichen Speicher beanspruchen, jedoch k\u00f6nnte es auch ineffektiv sein, den Dienst mit Gesch\u00e4ftslogik auf bedingte Sprachen wie Rust\/C++ umzuschreiben. In unserem Fall verwenden wir verschiedene Prozesse (oder sogar Dienste), was es erm\u00f6glicht, Gesch\u00e4ftslogik und IO-Operationen effektiv zu trennen.<\/li>\n<\/ul>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Praktische Architektur-Muster\" src=\"\/wp-content\/uploads\/2020\/05\/4dead07d5824938e09b986192ccc8f5e.png\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Ein solches Schema \u00e4hnelt nicht sehr der Bereitstellung von statischen Inhalten (da wir das gesamte Paket statischer Inhalte nicht irgendwo auslagern), dennoch besch\u00e4ftigt sich dieser Ansatz in der Realit\u00e4t genau mit der Bereitstellung von unver\u00e4nderbaren Daten. Dar\u00fcber hinaus kann dieses Schema auch auf andere F\u00e4lle verallgemeinert werden, in denen der Inhalt nicht nur statisch ist, sondern als eine Menge unver\u00e4nderlicher und nicht l\u00f6schbarer Bl\u00f6cke pr\u00e4sentiert werden kann (auch wenn sie hinzugef\u00fcgt werden k\u00f6nnen).<\/p>\n<p><\/p>\n<p>Ein weiteres Beispiel (zur Veranschaulichung): Wenn Sie mit Jenkins\/TeamCity gearbeitet haben, wissen Sie, dass beide L\u00f6sungen in Java geschrieben sind. Beide repr\u00e4sentieren einen Java-Prozess, der sowohl der Orchestrierung von Builds als auch dem Content-Management dient. Insbesondere haben sie beide Aufgaben wie \"eine Datei\/einen Ordner vom Server \u00fcbertragen\". Zum Beispiel: Bereitstellung von Artefakten, \u00dcbertragung des Quellcodes (wenn der Agent den Code nicht direkt aus dem Repository herunterl\u00e4dt, sondern der Server dies \u00fcbernimmt), Zugang zu Logs. All diese Aufgaben unterscheiden sich in ihrer IO-Belastung. Das bedeutet, dass der Server, der f\u00fcr komplexe Gesch\u00e4ftslogik verantwortlich ist, gleichzeitig in der Lage sein muss, gro\u00dfe Datenstr\u00f6me effizient zu leiten. Und das Interessante ist, dass eine solche Operation genau nach demselben Schema an nginx delegiert werden kann (au\u00dfer dass im Request der Schl\u00fcssel f\u00fcr die Daten hinzugef\u00fcgt werden muss).<\/p>\n<p><\/p>\n<p>Wenn wir jedoch zu unserem System zur\u00fcckkehren, ergibt sich folgendes Schema:<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Praktische Architektur-Muster\" src=\"\/wp-content\/uploads\/2020\/05\/97cfbf5daaa6678a9eecc3169692f0fc.png\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Wie sichtbar ist, hat sich das System radikal kompliziert. Es handelt sich nicht mehr nur um einen Mini-Prozess, der Dateien lokal speichert. Jetzt ist auch eine nicht ganz einfache Unterst\u00fctzung, Versionierung des API usw. erforderlich. Daher ist es am besten, nachdem alle Diagramme gezeichnet sind, sorgf\u00e4ltig abzuw\u00e4gen, ob die Skalierbarkeit solche Ausgaben rechtfertigt. Wenn Sie jedoch die M\u00f6glichkeit haben m\u00f6chten, das System auszubauen (insbesondere f\u00fcr die Arbeit mit einer noch gr\u00f6\u00dferen Anzahl von Benutzern), m\u00fcssen Sie solche L\u00f6sungen in Betracht ziehen. Als Ergebnis ist das System architektonisch bereit f\u00fcr eine h\u00f6here Last (praktisch jede Komponente kann f\u00fcr horizontale Skalierung geklont werden). Das System kann aktualisiert werden, ohne es herunterfahren zu m\u00fcssen (einige Operationen k\u00f6nnen lediglich leicht verlangsamt werden).<\/p>\n<p><\/p>\n<p>Wie ich zu Beginn erw\u00e4hnt habe, sehen sich derzeit viele Internetdienste einer erh\u00f6hten Last gegen\u00fcber. Einige von ihnen fangen einfach an, nicht mehr richtig zu funktionieren. Tats\u00e4chlich sind die Systeme genau zu dem Zeitpunkt ausgefallen, als das Gesch\u00e4ft Geld verdienen sollte. Anstatt auf ein sp\u00e4teres Versanddatum hinzuweisen, anstatt den Kunden zu sagen: \u201ePlanen Sie die Lieferung f\u00fcr die kommenden Monate\u201c, hat das System einfach gesagt: \u201eGeht zu den Wettbewerbern\u201c. Das ist der Preis niedriger Leistung: Verluste treten genau dann auf, wenn der Gewinn am h\u00f6chsten w\u00e4re.<\/p>\n<p><\/p>\n<h1 id=\"zaklyuchenie\">Fazit<\/h1>\n<p><\/p>\n<p>All diese Ans\u00e4tze waren fr\u00fcher bereits bekannt. Das gleiche VK nutzt schon lange die Idee des Static Content Hosting zur Auslieferung von Bildern. Viele Online-Spiele verwenden ein Sharding-System, um Spieler nach Regionen zu trennen oder um Spielstandorte (wenn die Welt einheitlich ist) zu trennen. Der Event Sourcing-Ansatz wird aktiv im E-Mail-Verkehr verwendet. Die meisten Anwendungen von H\u00e4ndlern, bei denen kontinuierlich Daten empfangen werden, basieren tats\u00e4chlich auf dem CQRS-Ansatz, um die erhaltenen Daten filtern zu k\u00f6nnen. Und horizontale Skalierung wird schon seit geraumer Zeit in vielen Diensten eingesetzt.<\/p>\n<p><\/p>\n<p>Aber das Wichtigste ist, dass all diese Muster in modernen Anwendungen sehr leicht anzuwenden sind (sofern sie relevant sind). Die Cloud bietet sofort Sharding und horizontale Skalierung an, was viel einfacher ist, als verschiedene dedizierte Server in verschiedenen Rechenzentren selbst zu bestellen. CQRS ist deutlich einfacher geworden, nicht zuletzt wegen der Entwicklung von Bibliotheken wie RX. Vor 10 Jahren konnte nur selten eine Website so etwas unterst\u00fctzen. Event Sourcing kann ebenfalls unglaublich einfach konfiguriert werden dank bereits vorhandener Container mit Apache Kafka. Vor 10 Jahren w\u00e4re das eine Innovation gewesen, heute ist es allt\u00e4glich. \u00c4hnlich verh\u00e4lt es sich mit dem Hosting von statischen Inhalten: Aufgrund besserer Technologien (unter anderem, weil es ausf\u00fchrliche Dokumentation und eine gro\u00dfe Wissensbasis gibt) ist dieser Ansatz noch einfacher geworden.<\/p>\n<p><\/p>\n<p>Zusammenfassend l\u00e4sst sich sagen, dass die Umsetzung einer Reihe von recht komplexen Architekturmustern jetzt viel einfacher geworden ist, und das sollte man sich im Voraus ansehen. Wenn in einer zehnj\u00e4hrigen Anwendung eine der obigen L\u00f6sungen aufgrund der hohen Kosten f\u00fcr Implementierung und Betrieb verworfen wurde, kann man jetzt in einer neuen Anwendung oder nach einer Refaktorisierung einen Dienst schaffen, der architektonisch sowohl skalierbar (in Bezug auf die Leistung) als auch bereit f\u00fcr neue Anforderungen von Kunden ist (zum Beispiel f\u00fcr die Lokalisierung personenbezogener Daten).<\/p>\n<p><\/p>\n<p>Und das Wichtigste: Bitte verwenden Sie diese Ans\u00e4tze nicht, wenn Sie eine einfache Anwendung haben. Ja, sie sind sch\u00f6n und interessant, aber f\u00fcr eine Website mit einer maximalen Besucherzahl von 100 Personen kann man oft mit einem klassischen Monolithen auskommen (zumindest von au\u00dfen, innen kann alles in Module unterteilt werden usw.).<\/p>\n<p>Quelle: <a content=\"nofollow\" rel=\"nofollow\" href=\"https:\/\/habr.com\/ru\/company\/dbtc\/blog\/499758\/\">habr.com<\/a> <\/p>","protected":false,"gt_translate_keys":[{"key":"rendered","format":"html"}]},"excerpt":{"rendered":"<p>\u041f\u0440\u0438\u0432\u0435\u0442, \u0425\u0430\u0431\u0440! \u0412 \u0441\u0432\u0435\u0442\u0435 \u0442\u0435\u043a\u0443\u0449\u0438\u0445 \u0441\u043e\u0431\u044b\u0442\u0438\u0439 \u0438\u0437-\u0437\u0430 \u043a\u043e\u0440\u043e\u043d\u0430\u0432\u0438\u0440\u0443\u0441\u0430 \u0440\u044f\u0434 \u0438\u043d\u0442\u0435\u0440\u043d\u0435\u0442-\u0441\u0435\u0440\u0432\u0438\u0441\u043e\u0432 \u0441\u0442\u0430\u043b \u043f\u043e\u043b\u0443\u0447\u0430\u0442\u044c \u0443\u0432\u0435\u043b\u0438\u0447\u0435\u043d\u043d\u0443\u044e \u043d\u0430\u0433\u0440\u0443\u0437\u043a\u0443. \u041d\u0430\u043f\u0440\u0438\u043c\u0435\u0440, \u043e\u0434\u043d\u0430 \u0438\u0437 \u0442\u043e\u0440\u0433\u043e\u0432\u044b\u0445 \u0441\u0435\u0442\u0435\u0439 \u0432 \u0412\u0435\u043b\u0438\u043a\u043e\u0431\u0440\u0438\u0442\u0430\u043d\u0438\u0438 \u043f\u0440\u043e\u0441\u0442\u043e \u043e\u0441\u0442\u0430\u043d\u043e\u0432\u0438\u043b\u0430 \u0441\u0430\u0439\u0442 \u0441 \u043e\u043d\u043b\u0430\u0439\u043d-\u0437\u0430\u043a\u0430\u0437\u0430\u043c\u0438, \u0442\u0430\u043a \u043a\u0430\u043a \u043d\u0435 \u0445\u0432\u0430\u0442\u0438\u043b\u043e \u043c\u043e\u0449\u043d\u043e\u0441\u0442\u0435\u0439. \u0418 \u0434\u0430\u043b\u0435\u043a\u043e \u043d\u0435 \u0432\u0441\u0435\u0433\u0434\u0430 \u043c\u043e\u0436\u043d\u043e \u0443\u0441\u043a\u043e\u0440\u0438\u0442\u044c \u0441\u0435\u0440\u0432\u0435\u0440, \u043f\u0440\u043e\u0441\u0442\u043e \u0434\u043e\u0431\u0430\u0432\u0438\u0432 \u0431\u043e\u043b\u0435\u0435 \u043c\u043e\u0449\u043d\u043e\u0435 \u043e\u0431\u043e\u0440\u0443\u0434\u043e\u0432\u0430\u043d\u0438\u0435, \u043e\u0434\u043d\u0430\u043a\u043e \u0437\u0430\u043f\u0440\u043e\u0441\u044b \u043a\u043b\u0438\u0435\u043d\u0442\u043e\u0432 \u043e\u0431\u0440\u0430\u0431\u0430\u0442\u044b\u0432\u0430\u0442\u044c \u043d\u0430\u0434\u043e (\u0438\u043b\u0438 \u043e\u043d\u0438 \u0443\u0439\u0434\u0443\u0442 \u043a \u043a\u043e\u043d\u043a\u0443\u0440\u0435\u043d\u0442\u0430\u043c). \u0412 \u044d\u0442\u043e\u0439 [&hellip;]<\/p>\n","protected":false,"gt_translate_keys":[{"key":"rendered","format":"html"}]},"author":1,"featured_media":80036,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[688],"tags":[],"class_list":["post-80035","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=\"description\" content=\"\u041f\u0440\u0438\u0432\u0435\u0442, \u0425\u0430\u0431\u0440! \u0412 \u0441\u0432\u0435\u0442\u0435 \u0442\u0435\u043a\u0443\u0449\u0438\u0445 \u0441\u043e\u0431\u044b\u0442\u0438\u0439 \u0438\u0437-\u0437\u0430 \u043a\u043e\u0440\u043e\u043d\u0430\u0432\u0438\u0440\u0443\u0441\u0430 \u0440\u044f\u0434 \u0438\u043d\u0442\u0435\u0440\u043d\u0435\u0442-\u0441\u0435\u0440\u0432\u0438\u0441\u043e\u0432 \u0441\u0442\u0430\u043b \u043f\u043e\u043b\u0443\u0447\u0430\u0442\u044c \u0443\u0432\u0435\u043b\u0438\u0447\u0435\u043d\u043d\u0443\u044e \u043d\u0430\u0433\u0440\u0443\u0437\u043a\u0443.\" \/>\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\/udobnye-arhitekturnye-patterny\" \/>\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\u0423\u0434\u043e\u0431\u043d\u044b\u0435 \u0430\u0440\u0445\u0438\u0442\u0435\u043a\u0442\u0443\u0440\u043d\u044b\u0435 \u043f\u0430\u0442\u0442\u0435\u0440\u043d\u044b | ProHoster\" \/>\n\t\t<meta property=\"og:description\" content=\"\u041f\u0440\u0438\u0432\u0435\u0442, \u0425\u0430\u0431\u0440! \u0412 \u0441\u0432\u0435\u0442\u0435 \u0442\u0435\u043a\u0443\u0449\u0438\u0445 \u0441\u043e\u0431\u044b\u0442\u0438\u0439 \u0438\u0437-\u0437\u0430 \u043a\u043e\u0440\u043e\u043d\u0430\u0432\u0438\u0440\u0443\u0441\u0430 \u0440\u044f\u0434 \u0438\u043d\u0442\u0435\u0440\u043d\u0435\u0442-\u0441\u0435\u0440\u0432\u0438\u0441\u043e\u0432 \u0441\u0442\u0430\u043b \u043f\u043e\u043b\u0443\u0447\u0430\u0442\u044c \u0443\u0432\u0435\u043b\u0438\u0447\u0435\u043d\u043d\u0443\u044e \u043d\u0430\u0433\u0440\u0443\u0437\u043a\u0443.\" \/>\n\t\t<meta property=\"og:url\" content=\"https:\/\/prohoster.info\/de\/blog\/administrirovanie\/udobnye-arhitekturnye-patterny\" \/>\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=\"2020-05-02T11:42:54+00:00\" \/>\n\t\t<meta property=\"article:modified_time\" content=\"2020-05-02T11:42:54+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\udd47Bequeme Architekturmodelle | ProHoster","description":"Hallo, Habr! In Anbetracht der aktuellen Ereignisse aufgrund des Coronavirus haben viele Internetdienste eine erh\u00f6hte Last erfahren.","canonical_url":"https:\/\/prohoster.info\/de\/blog\/administrirovanie\/udobnye-arhitekturnye-patterny","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\u0423\u0434\u043e\u0431\u043d\u044b\u0435 \u0430\u0440\u0445\u0438\u0442\u0435\u043a\u0442\u0443\u0440\u043d\u044b\u0435 \u043f\u0430\u0442\u0442\u0435\u0440\u043d\u044b | ProHoster","og:description":"\u041f\u0440\u0438\u0432\u0435\u0442, \u0425\u0430\u0431\u0440! \u0412 \u0441\u0432\u0435\u0442\u0435 \u0442\u0435\u043a\u0443\u0449\u0438\u0445 \u0441\u043e\u0431\u044b\u0442\u0438\u0439 \u0438\u0437-\u0437\u0430 \u043a\u043e\u0440\u043e\u043d\u0430\u0432\u0438\u0440\u0443\u0441\u0430 \u0440\u044f\u0434 \u0438\u043d\u0442\u0435\u0440\u043d\u0435\u0442-\u0441\u0435\u0440\u0432\u0438\u0441\u043e\u0432 \u0441\u0442\u0430\u043b \u043f\u043e\u043b\u0443\u0447\u0430\u0442\u044c \u0443\u0432\u0435\u043b\u0438\u0447\u0435\u043d\u043d\u0443\u044e \u043d\u0430\u0433\u0440\u0443\u0437\u043a\u0443.","og:url":"https:\/\/prohoster.info\/de\/blog\/administrirovanie\/udobnye-arhitekturnye-patterny","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":"2020-05-02T11:42:54+00:00","article:modified_time":"2020-05-02T11:42:54+00:00","article:publisher":"https:\/\/www.facebook.com\/prohoster","article:author":"https:\/\/www.facebook.com\/prohoster"},"aioseo_meta_data":{"post_id":"80035","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":null,"breadcrumb_settings":null,"limit_modified_date":false,"reviewed_by":null,"ai":null,"created":"2021-02-28 16:26:40","updated":"2022-09-28 01:38:29","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\/80035","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=80035"}],"version-history":[{"count":0,"href":"https:\/\/prohoster.info\/de\/wp-json\/wp\/v2\/posts\/80035\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/prohoster.info\/de\/wp-json\/wp\/v2\/media\/80036"}],"wp:attachment":[{"href":"https:\/\/prohoster.info\/de\/wp-json\/wp\/v2\/media?parent=80035"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/prohoster.info\/de\/wp-json\/wp\/v2\/categories?post=80035"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/prohoster.info\/de\/wp-json\/wp\/v2\/tags?post=80035"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}