{"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 Architekturmodelle","gt_translate_keys":[{"key":"rendered","format":"text"}]},"content":{"rendered":"<p>Hallo, Habr!<\/p>\n<p><\/p>\n<p>Angesichts der aktuellen Ereignisse aufgrund des Coronavirus haben viele Internetdienste einen Anstieg der Last 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\">eine Einzelhandelskette in Gro\u00dfbritannien hat 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 leistungsf\u00e4higere Hardware zu beschleunigen, jedoch m\u00fcssen die Kundenanfragen bearbeitet werden (oder sie wenden sich an die Konkurrenz).<\/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 erstellen. Ich habe jedoch nur die Entwicklungsans\u00e4tze ausgew\u00e4hlt, die derzeit <strong>einfach anzuwenden sind.<\/strong>F\u00fcr jeden Punkt stehen Ihnen entweder bereits vorhandene Bibliotheken zur Verf\u00fcgung oder es besteht die M\u00f6glichkeit, die Aufgabe \u00fcber eine Cloud-Plattform zu 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 bekannteste Punkt. Allgemein gesagt gibt es zwei h\u00e4ufig anzutreffende Lastverteilungsschemata \u2013 horizontale und vertikale Skalierung. <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> Sie bestellen leistungsst\u00e4rkere Server oder optimieren den Code.<\/p>\n<p><\/p>\n<p>Als Beispiel nehme ich einen abstrakten Cloud-Speicher, also eine Art von OwnCloud, OneDrive usw.<\/p>\n<p><\/p>\n<p>Das Standarddiagramm einer solchen Architektur ist unten dargestellt, zeigt jedoch lediglich die Komplexit\u00e4t des Systems. Wir m\u00fcssen die Dienste verstehen und synchronisieren. Was passiert, wenn ein Nutzer von seinem Tablet eine Datei speichert und sie dann auf seinem Smartphone ansehen m\u00f6chte?<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Praktische Architekturmodelle\" src=\"\/wp-content\/uploads\/2020\/05\/7512c6d8783f5e0a38cc0861b01e54c8.png\" style=\"display:block;margin: 0 auto;\" \/><br \/>\nDer Unterschied zwischen den Ans\u00e4tzen: Beim vertikalen Scaling sind wir bereit, die Leistung der Knoten zu erh\u00f6hen, w\u00e4hrend wir beim horizontalen Scaling 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> Dies ist ein ziemlich wichtiges Muster, da es verschiedenen Clients nicht nur erm\u00f6glicht, sich mit unterschiedlichen Diensten zu verbinden, sondern auch identische Ereignisstr\u00f6me zu erhalten. Die Vorteile sind f\u00fcr einfache Anwendungen nicht sofort ersichtlich, jedoch sind sie entscheidend (und einfach) f\u00fcr stark belastete Dienste. Die Grundidee ist: Eingehende und ausgehende Datenstr\u00f6me sollten sich nicht \u00fcberschneiden. Das hei\u00dft, Sie k\u00f6nnen eine Anfrage senden und nicht auf eine Antwort warten; stattdessen senden Sie eine Anfrage an Dienst A, erhalten jedoch 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 des Wortes) w\u00e4hrend einer langen Anfrage zu unterbrechen. Nehmen wir als Beispiel eine mehr oder weniger standardm\u00e4\u00dfige Abfolge:<\/p>\n<p><\/p>\n<ol>\n<li>Der Kunde hat eine Anfrage an den Server gesendet.<\/li>\n<li>Der Server hat die langwierige Verarbeitung gestartet.<\/li>\n<li>Der Server hat dem Kunden mit dem Ergebnis geantwortet.<\/li>\n<\/ol>\n<p><\/p>\n<p>Stellen wir uns vor, dass in Punkt 2 die Verbindung unterbrochen wurde (entweder wurde das Netzwerk neu verbunden oder der Benutzer ist auf eine andere Seite gewechselt, wodurch die Verbindung unterbrochen wurde). In diesem Fall w\u00e4re es f\u00fcr den Server schwierig, dem Benutzer zu vermitteln, was genau verarbeitet wurde. Wenn wir CQRS anwenden, wird die Abfolge etwas anders aussehen:<\/p>\n<p><\/p>\n<ol>\n<li>Der Kunde hat sich f\u00fcr Updates angemeldet.<\/li>\n<li>Der Kunde hat eine Anfrage an den Server gesendet.<\/li>\n<li>Der Server hat mit \u00abAnfrage angenommen\u00bb geantwortet.<\/li>\n<li>Der Server hat das Ergebnis \u00fcber den Kanal aus Punkt \u00ab1\u00bb \u00fcbermittelt.<\/li>\n<\/ol>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Praktische Architekturmodelle\" 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 Request-Response-Ansatz hier. Doch wie man sieht, f\u00fchrt eine Unterbrechung der Verbindung w\u00e4hrend der Anfrageverarbeitung nicht zu einem Fehler. Tats\u00e4chlich kann, wenn der Benutzer mit mehreren Ger\u00e4ten (z.B. mit einem Mobiltelefon und einem Tablet) verbunden ist, sichergestellt werden, dass die Antwort auf beide Ger\u00e4te gesendet wird.<\/p>\n<p><\/p>\n<p>Interessanterweise wird der Code zur Verarbeitung eingehender Nachrichten \u00e4hnlich (aber nicht zu 100 %) f\u00fcr Ereignisse, die durch den Kunden selbst beeinflusst wurden, sowie f\u00fcr andere Ereignisse, einschlie\u00dflich solcher von anderen Kunden.<\/p>\n<p><\/p>\n<p>In der Praxis erhalten wir jedoch zus\u00e4tzliche Vorteile, da der einseitige Datenstrom im funktionalen Stil verarbeitet werden kann (unter Verwendung von RX und \u00e4hnlichen Technologien). Das ist ein erheblicher Vorteil, denn so kann die Anwendung vollst\u00e4ndig reaktiv gestaltet werden, wobei ein funktionaler Ansatz zum Einsatz kommt. F\u00fcr umfangreiche Anwendungen kann das die Ressourcen f\u00fcr Entwicklung und Support erheblich einsparen.<\/p>\n<p><\/p>\n<p>Kombinieren wir diesen Ansatz mit horizontaler Skalierung, erhalten wir zus\u00e4tzlich die M\u00f6glichkeit, Anfragen an einen Server zu senden und Antworten von einem anderen zu empfangen. So kann der Kunde den f\u00fcr ihn passenden Dienst w\u00e4hlen, w\u00e4hrend das System intern 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 einzelnen Prozess k\u00f6nnen Sie eine Synchronisierung (unter Verwendung der gleichen Mutexes) durchf\u00fchren, innerhalb derer Sie sicherstellen k\u00f6nnen, dass niemand sonst diesen Code ausf\u00fchrt. In einem verteilten System ist dies jedoch gef\u00e4hrlich, da es zus\u00e4tzlichen Overhead verursacht und die wundervolle M\u00f6glichkeit der Skalierung beeintr\u00e4chtigt \u2014 letztlich werden alle Komponenten auf ein einzelnes Element warten.<\/p>\n<p><\/p>\n<p>Hieraus ergibt sich eine wichtige Erkenntnis \u2014 ein schnelles verteiltes System kann nicht synchronisiert werden, da dies die Leistung verringern w\u00fcrde. Andererseits ben\u00f6tigen wir oft eine gewisse Konsistenz der Komponenten. Daf\u00fcr kann der Ansatz der <noindex><a rel=\"nofollow\" href=\"https:\/\/en.wikipedia.org\/wiki\/Eventual_consistency\">eventual consistency<\/a><\/noindex>verwendet werden, der garantiert, dass in Abwesenheit von Daten\u00e4nderungen nach einer bestimmten Zeitspanne seit der letzten Aktualisierung (\u201eletztendlich\u201c) alle Anfragen den letzten aktualisierten Wert zur\u00fcckgeben.<\/p>\n<p><\/p>\n<p>Es ist wichtig zu verstehen, dass f\u00fcr klassische Datenbanken oft <noindex><a rel=\"nofollow\" href=\"https:\/\/en.wikipedia.org\/wiki\/Consistency_model#Strict_consistency\">strikte Konsistenz<\/a><\/noindex>, wo jeder Knoten \u00fcber die gleichen Informationen verf\u00fcgt (dies wird h\u00e4ufig erreicht, wenn eine Transaktion erst dann als abgeschlossen gilt, wenn die Antwort des zweiten Servers vorliegt). Es gibt hier einige Ausnahmen aufgrund der Isolationslevel, aber das grundlegende Konzept bleibt gleich \u2013 Sie k\u00f6nnen in einer vollst\u00e4ndig konsistenten Welt leben.<\/p>\n<p><\/p>\n<p>Kehren wir jedoch zu der urspr\u00fcnglichen Aufgabe zur\u00fcck. Wenn ein Teil des Systems aufgebaut werden kann mit <noindex><a rel=\"nofollow\" href=\"https:\/\/en.wikipedia.org\/wiki\/Eventual_consistency\">eventual consistency<\/a><\/noindex>, dann kann das folgende Schema aufgebaut werden.<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Praktische Architekturmodelle\" 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 der Anfrage kann der Dienst auch Aufgaben in andere Warteschlangen einf\u00fcgen.<\/li>\n<li>Jedes eingehende Ereignis hat einen Identifikator (der f\u00fcr die Deduplizierung erforderlich ist).<\/li>\n<li>\u041e\u0447\u0435\u0440\u0435\u0434\u044c \u0438\u0434\u0435\u043e\u043b\u043e\u0433\u0438\u0447\u0435\u0441\u043a\u0438 \u0440\u0430\u0431\u043e\u0442\u0430\u0435\u0442 \u043f\u043e \u0441\u0445\u0435\u043c\u0435 &quot;append only&quot;. \u0418\u0437 \u043d\u0435\u0451 \u043d\u0435\u043b\u044c\u0437\u044f \u0443\u0434\u0430\u043b\u044f\u0442\u044c \u044d\u043b\u0435\u043c\u0435\u043d\u0442\u044b \u0438\u043b\u0438 \u043f\u0435\u0440\u0435\u0441\u0442\u0430\u0432\u043b\u044f\u0442\u044c \u0438\u0445.<\/li>\n<li>Die Warteschlange arbeitet nach dem FIFO-Prinzip (Entschuldigung f\u00fcr die tautologische Aussage). Wenn die parallele Ausf\u00fchrung 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 wird das System ungef\u00e4hr so aussehen:<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Praktische Architekturmodelle\" src=\"\/wp-content\/uploads\/2020\/05\/b95efb29545dcde1db9432d12d00a1b1.png\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Es ist wichtig zu beachten, dass die Dienste in der Grafik nicht unbedingt einen separaten Server darstellen. Sogar der Prozess kann derselbe sein. Entscheidend ist jedoch, dass diese Konzepte ideologisch so voneinander getrennt sind, dass eine einfache horizontale Skalierung m\u00f6glich ist.<\/p>\n<p><\/p>\n<p>F\u00fcr zwei Benutzer w\u00fcrde das Diagramm folgenderma\u00dfen aussehen (Dienste, die f\u00fcr unterschiedliche Benutzer bestimmt sind, sind durch verschiedene Farben gekennzeichnet):<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Praktische Architekturmodelle\" src=\"\/wp-content\/uploads\/2020\/05\/4c4aadc8b9dd505c3ad743e69fee4fae.png\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Vorteile einer solchen Kombination:<\/p>\n<p><\/p>\n<ul>\n<li>Die Informationsverarbeitungsdienste sind getrennt. Die Warteschlangen sind ebenfalls getrennt. Wenn wir die Systemkapazit\u00e4t erh\u00f6hen 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 auf die vollst\u00e4ndige Speicherung der Daten warten. Im Gegenteil, es reicht aus, mit 'ok' zu antworten und dann schrittweise zu beginnen. Gleichzeitig mildert die Warteschlange die Spitzen, da das Hinzuf\u00fcgen eines neuen Objekts schnell geschieht und der Benutzer nicht auf den vollst\u00e4ndigen Durchlauf des gesamten Prozesses warten muss.<\/li>\n<li>Als Beispiel habe ich einen Deduplication-Dienst hinzugef\u00fcgt, der versucht, identische Dateien zusammenzuf\u00fchren. Wenn er lange in 1 % der F\u00e4lle arbeitet, wird der Kunde das praktisch nicht bemerken (siehe oben), was ein gro\u00dfer Vorteil ist, da wir nicht unbedingt eine hundertprozentige Geschwindigkeit und Zuverl\u00e4ssigkeit ben\u00f6tigen.<\/li>\n<\/ul>\n<p><\/p>\n<p>Allerdings sind auch die Nachteile sofort sichtbar:<\/p>\n<p><\/p>\n<ul>\n<li>Unser System hat die strenge Konsistenz verloren. 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 annimmt). Ein weiteres Ergebnis ist, dass das System jetzt keine gemeinsame Zeit hat. Man kann also beispielsweise nicht einfach alle Ereignisse nach ihrem Eintreffen sortieren, da die Uhren zwischen den Servern nicht synchron sein k\u00f6nnen (dar\u00fcber hinaus ist es eine Utopie, dass zwei Server die gleiche Zeit haben).<\/li>\n<li>Es k\u00f6nnen nun keine Ereignisse 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>, der den letzten Zustand auf den erforderlichen \u00e4ndern wird. Ein Beispiel aus einem verwandten Bereich: Ohne die Historie zu \u00fcberschreiben (was in manchen F\u00e4llen schlecht ist) kann man in Git keinen Commit zur\u00fccksetzen, jedoch kann man einen speziellen <noindex><a rel=\"nofollow\" href=\"https:\/\/git-scm.com\/docs\/git-revert\">Rollback-Commit<\/a><\/noindex>, der im Grunde genommen einfach den alten Zustand wiederherstellt. Allerdings bleibt sowohl der fehlerhafte Commit als auch der Rollback in der Historie erhalten.<\/li>\n<li>Das Daten-Schema kann sich von Version zu Version \u00e4ndern, jedoch k\u00f6nnen alte Ereignisse nun nicht 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 man sieht, harmoniert Event Sourcing hervorragend mit CQRS. Dar\u00fcber hinaus ist es bereits schwierig, ein System mit effizienten und benutzerfreundlichen Warteschlangen zu implementieren, ohne Datenstr\u00f6me zu trennen. Es m\u00fcssen Synchronisationspunkte hinzugef\u00fcgt werden, die den gesamten positiven Effekt der Warteschlangen zunichte machen. Bei der Anwendung beider Ans\u00e4tze ist es notwendig, den Code der Anwendung geringf\u00fcgig anzupassen. In unserem Fall, wenn eine Datei an den Server gesendet wird, kommt als Antwort nur \"ok\", was lediglich bedeutet, dass \"die Datei erfolgreich hinzugef\u00fcgt wurde\". Formal bedeutet dies nicht, dass die Daten bereits auf anderen Ger\u00e4ten verf\u00fcgbar sind (zum Beispiel kann der Deduplizierungsdienst den Index neu aufbauen). Nach einiger Zeit erh\u00e4lt der Kunde jedoch eine Benachrichtigung in der Art von \"Datei X gespeichert\".<\/p>\n<p><\/p>\n<p>Das Ergebnis:<\/p>\n<p><\/p>\n<ul>\n<li>Die Anzahl der Statusmeldungen f\u00fcr Datei\u00fcbertragungen steigt: Anstelle 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 die Datei bereits erhalten k\u00f6nnen (unter Ber\u00fccksichtigung der Tatsache, dass Warteschlangen mit unterschiedlicher Geschwindigkeit arbeiten).<\/li>\n<li>Da Informationen \u00fcber den Versand nun \u00fcber verschiedene Kan\u00e4le eintreffen, m\u00fcssen wir L\u00f6sungen entwickeln, um den Status der Dateiverarbeitung zu erhalten. Folglich kann der Client w\u00e4hrend der Dateiverarbeitung neu gestartet werden, w\u00e4hrend der Status dieser Verarbeitung dennoch korrekt bleibt. Dieses Prinzip funktioniert im Grunde genommen sofort. Dadurch sind wir nun toleranter gegen\u00fcber Ausf\u00e4llen.<\/li>\n<\/ul>\n<p><\/p>\n<h1 id=\"sharding\">Sharding<\/h1>\n<p><\/p>\n<p>Wie bereits erw\u00e4hnt, weisen Systeme mit Event-Sourcing keine strikte Konsistenz auf. Das bedeutet, dass wir mehrere Speicherl\u00f6sungen nutzen k\u00f6nnen, ohne dass eine Synchronisation zwischen ihnen erforderlich ist. In Bezug auf unsere Aufgabe k\u00f6nnen wir:<\/p>\n<p><\/p>\n<ul>\n<li>Dateien nach Typen trennen. Beispielsweise k\u00f6nnen Bilder\/Videos dekodiert werden, um ein effizienteres Format auszuw\u00e4hlen.<\/li>\n<li>Konten nach L\u00e4ndern aufteilen. Aufgrund verschiedener Gesetze kann dies erforderlich sein, doch dieses Architekturdesign erm\u00f6glicht dies automatisch.<\/li>\n<\/ul>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Praktische Architekturmodelle\" 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, reicht dies nicht mit den Standardmitteln aus. Leider m\u00fcssen Sie in diesem Fall die Warteschlange anhalten, die Migration durchf\u00fchren und sie dann wieder starten. Im Allgemeinen k\u00f6nnen Daten nicht \"live\" \u00fcbertragen werden, allerdings, wenn die Ereigniswarteschlange vollst\u00e4ndig gespeichert ist und Sie Snapshots der vorherigen Zust\u00e4nde des Speichers haben, k\u00f6nnen wir die Ereignisse folgenderma\u00dfen neu abspielen:<\/p>\n<p><\/p>\n<ul>\n<li>In der Ereignisquelle hat jedes Ereignis seine eigene Identifikationsnummer (idealerweise eine, die nicht abnimmt). Das bedeutet, dass wir im Speicher ein Feld hinzuf\u00fcgen k\u00f6nnen \u2014 die ID des letzten verarbeiteten Elements.<\/li>\n<li>Wir duplizieren die Warteschlange, sodass alle Ereignisse f\u00fcr mehrere unabh\u00e4ngige Speicherorte verarbeitet werden k\u00f6nnen (das erste ist der Speicher, in dem die Daten bereits gespeichert sind, das zweite ist neu und derzeit jedoch leer). Die zweite Warteschlange wird nat\u00fcrlich vorerst nicht bearbeitet.<\/li>\n<li>Wir starten die zweite Warteschlange (das hei\u00dft, wir beginnen mit dem erneuten Abspielen 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 Abruf akzeptabel ist), k\u00f6nnen wir damit beginnen, die Leser auf den neuen Speicherort umzuschalten.<\/li>\n<\/ul>\n<p><\/p>\n<p>Wie zu sehen ist, haben wir in unserem System keine strenge Konsistenz. Es gibt nur eventual consistency, was bedeutet, dass Ereignisse in der gleichen Reihenfolge verarbeitet werden, jedoch m\u00f6glicherweise mit unterschiedlicher Verz\u00f6gerung. Daher k\u00f6nnen wir die Daten vergleichsweise einfach ohne Systemunterbrechung an einen anderen Ort auf der Erde \u00fcbertragen.<\/p>\n<p><\/p>\n<p>Auf diese Weise bringt unsere Architektur im Beispiel eines Online-Dateispeichers bereits eine Reihe von Vorteilen mit sich:<\/p>\n<p><\/p>\n<ul>\n<li>Wir k\u00f6nnen Objekte dynamisch n\u00e4her zu den Nutzern verschieben, was die Servicequalit\u00e4t verbessert. <\/li>\n<li>Wir k\u00f6nnen einen Teil der Daten innerhalb der Unternehmen speichern. Beispielsweise verlangen Enterprise-Kunden oft, dass ihre Daten in kontrollierten Rechenzentren gespeichert werden, um Datenlecks zu vermeiden. Durch Sharding k\u00f6nnen wir dies leicht unterst\u00fctzen. Die Aufgabe wird noch einfacher, wenn der Kunde eine kompatible Cloud hat (zum Beispiel, <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>Das Wichtigste ist, dass wir das nicht zwingend tun m\u00fcssen. Zu Beginn w\u00fcrde uns ein einziges Speicherangebot f\u00fcr alle Konten gen\u00fcgen, um schnell mit der Arbeit zu beginnen. Das Hauptmerkmal dieses Systems ist, obwohl es erweiterbar ist, dass es in der Anfangsphase relativ einfach gehalten wird. Man muss nicht sofort Code schreiben, der mit einer Million separater, unabh\u00e4ngiger Warteschlangen arbeitet usw. Wenn n\u00f6tig, kann das in der Zukunft umgesetzt werden.<\/li>\n<\/ul>\n<p><\/p>\n<h1 id=\"static-content-hosting\">Hosting f\u00fcr statische Inhalte<\/h1>\n<p><\/p>\n<p>Dieser Punkt mag offensichtlich erscheinen, ist jedoch f\u00fcr eine mehr oder weniger standardisierte, stark belastete Anwendung unerl\u00e4sslich. Die Idee dahinter ist einfach: Alle statischen Inhalte werden nicht von demselben Server bereitgestellt, auf dem sich die Anwendung befindet, sondern von speziellen Servern, die genau daf\u00fcr vorgesehen sind. Dadurch erfolgen diese Vorg\u00e4nge schneller (ein typischer nginx-Server liefert Dateien effizienter und kosteng\u00fcnstiger als ein Java-Server). Zudem erm\u00f6glicht die Architektur eines CDN (<noindex><a rel=\"nofollow\" href=\"https:\/\/en.wikipedia.org\/wiki\/Content_delivery_network\">Content Delivery Network<\/a><\/noindex>) unsere Dateien n\u00e4her an den Endnutzern zu positionieren, was sich positiv auf die Benutzerfreundlichkeit des Services auswirkt.<\/p>\n<p><\/p>\n<p>Das einfachste und Standardbeispiel f\u00fcr statische Inhalte ist ein Set aus Skripten und Bildern f\u00fcr eine Website. Diese sind im Voraus bekannt, dann wird das Archiv auf die CDN-Server hochgeladen, von wo aus sie an die Endbenutzer verteilt werden.<\/p>\n<p><\/p>\n<p>In der Praxis kann jedoch ein Ansatz verwendet werden, der etwas der Lambda-Architektur \u00e4hnelt. Kommen wir zur\u00fcck zu unserem Ziel (Online-Dateispeicher), bei dem wir Dateien an Benutzer bereitstellen m\u00fcssen. Die einfachste L\u00f6sung w\u00e4re, einen Dienst zu erstellen, der f\u00fcr jede Benutzeranfrage alle notwendigen Pr\u00fcfungen (z. B. Autorisierung usw.) durchf\u00fchrt und dann die Datei direkt aus unserem Speicher herunterl\u00e4dt. Der Hauptnachteil dieses Ansatzes ist, dass der statische Inhalt (und eine Datei mit einer bestimmten Revision ist im Grunde statischer Inhalt) vom selben Server bereitgestellt wird, der auch die Gesch\u00e4ftslogik enth\u00e4lt. Stattdessen kann folgendes Schema implementiert werden:<\/p>\n<p><\/p>\n<ul>\n<li>Der Server gibt eine URL zum Herunterladen aus. Diese kann die Form file_id + key haben, wobei key eine kleine digitale Signatur ist, die den Zugang zum Ressourcen innerhalb der n\u00e4chsten 24 Stunden erm\u00f6glicht.<\/li>\n<li>Das Bereitstellen der Datei erfolgt durch einen einfachen Nginx mit den folgenden Optionen:\n<ul>\n<li>Content-Caching. Da dieser Dienst auf einem separaten Server liegen kann, haben wir uns die M\u00f6glichkeit offen gehalten, alle zuletzt heruntergeladenen Dateien auf der Festplatte zu speichern.<\/li>\n<li>Schl\u00fcssel\u00fcberpr\u00fcfung beim Verbindungsaufbau<\/li>\n<\/ul>\n<\/li>\n<li>Optional: Stream-Verarbeitung von Inhalten. Wenn wir beispielsweise alle Dateien im Dienst komprimieren, kann die Dekomprimierung direkt in diesem Modul erfolgen. Das bedeutet, dass IO-Operationen dort durchgef\u00fchrt werden, wo sie am sinnvollsten sind. Ein Java-Archivierer kann viel zus\u00e4tzlichen Speicher beanspruchen, aber einen Dienst mit Gesch\u00e4ftslogik in Rust\/C++ umzuschreiben, k\u00f6nnte ebenfalls unwirtschaftlich sein. In unserem Fall verwenden wir verschiedene Prozesse (oder sogar Dienste), sodass wir Gesch\u00e4ftslogik und IO-Operationen recht effektiv trennen k\u00f6nnen.<\/li>\n<\/ul>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Praktische Architekturmodelle\" 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 wirklich der Bereitstellung statischer Inhalte (da wir das gesamte Paket an Statik nicht an einen Ort auslagern), jedoch befasst sich dieser Ansatz tats\u00e4chlich mit der Bereitstellung unver\u00e4nderlicher Daten. Dar\u00fcber hinaus kann dieses Schema auch auf andere Situationen erweitert werden, in denen der Inhalt nicht nur statisch ist, sondern in Form einer Sammlung von unver\u00e4nderlichen und nicht l\u00f6schbaren Bl\u00f6cken pr\u00e4sentiert werden kann (auch wenn weitere hinzugef\u00fcgt werden k\u00f6nnen).<\/p>\n<p><\/p>\n<p>\u041a\u0430\u043a \u0435\u0449\u0435 \u043f\u0440\u0438\u043c\u0435\u0440 (\u0434\u043b\u044f \u0437\u0430\u043a\u0440\u0435\u043f\u043b\u0435\u043d\u0438\u044f): \u0435\u0441\u043b\u0438 \u0432\u044b \u0440\u0430\u0431\u043e\u0442\u0430\u043b\u0438 \u0441 Jenkins\/TeamCity, \u0442\u043e \u0437\u043d\u0430\u0435\u0442\u0435, \u0447\u0442\u043e \u043e\u0431\u0430 \u0440\u0435\u0448\u0435\u043d\u0438\u044f \u043d\u0430\u043f\u0438\u0441\u0430\u043d\u044b \u043d\u0430 Java. \u041e\u0431\u0430 \u043e\u043d\u0438 \u043f\u0440\u0435\u0434\u0441\u0442\u0430\u0432\u043b\u044f\u044e\u0442 \u0441\u043e\u0431\u043e\u0439 Java-\u043f\u0440\u043e\u0446\u0435\u0441\u0441, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0437\u0430\u043d\u0438\u043c\u0430\u0435\u0442\u0441\u044f \u043a\u0430\u043a \u043e\u0440\u043a\u0435\u0441\u0442\u0440\u0430\u0446\u0438\u0435\u0439 \u0431\u0438\u043b\u0434\u043e\u0432, \u0442\u0430\u043a \u0438 \u043c\u0435\u043d\u0435\u0434\u0436\u043c\u0435\u043d\u0442\u043e\u043c \u043a\u043e\u043d\u0442\u0435\u043d\u0442\u0430. \u0412 \u0447\u0430\u0441\u0442\u043d\u043e\u0441\u0442\u0438, \u0443 \u043d\u0438\u0445 \u043e\u0431\u043e\u0438\u0445 \u0435\u0441\u0442\u044c \u0437\u0430\u0434\u0430\u0447\u0438 \u0432\u0438\u0434\u0430 &quot;\u043f\u0435\u0440\u0435\u0434\u0430\u0442\u044c \u0444\u0430\u0439\u043b\/\u043f\u0430\u043f\u043a\u0443 \u0441 \u0441\u0435\u0440\u0432\u0435\u0440\u0430&quot;. \u041a\u0430\u043a \u043f\u0440\u0438\u043c\u0435\u0440: \u0432\u044b\u0434\u0430\u0447\u0430 \u0430\u0440\u0442\u0435\u0444\u0430\u043a\u0442\u043e\u0432, \u043f\u0435\u0440\u0435\u0434\u0430\u0447\u0430 \u0438\u0441\u0445\u043e\u0434\u043d\u043e\u0433\u043e \u043a\u043e\u0434\u0430 (\u043a\u043e\u0433\u0434\u0430 \u0430\u0433\u0435\u043d\u0442 \u043d\u0435 \u0441\u043a\u0430\u0447\u0438\u0432\u0430\u0435\u0442 \u043a\u043e\u0434 \u043d\u0430\u043f\u0440\u044f\u043c\u0443\u044e \u0438\u0437 \u0440\u0435\u043f\u043e\u0437\u0438\u0442\u043e\u0440\u0438\u044f, \u0430 \u0437\u0430 \u043d\u0435\u0433\u043e \u044d\u0442\u043e \u0434\u0435\u043b\u0430\u0435\u0442 \u0441\u0435\u0440\u0432\u0435\u0440), \u0434\u043e\u0441\u0442\u0443\u043f \u043a \u043b\u043e\u0433\u0430\u043c. \u0412\u0441\u0435 \u044d\u0442\u0438 \u0437\u0430\u0434\u0430\u0447\u0438 \u043e\u0442\u043b\u0438\u0447\u0430\u044e\u0442\u0441\u044f \u043d\u0430\u0433\u0440\u0443\u0437\u043a\u043e\u0439 \u043d\u0430 IO. \u0422\u043e \u0435\u0441\u0442\u044c \u043f\u043e\u043b\u0443\u0447\u0430\u0435\u0442\u0441\u044f, \u0447\u0442\u043e \u0441\u0435\u0440\u0432\u0435\u0440, \u043e\u0442\u0432\u0435\u0447\u0430\u044e\u0449\u0438\u0439 \u0437\u0430 \u0441\u043b\u043e\u0436\u043d\u0443\u044e \u0431\u0438\u0437\u043d\u0435\u0441-\u043b\u043e\u0433\u0438\u043a\u0443, \u0437\u0430\u043e\u0434\u043d\u043e \u0434\u043e\u043b\u0436\u0435\u043d \u0443\u043c\u0435\u0442\u044c \u044d\u0444\u0444\u0435\u043a\u0442\u0438\u0432\u043d\u043e \u043f\u0440\u043e\u0442\u0430\u043b\u043a\u0438\u0432\u0430\u0442\u044c \u0447\u0435\u0440\u0435\u0437 \u0441\u0435\u0431\u044f \u0431\u043e\u043b\u044c\u0448\u0438\u0435 \u043f\u043e\u0442\u043e\u043a\u0438 \u0434\u0430\u043d\u043d\u044b\u0445. \u0418 \u0447\u0442\u043e \u0441\u0430\u043c\u043e\u0435 \u0438\u043d\u0442\u0435\u0440\u0435\u0441\u043d\u043e\u0435, \u043f\u043e\u0434\u043e\u0431\u043d\u0443\u044e \u043e\u043f\u0435\u0440\u0430\u0446\u0438\u044e \u043c\u043e\u0436\u043d\u043e \u0441\u0434\u0435\u043b\u0435\u0433\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u0442\u043e\u043c\u0443 \u0436\u0435 nginx&#8217;\u0443 \u043f\u043e \u0440\u043e\u0432\u043d\u043e \u0442\u043e\u0439 \u0436\u0435 \u0441\u0445\u0435\u043c\u0435 (\u0440\u0430\u0437\u0432\u0435 \u0447\u0442\u043e \u0432 \u0437\u0430\u043f\u0440\u043e\u0441 \u0441\u043b\u0435\u0434\u0443\u0435\u0442 \u0434\u043e\u0431\u0430\u0432\u043b\u044f\u0442\u044c \u043a\u043b\u044e\u0447 \u0434\u0430\u043d\u043d\u044b\u0445).<\/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 Architekturmodelle\" src=\"\/wp-content\/uploads\/2020\/05\/97cfbf5daaa6678a9eecc3169692f0fc.png\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Wie man sieht, ist das System radikal komplexer geworden. Es handelt sich nun nicht mehr nur um einen Mini-Prozess, der Dateien lokal speichert. Jetzt erfordert es eine durchaus anspruchsvolle Unterst\u00fctzung, API-Versionierung und so weiter. Daher ist es nach dem Zeichnen aller Diagramme ratsam, die Skalierbarkeit solcher Kosten genau zu bewerten. Wenn Sie jedoch die F\u00e4higkeit haben m\u00f6chten, das System zu erweitern (insbesondere f\u00fcr eine noch h\u00f6here Anzahl von Benutzern), m\u00fcssen Sie solche L\u00f6sungen in Betracht ziehen. Das Resultat ist, dass das architektonische System f\u00fcr eine h\u00f6here Last bereit ist (fast jede Komponente kann f\u00fcr horizontale Skalierung geklont werden). Das System kann ohne Unterbrechung aktualisiert werden (einfach einige Operationen werden geringf\u00fcgig langsamer).<\/p>\n<p><\/p>\n<p>Wie ich bereits zu Beginn erw\u00e4hnt habe, sind eine Reihe von Internetdiensten derzeit mit einer erh\u00f6hten Nachfrage konfrontiert. Einige von ihnen haben einfach aufgeh\u00f6rt, richtig zu funktionieren. Im Grunde haben die Systeme genau zu dem Zeitpunkt versagt, als das Gesch\u00e4ft gerade Geld verdienen sollte. Anstatt eine verz\u00f6gerte Lieferung anzubieten oder den Kunden zu sagen: \u201ePlanen Sie die Lieferung f\u00fcr die kommenden Monate\u201c, hat das System einfach gesagt: \u201eGehen Sie zu den Konkurrenten\u201c. Das ist der Preis f\u00fcr eine niedrige 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 auch fr\u00fcher bekannt. Zum Beispiel nutzt VK bereits seit langem die Idee des Static Content Hosting zur Bereitstellung von Bildern. Viele Online-Spiele verwenden ein Sharding-System, um Spieler nach Regionen zu unterteilen oder um Spielareale (wenn die Welt einheitlich ist) zu unterteilen. Der Event Sourcing-Ansatz wird aktiv im E-Mail-Verkehr genutzt. Die meisten Handelsanwendungen, die kontinuierlich Daten empfangen, basieren tats\u00e4chlich auf dem CQRS-Ansatz, um die erhaltenen Daten filtern zu k\u00f6nnen. Horizontal Scaling wird zudem seit langem in vielen Diensten angewendet.<\/p>\n<p><\/p>\n<p>Doch das Wichtigste ist, dass all diese Muster in modernen Anwendungen sehr einfach anzuwenden sind (wenn sie nat\u00fcrlich passend sind). Clouds bieten Sharding und horizontale Skalierung auf einfache Weise an, was viel einfacher ist, als verschiedene dedizierte Server in unterschiedlichen Rechenzentren selbst zu bestellen. CQRS wurde dank Entwicklungen in Bibliotheken wie RX wesentlich zug\u00e4nglicher. Vor etwa 10 Jahren konnte eine seltene Website so etwas unterst\u00fctzen. Event Sourcing l\u00e4sst sich ebenfalls unglaublich leicht dank bereits vorhandener Container mit Apache Kafka einrichten. Vor einem Jahrzehnt w\u00e4re das eine Innovation gewesen, heute ist es \u00fcberall verbreitet. Das Gleiche gilt f\u00fcr das Hosting statischer Inhalte: Dank besserer Technologien (einschlie\u00dflich umfangreicher Dokumentation und einer gro\u00dfen Wissensdatenbank) ist dieser Ansatz noch einfacher geworden.<\/p>\n<p><\/p>\n<p>Zusammenfassend l\u00e4sst sich sagen, dass die Implementierung einer Reihe komplexer Architektur-Patterns jetzt viel einfacher geworden ist, was bedeutet, dass es sich lohnt, sie im Voraus in Betracht zu ziehen. Wenn in einer zehnj\u00e4hrigen Anwendung aufgrund hoher Implementierungs- und Betriebskosten von einer der oben genannten L\u00f6sungen abgesehen wurde, kann man im neuen Projekt oder nach dem Refactoring einen Service erstellen, der architektonisch sowohl skalierbar (in Bezug auf die Leistung) als auch bereit f\u00fcr neue Anforderungen der Kunden ist (zum Beispiel zur 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 einem Spitzenaufkommen von 100 Besuchern kann man oft mit einem klassischen Monolithen auskommen (zumindest von au\u00dfen; intern 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 4.9.10 - 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. \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\" \/>\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) 4.9.10\" \/>\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. \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\" \/>\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\udd47Praktische Architekturmuster | ProHoster","description":"Hallo, Habr! Angesichts der aktuellen Ereignisse rund um das Coronavirus haben viele Internetdienste einen erh\u00f6hten Ansturm zu verzeichnen. Ein Beispiel ist eine Einzelhandelskette in Gro\u00dfbritannien, die ihren Online-Bestellservice vor\u00fcbergehend eingestellt hat, da die Kapazit\u00e4ten nicht ausreichten. Es ist nicht immer m\u00f6glich, einen Server einfach durch leistungsst\u00e4rkere Hardware zu beschleunigen, doch die Kundenanfragen m\u00fcssen bearbeitet werden (ansonsten wandern sie zu den Konkurrenten). In diesem","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. \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","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"},"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}]}}