{"id":52389,"date":"2019-11-07T00:00:00","date_gmt":"2019-11-06T21:00:00","guid":{"rendered":"https:\/\/prohoster.info\/blog\/blog_prohoster\/kak-realizuetsya-otkazoustojchivaya-veb-arhitektura-v-platforme-mail-ru-cloud-solutions"},"modified":"2020-02-18T14:00:05","modified_gmt":"2020-02-18T11:00:05","slug":"kak-realizuetsya-otkazoustojchivaya-veb-arhitektura-v-platforme-mail-ru-cloud-solutions","status":"publish","type":"post","link":"https:\/\/prohoster.info\/de\/blog\/administrirovanie\/kak-realizuetsya-otkazoustojchivaya-veb-arhitektura-v-platforme-mail-ru-cloud-solutions","title":{"rendered":"Wie eine ausfallsichere Web-Architektur in der Plattform Mail.ru Cloud Solutions realisiert wird.","gt_translate_keys":[{"key":"rendered","format":"text"}]},"content":{"rendered":"<p><img decoding=\"async\" alt=\"Wie eine ausfallsichere Web-Architektur in der Plattform Mail.ru Cloud Solutions realisiert wird.\" src=\"\/wp-content\/uploads\/2019\/11\/fe7af07f3ac5ca4e75009993b742293e.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<br \/>\nHallo, Habr! Ich bin Artem Karamyshev, der Leiter des Systemadministrationsteams. <noindex><a rel=\"nofollow\" href=\"https:\/\/mcs.mail.ru\/\">Mail.Ru Cloud Solutions (MCS)<\/a><\/noindex>. Im letzten Jahr haben wir viele neue Produkte eingef\u00fchrt. Unser Ziel war es, sicherzustellen, dass die API-Dienste leicht skalierbar, ausfallsicher und in der Lage sind, pl\u00f6tzliche Benutzerlasten schnell zu bew\u00e4ltigen. Unsere Plattform basiert auf OpenStack, und ich m\u00f6chte Ihnen erz\u00e4hlen, welche Herausforderungen in Bezug auf die Ausfallsicherheit der Komponenten wir bew\u00e4ltigen mussten, um ein ausfallsicheres System zu erhalten. Ich denke, das wird auch f\u00fcr diejenigen interessant sein, die Produkte auf OpenStack entwickeln.<\/p>\n<p>Die allgemeine Ausfallsicherheit der Plattform ergibt sich aus der Robustheit ihrer Komponenten. Daher werden wir schrittweise alle Ebenen durchlaufen, auf denen wir Risiken erkannt und diese behoben haben.<\/p>\n<p>Die Video-Version dieser Geschichte, die aus einem Vortrag auf der Konferenz Uptime Day 4 stammt, die von <noindex><a rel=\"nofollow\" href=\"http:\/\/www.itsumma.ru\">ITSumma<\/a><\/noindex>organisiert wurde, kann angesehen werden <noindex><a rel=\"nofollow\" href=\"https:\/\/www.youtube.com\/watch?v=3b06MVou-vg&amp;list=PLmXjIrLllpkjwuIGkzBkLbI7oHtUadmvZ&amp;index=5\">auf dem YouTube-Kanal der Uptime Community.<\/a><\/noindex>. <br \/>\n<noindex><a rel=\"nofollow\" name=\"habracut\"><\/a><\/noindex><\/p>\n<h2>Die Ausfallsicherheit der physischen Architektur.<\/h2>\n<p>\nDer \u00f6ffentliche Teil der MCS-Cloud ist derzeit in zwei Tier-III-Rechenzentren untergebracht, die durch ein eigenes dunkles Glasfaser-Netzwerk verbunden sind, das auf physischer Ebene durch verschiedene Routen reserviert ist, mit einer Bandbreite von 200 Gbit\/s. Der Tier-III-Niveau gew\u00e4hrleistet die erforderliche Ausfallsicherheit der physischen Infrastruktur. <\/p>\n<p>Das dunkle Glasfaser-Netzwerk ist sowohl auf physischer als auch auf logischer Ebene reserviert. Der Prozess der Kanalreservierung war iterativ, es gab Schwierigkeiten, und wir verbessern kontinuierlich die Verbindung zwischen den Rechenzentren. <\/p>\n<blockquote><p>Zum Beispiel wurde nicht so lange her bei Arbeiten in einem Schacht neben einem der Rechenzentren mit einem Bagger ein Rohr durchbrochen, in dem sich sowohl das Haupt- als auch das Reserve-Optik-Kabel befanden. Unser Ausfall-sicherer Kommunikationskanal zum Rechenzentrum war an einem Punkt, dem Schacht, verletzlich. Infolgedessen verloren wir einen Teil der Infrastruktur. Wir zogen Lehren daraus und ergriffen eine Reihe von Ma\u00dfnahmen, einschlie\u00dflich der Verlegung von zus\u00e4tzlicher Optik durch den benachbarten Schacht.<\/p><\/blockquote>\n<p>\nIn den Rechenzentren befinden sich Pr\u00e4senzpunkte von Netzbetreibern, an die wir unsere Pr\u00e4fixe \u00fcber BGP \u00fcbertragen. F\u00fcr jede Netzwerkrichtung wird die beste Metrik ausgew\u00e4hlt, um unseren Kunden die bestm\u00f6gliche Verbindungsqualit\u00e4t zu gew\u00e4hrleisten. Wenn die Verbindung \u00fcber einen Anbieter unterbrochen wird, passen wir unsere Routing-Strategie auf verf\u00fcgbare Anbieter an.<\/p>\n<p>Im Falle eines Ausfalls eines Anbieters schalten wir automatisch auf den n\u00e4chsten um. Bei einem Ausfall eines der Rechenzentren haben wir eine Spiegelkopie unserer Dienste im zweiten Rechenzentrum, die die gesamte Last \u00fcbernehmen.<\/p>\n<p><img decoding=\"async\" alt=\"Wie eine ausfallsichere Web-Architektur in der Plattform Mail.ru Cloud Solutions realisiert wird.\" src=\"\/wp-content\/uploads\/2019\/11\/295ca212f48dd074d834154666e5b0c3.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<i>Ausfallsicherheit der physischen Infrastruktur<\/i><\/p>\n<h2>Womit wir Ausfallsicherheit auf Anwendungsebene gew\u00e4hrleisten<\/h2>\n<p>\nUnser Dienst basiert auf einer Reihe von Open-Source-Komponenten. <\/p>\n<p><b>ExaBGP<\/b> \u2014 ein Dienst, der eine Reihe von Funktionen mit Hilfe des dynamischen Routing-Protokolls auf Basis von BGP implementiert. Wir nutzen ihn aktiv, um unsere wei\u00dfen IP-Adressen anzuk\u00fcndigen, \u00fcber die Benutzer auf die API zugreifen.<\/p>\n<p><b>HAProxy<\/b> \u2014 hochbelastbarer Load-Balancer, der sehr flexible Load-Balancing-Regeln auf verschiedenen OSI-Modell-Ebenen erm\u00f6glicht. Wir verwenden ihn zum Balancieren vor all unseren Diensten: Datenbanken, Nachrichtenbroker, API-Dienste, Web-Dienste, unsere internen Projekte \u2014 alles steht hinter HAProxy.<\/p>\n<p><b>API-Anwendung<\/b> \u2014 Web-Anwendung, die in Python geschrieben ist und es dem Benutzer erm\u00f6glicht, seine Infrastruktur und seinen Dienst zu verwalten.<\/p>\n<p><b>Worker-Anwendung <\/b>(im Folgenden einfach Worker) \u2014 in den OpenStack-Diensten ist dies ein infrastruktureller Daemon, der es erm\u00f6glicht, API-Befehle in die Infrastruktur zu \u00fcbertragen. Zum Beispiel erfolgt die Erstellung einer Festplatte genau im Worker, w\u00e4hrend die Anfrage zur Erstellung in der API-Anwendung erfolgt. <\/p>\n<h2>Standardarchitektur der OpenStack-Anwendung<\/h2>\n<p>\nDie meisten Dienste, die f\u00fcr OpenStack entwickelt werden, folgen einem einheitlichen Paradigma. Ein Dienst besteht normalerweise aus zwei Teilen: API und Worker (Backend-Executoren). In der Regel ist die API eine WSGI-Anwendung in Python, die entweder als eigenst\u00e4ndiger Prozess (Daemon) oder mit einem bereits vorhandenen Webserver wie Nginx oder Apache ausgef\u00fchrt wird. Die API verarbeitet die Benutzeranfrage und \u00fcbergibt die weiteren Anweisungen an die Worker-Anwendung. Die \u00dcbertragung erfolgt \u00fcber einen Message Broker, typischerweise RabbitMQ, w\u00e4hrend andere Broker nur schlecht unterst\u00fctzt werden. Wenn Nachrichten im Broker ankommen, verarbeiten die Worker diese und geben bei Bedarf eine Antwort zur\u00fcck. <\/p>\n<p>Dieses Paradigma sieht isolierte gemeinsame Fehlerpunkte vor: RabbitMQ und die Datenbank. Allerdings ist RabbitMQ innerhalb eines Dienstes isoliert und kann theoretisch f\u00fcr jeden Dienst individuell sein. Daher trennen wir bei MCS diese Dienste m\u00f6glichst, indem wir f\u00fcr jedes einzelne Projekt eine separate Datenbank und ein separates RabbitMQ erstellen. Dieser Ansatz hat den Vorteil, dass im Falle eines Ausfalls an bestimmten anf\u00e4lligen Punkten nicht der gesamte Dienst ausf\u00e4llt, sondern nur ein Teil davon.<\/p>\n<p>Die Anzahl der Worker-Anwendungen ist unbegrenzt, sodass die API problemlos horizontal skaliert werden kann, um die Leistung und Ausfallsicherheit zu erh\u00f6hen, indem sie hinter Lastenausgleichssystemen platziert wird.<\/p>\n<blockquote><p>In einigen Diensten ist eine Koordination innerhalb des Dienstes erforderlich \u2013 insbesondere bei komplexen aufeinanderfolgenden Operationen zwischen APIs und Workern. In diesem Fall wird ein zentrales Koordinationssystem verwendet, wie zum Beispiel ein Cluster-System vom Typ Redis, Memcache, etcd, das es einem Worker erm\u00f6glicht, einem anderen mitzuteilen, dass diese Aufgabe ihm zugewiesen ist (\u201ebitte \u00fcbernimm sie nicht\u201c). Wir nutzen etcd. In der Regel kommunizieren die Worker aktiv mit der Datenbank, indem sie Informationen lesen und schreiben. Als Datenbank verwenden wir MariaDB, die sich in einem Multi-Master-Cluster befindet.\n<\/p><\/blockquote>\n<p>\nEin klassischer Einzelservice wird nach dem allgemein anerkannten Verfahren f\u00fcr OpenStack organisiert. Er kann als ein geschlossenes System betrachtet werden, bei dem die Methoden zur Skalierung und Ausfallsicherheit offensichtlich sind. Beispielsweise gen\u00fcgt es f\u00fcr die Ausfallsicherheit, einen Lastenausgleich vor der API einzurichten. Die Skalierung der Worker wird durch Erh\u00f6hung ihrer Anzahl erreicht. <\/p>\n<p>Ein Schwachpunkt im gesamten System sind RabbitMQ und MariaDB. Ihre Architektur verdient einen eigenen Artikel. In diesem Artikel m\u00f6chte ich mich auf die Ausfallsicherheit der API konzentrieren.<\/p>\n<p><img decoding=\"async\" alt=\"Wie eine ausfallsichere Web-Architektur in der Plattform Mail.ru Cloud Solutions realisiert wird.\" src=\"\/wp-content\/uploads\/2019\/11\/f39e5a8ae350864e311bf4db3b9c34b3.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<i>Architektur der OpenStack-Anwendung. Lastverteilung und Ausfallsicherheit der Cloud-Plattform.<\/i><\/p>\n<h2>Wir machen den HAProxy-Lastverteiler mit ExaBGP ausfallsicher.<\/h2>\n<p>\nUm unsere APIs skalierbar, schnell und ausfallsicher zu gestalten, haben wir einen Lastverteiler davor gesetzt. Wir haben uns f\u00fcr HAProxy entschieden, da er in meinen Augen alle notwendigen Eigenschaften f\u00fcr unsere Anforderungen besitzt: Lastverteilung auf mehreren OSI-Ebenen, Verwaltungsoberfl\u00e4che, Flexibilit\u00e4t und Skalierbarkeit, eine Vielzahl von Lastverteilungsverfahren und Unterst\u00fctzung f\u00fcr Sitzungstabellen.<\/p>\n<p>Das erste Problem, das gel\u00f6st werden musste, war die Ausfallsicherheit des Lastverteilers selbst. Allein die Installation eines Lastverteilers schafft ebenfalls einen Ausfallpunkt: f\u00e4llt der Lastverteiler aus, bricht der Dienst zusammen. Um dies zu vermeiden, haben wir HAProxy zusammen mit ExaBGP verwendet.<\/p>\n<p>ExaBGP erm\u00f6glicht die Implementierung eines \u00dcberwachungsmechanismus f\u00fcr den Dienststatus. Wir haben diesen Mechanismus verwendet, um die Funktionsf\u00e4higkeit von HAProxy zu \u00fcberpr\u00fcfen und im Falle von Problemen den HAProxy-Dienst aus BGP auszuschalten. <\/p>\n<p><b>Schema ExaBGP+HAProxy<\/b><\/p>\n<ol>\n<li>Wir installieren die ben\u00f6tigte Software ExaBGP und HAProxy auf drei Servern. <\/li>\n<li>Auf jedem der Server erstellen wir ein Loopback-Interface.<\/li>\n<li>Auf allen drei Servern tragen wir die gleiche \u00f6ffentliche IP-Adresse in dieses Interface ein.<\/li>\n<li>Die \u00f6ffentliche IP-Adresse wird \u00fcber ExaBGP im Internet angek\u00fcndigt. <\/li>\n<\/ol>\n<p>\nDie Ausfallsicherheit wird erreicht, indem dieselbe IP-Adresse von allen drei Servern angek\u00fcndigt wird. Aus Sicht des Netzwerks ist die gleiche Adresse von drei verschiedenen Next Hops zug\u00e4nglich. Der Router sieht drei identische Routen und w\u00e4hlt diejenige mit der h\u00f6chsten Priorit\u00e4t basierend auf seiner eigenen Metrik (in der Regel ist es die gleiche Option), sodass der Verkehr nur zu einem der Server geleitet wird. <\/p>\n<p>Im Falle von Problemen mit HAProxy oder dem Ausfall eines Servers h\u00f6rt ExaBGP auf, die Route anzuk\u00fcndigen, und der Verkehr wechselt reibungslos zu einem anderen Server. <\/p>\n<p>So haben wir die Ausfallsicherheit des Load-Balancers erreicht.<\/p>\n<p><img decoding=\"async\" alt=\"Wie eine ausfallsichere Web-Architektur in der Plattform Mail.ru Cloud Solutions realisiert wird.\" src=\"\/wp-content\/uploads\/2019\/11\/9fba0718176dc1266f25a2c01ec87348.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<i>Ausfallsicherheit der HAProxy-Load-Balancer<\/i><\/p>\n<p>Das Schema ist nicht perfekt geworden: Wir haben gelernt, HAProxy zu reservieren, aber nicht, die Last innerhalb der Dienste zu verteilen. Daher haben wir das Schema etwas erweitert: Wir haben die Balance zwischen mehreren wei\u00dfen IP-Adressen eingef\u00fchrt.<\/p>\n<h2>DNS-basierte Lastverteilung plus BGP<\/h2>\n<p>\nDie Frage der Lastverteilung vor unseren HAProxy ist noch offen. Dennoch l\u00e4sst sie sich recht einfach l\u00f6sen, wie wir es auch bei uns gemacht haben.<\/p>\n<p>F\u00fcr die Lastverteilung von drei Servern werden 3 \u00f6ffentliche IP-Adressen und der alte gute DNS ben\u00f6tigt. Jede dieser Adressen wird dem Loopback-Interface jedes HAProxy zugeordnet und im Internet angek\u00fcndigt. <\/p>\n<p>In OpenStack wird ein Serviceverzeichnis zur Verwaltung von Ressourcen verwendet, in dem der API-Endpunkt des jeweiligen Dienstes festgelegt wird. In diesem Verzeichnis tragen wir den Domainnamen \u2014 public.infra.mail.ru ein, der \u00fcber DNS auf drei verschiedene IP-Adressen aufgel\u00f6st wird. So erhalten wir eine Lastverteilung zwischen den drei Adressen \u00fcber DNS. <\/p>\n<p>Da wir bei der Ank\u00fcndigung von \u00f6ffentlichen IP-Adressen die Priorit\u00e4ten bei der Serverauswahl nicht steuern, bis es zur Lastverteilung kommt, wird in der Regel nur ein Server basierend auf der IP-Adresse ausgew\u00e4hlt, w\u00e4hrend die beiden anderen unt\u00e4tig bleiben, da keine Metriken im BGP angegeben sind.<\/p>\n<p>Wir haben begonnen, Routen \u00fcber ExaBGP mit unterschiedlichen Metriken auszugeben. Jeder Lastverteiler k\u00fcndigt alle drei \u00f6ffentlichen IP-Adressen an, aber eine davon, die Hauptadresse f\u00fcr diesen Lastverteiler, wird mit der niedrigsten Metrik angek\u00fcndigt. Solange alle drei Lastverteiler einsatzbereit sind, gelangen die Anfragen zur ersten IP-Adresse an den ersten Lastverteiler, Anfragen zur zweiten an den zweiten und zur dritten an den dritten.<\/p>\n<p>Was passiert, wenn einer der Lastverteiler ausf\u00e4llt? Bei einem Ausfall eines Lastverteilers wird die Hauptadresse weiterhin von den beiden anderen angek\u00fcndigt, und der Verkehr zwischen ihnen wird umverteilt. Dadurch liefern wir dem Nutzer \u00fcber DNS mehrere IP-Adressen gleichzeitig. Durch die DNS-Balancierung und unterschiedliche Metriken erreichen wir eine gleichm\u00e4\u00dfige Lastverteilung auf alle drei Lastverteiler und verlieren dabei nicht die Ausfallsicherheit.<\/p>\n<p><img decoding=\"async\" alt=\"Wie eine ausfallsichere Web-Architektur in der Plattform Mail.ru Cloud Solutions realisiert wird.\" src=\"\/wp-content\/uploads\/2019\/11\/1485367a934aea06b68c6d05c184d263.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<i>HAProxy-Lastverteilung basierend auf DNS + BGP<\/i><\/p>\n<h2>Interaktion zwischen ExaBGP und HAProxy<\/h2>\n<p>\nWir haben also die Ausfallsicherheit f\u00fcr den Fall eines Serverausfalls implementiert, basierend auf dem Ausbleiben von Routenank\u00fcndigungen. Aber HAProxy kann aus anderen Gr\u00fcnden ausfallen als ein Serverausfall: Verwaltungsfehler, interne Dienstfehler. Wir m\u00f6chten den defekten Lastenausgleich aus der Last nehmen und daf\u00fcr ist ein anderer Mechanismus erforderlich. <\/p>\n<p>Daher haben wir, um das vorherige Schema zu erweitern, ein Heartbeat zwischen ExaBGP und HAProxy implementiert. Dies ist eine Softwareimplementierung f\u00fcr die Interaktion zwischen ExaBGP und HAProxy, bei der ExaBGP benutzerdefinierte Skripte verwendet, um den Status von Anwendungen zu \u00fcberpr\u00fcfen.<\/p>\n<p>Daf\u00fcr muss im ExaBGP-Konfigurationsfile ein Health Checker eingerichtet werden, der den Status von HAProxy pr\u00fcfen kann. In unserem Fall haben wir einen Health Backend in HAProxy konfiguriert, w\u00e4hrend wir von ExaBGP aus eine einfache GET-Anfrage zur \u00dcberpr\u00fcfung verwenden. Wenn die Ank\u00fcndigung aufh\u00f6rt, bedeutet das wahrscheinlich, dass HAProxy nicht funktioniert, und es ist nicht notwendig, es anzuk\u00fcndigen. <\/p>\n<p><img decoding=\"async\" alt=\"Wie eine ausfallsichere Web-Architektur in der Plattform Mail.ru Cloud Solutions realisiert wird.\" src=\"\/wp-content\/uploads\/2019\/11\/d5cda30043fe02ab81355b28c0d83ac6.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<i>HAProxy Health Check<\/i><\/p>\n<h2>HAProxy Peers: Sitzungssynchronisation <\/h2>\n<p>\nDer n\u00e4chste Schritt bestand darin, die Sitzungen zu synchronisieren. Bei der Arbeit mit verteilten Lastenausgleichern ist es schwierig, Informationen \u00fcber die Kundensitzungen zu speichern. Doch HAProxy geh\u00f6rt zu den wenigen Lastenausgleichern, die dies dank der Funktion Peers \u2014 der M\u00f6glichkeit des Transfers von Sitzungstabellen zwischen verschiedenen HAProxy-Prozessen \u2014 k\u00f6nnen. <\/p>\n<p>Es gibt verschiedene Methoden des Lastenausgleichs: einfache, wie <noindex><a rel=\"nofollow\" href=\"https:\/\/ru.wikipedia.org\/wiki\/Round-robin_(%D0%B0%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC)\">Round-Robin<\/a><\/noindex>, und erweiterte, bei denen die Sitzung des Kunden gespeichert wird, sodass er bei jeder Anfrage denselben Server erreicht wie zuvor. Wir wollten die zweite Option umsetzen.<\/p>\n<p>In HAProxy wird dieser Mechanismus zur Speicherung der Kundensitzungen mit stick-tables realisiert. Diese speichern die urspr\u00fcngliche IP-Adresse des Kunden, die ausgew\u00e4hlten Zieladressen (Backends) und einige Verwaltungsinformationen. \u00dcblicherweise werden stick-tables genutzt, um das Pair von source-IP + destination-IP zu speichern, was besonders n\u00fctzlich f\u00fcr Anwendungen ist, die den Sitzungskontext des Benutzers beim Wechsel zu einem anderen Lastenausgleicher nicht \u00fcbertragen k\u00f6nnen, beispielsweise im RoundRobin-Modus.<\/p>\n<p>Wenn die stick-Tabelle dazu gebracht wird, zwischen verschiedenen HAProxy-Prozessen zu wechseln (zwischen denen das Load Balancing erfolgt), k\u00f6nnen unsere Load Balancer mit einem einzigen Pool von stick-Tabellen arbeiten. Dies erm\u00f6glicht ein nahtloses Umschalten des Client-Netzwerks, wenn einer der Load Balancer ausf\u00e4llt; die Arbeit mit den Clientsitzungen wird auf denselben Backends fortgesetzt, die zuvor ausgew\u00e4hlt wurden.<\/p>\n<p>F\u00fcr den korrekten Betrieb muss das Problem mit der Quell-IP-Adresse des Load Balancers, von dem die Sitzung eingerichtet wurde, gel\u00f6st werden. In unserem Fall ist dies die dynamische Adresse auf dem Loopback-Interface. <\/p>\n<p>Die korrekte Funktion der Peers wird nur unter bestimmten Bedingungen erreicht. Das bedeutet, dass die TCP-Timeouts ausreichend gro\u00df sein m\u00fcssen oder das Umschalten schnell genug erfolgen muss, damit die TCP-Sitzung nicht abbricht. Dennoch erm\u00f6glicht dies ein nahtloses Umschalten. <\/p>\n<p>In unserem IaaS gibt es einen Dienst, der auf der gleichen Technologie basiert. Das ist <noindex><a rel=\"nofollow\" href=\"https:\/\/mcs.mail.ru\/app\/services\/infra\/balancers-list\/\">Load Balancer als Dienst f\u00fcr OpenStack<\/a><\/noindex>, der Octavia genannt wird. Er basiert auf zwei HAProxy-Prozessen und unterst\u00fctzt urspr\u00fcnglich Peers. In diesem Dienst haben sie sich hervorragend bew\u00e4hrt.<\/p>\n<p>Das Bild zeigt schematisch die Verschiebung von Peers-Tabellen zwischen drei HAProxy-Instanzen, es wird eine Konfiguration vorgeschlagen, wie man dies einrichten kann:<\/p>\n<p><img decoding=\"async\" alt=\"Wie eine ausfallsichere Web-Architektur in der Plattform Mail.ru Cloud Solutions realisiert wird.\" src=\"\/wp-content\/uploads\/2019\/11\/d31fab761da627923345b7ace7f0b943.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<i>HAProxy Peers (Sitzungssynchronisation)<\/i><\/p>\n<p>Wenn Sie ein \u00e4hnliches Schema implementieren, m\u00fcssen Sie dessen Funktionalit\u00e4t sorgf\u00e4ltig testen. Es ist nicht garantiert, dass es in genau der gleichen Form in 100 % der F\u00e4lle funktioniert. Aber zumindest verlieren Sie keine Stick-Tabellen, wenn Sie sich an die Quell-IP des Clients erinnern m\u00fcssen.<\/p>\n<h2>Begrenzung der Anzahl gleichzeitiger Anfragen von demselben Client<\/h2>\n<p>\nAlle \u00f6ffentlich zug\u00e4nglichen Dienste, einschlie\u00dflich unserer APIs, k\u00f6nnen von Anfragefluten betroffen sein. Die Gr\u00fcnde k\u00f6nnen sehr unterschiedlich sein, von Benutzerfehlern bis hin zu gezielten Angriffen. Wir werden regelm\u00e4\u00dfig durch IP-Adressen DDoS angegriffen. Kunden machen oft Fehler in ihren Skripten und verursachen damit Mini-DDoS-Attacken.<\/p>\n<p>In jedem Fall muss zus\u00e4tzlicher Schutz eingeplant werden. Eine offensichtliche L\u00f6sung besteht darin, die Anzahl der Anfragen an die API zu begrenzen und keine CPU-Zeit f\u00fcr die Verarbeitung b\u00f6sartiger Anfragen aufzuwenden.<\/p>\n<p>Um solche Begrenzungen zu implementieren, verwenden wir Rate Limits, die auf HAProxy basieren und dieselben Stick-Tabellen nutzen. Die Limits lassen sich relativ einfach einstellen und erm\u00f6glichen es, die Anzahl der API-Anfragen eines Benutzers zu begrenzen. Der Algorithmus speichert die Quell-IP, von der Anfragen gesendet werden, und limitiert die Anzahl gleichzeitiger Anfragen von einem Nutzer. Selbstverst\u00e4ndlich haben wir das durchschnittliche Lastprofil der API f\u00fcr jeden Dienst ermittelt und einen Limit von etwa dem Zehnfachen dieses Wertes festgelegt. Wir beobachten die Situation weiterhin aufmerksam und halten den Puls der Zeit.<\/p>\n<p>Wie sieht das in der Praxis aus? Wir haben Kunden, die unsere APIs zur automatischen Skalierung permanent nutzen. Sie erstellen morgens etwa zweihundert bis dreihundert virtuelle Maschinen und l\u00f6schen sie am Abend wieder. Um in OpenStack eine virtuelle Maschine zu erstellen, einschlie\u00dflich PaaS-Diensten, sind mindestens 1000 API-Anfragen n\u00f6tig, da die Interaktion zwischen den Diensten ebenfalls \u00fcber APIs erfolgt. <\/p>\n<p>Solche Aufgabenverschiebungen verursachen eine erhebliche Belastung. Wir haben diese Belastung bewertet, die t\u00e4glichen Spitzen erfasst, sie verzehnfacht und das wurde unser Rate-Limit. Wir sind st\u00e4ndig am Puls der Zeit. Oft beobachten wir Bots und Scanner, die versuchen, uns zu \u00fcberwachen, ob wir irgendwelche CGA-Skripte haben, die sie starten k\u00f6nnen, und wir schneiden diese aktiv ab.<\/p>\n<h2>Wie man den Code unauff\u00e4llig f\u00fcr die Benutzer aktualisiert.<\/h2>\n<p>\nWir implementieren die Ausfallsicherheit auch auf der Ebene der Code-Deploy-Prozesse. Bei Rollouts k\u00f6nnen Fehler auftreten, aber deren Einfluss auf die Verf\u00fcgbarkeit der Dienste kann minimiert werden.<\/p>\n<p>Wir aktualisieren st\u00e4ndig unsere Dienste und m\u00fcssen den Prozess der Aktualisierung der Codebasis ohne Auswirkungen auf die Benutzer sicherstellen. Diese Aufgabe konnten wir mithilfe der HAProxy-Management-Funktionen und der Umsetzung eines Graceful Shutdown in unseren Diensten l\u00f6sen.<\/p>\n<p>Um diese Aufgabe zu l\u00f6sen, war es notwendig, die Steuerung des Load Balancers und das 'richtige' Herunterfahren der Dienste zu gew\u00e4hrleisten:<\/p>\n<ul>\n<li>Im Fall von HAProxy erfolgt die Verwaltung \u00fcber eine Stats-Datei, die im Wesentlichen ein Socket ist und in der HAProxy-Konfiguration definiert wird. Befehle k\u00f6nnen \u00fcber stdio \u00fcbergeben werden. Unser Hauptwerkzeug zur Kontrolle der Konfigurationen ist jedoch Ansible, weshalb es ein integriertes Modul zur Verwaltung von HAProxy gibt, das wir aktiv nutzen. <\/li>\n<li>Der Gro\u00dfteil unserer API- und Engine-Dienste unterst\u00fctzt Technologien f\u00fcr ein sanftes Herunterfahren: Beim Ausschalten warten sie auf den Abschluss der aktuellen Aufgabe, sei es eine HTTP-Anfrage oder eine andere Dienstaufgabe. Das Gleiche gilt f\u00fcr den Worker. Er kennt alle Aufgaben, die er erledigt, und beendet sich, wenn er alles erfolgreich abgeschlossen hat. <\/li>\n<\/ul>\n<p>\nDank dieser beiden Aspekte sieht unser sicherer Deployment-Algorithmus folgenderma\u00dfen aus:<\/p>\n<ol>\n<li>Der Entwickler erstellt ein neues Codepaket (bei uns ist das ein RPM), testet es in der Entwicklungsumgebung, testet es in der Staging-Umgebung und hinterl\u00e4sst es im Staging-Repository.<\/li>\n<li>Der Entwickler stellt eine Anfrage f\u00fcr das Deployment mit einer m\u00f6glichst detaillierten Beschreibung der \"Artefakte\": Version des neuen Pakets, Beschreibung des neuen Funktionsumfangs und weitere Einzelheiten zum Deployment, falls erforderlich.<\/li>\n<li>Der Systemadministrator beginnt mit dem Update. Er startet das Ansible-Playbook, das wiederum Folgendes durchf\u00fchrt: \n<ul>\n<li>Es nimmt das Paket aus dem Stage-Repository und aktualisiert daraufhin die Versionsnummer des Pakets im Produktionsrepository.<\/li>\n<li>Es erstellt eine Liste der Backends des aktualisierten Services.<\/li>\n<li>Der erste zu aktualisierende Service wird in HAProxy deaktiviert, und es wird auf das Ende seiner Prozesse gewartet. Dank des sanften Herunterfahrens sind wir sicher, dass alle aktuellen Kundenanfragen erfolgreich abgeschlossen werden.<\/li>\n<li>Nach dem vollst\u00e4ndigen Stopp der API, der Worker und dem Ausschalten von HAProxy erfolgt ein Code-Update.<\/li>\n<li>Ansible startet die Dienste.<\/li>\n<li>F\u00fcr jeden Dienst werden bestimmte \"H\u00e4ndchen\" gezogen, die Unit-Tests anhand einer Reihe vordefinierter Schl\u00fcsseltests durchf\u00fchren. Es findet eine grundlegende Pr\u00fcfung des neuen Codes statt.<\/li>\n<li>Wenn im vorherigen Schritt keine Fehler festgestellt wurden, wird das Backend aktiviert.<\/li>\n<li>Wir gehen zum n\u00e4chsten Backend \u00fcber.<\/li>\n<\/ul>\n<\/li>\n<li>Nach dem Update aller Backends werden funktionale Tests gestartet. Wenn diese nicht ausreichen, pr\u00fcft der Entwickler jede neue Funktionalit\u00e4t, die er implementiert hat.<\/li>\n<\/ol>\n<p>\nDamit ist das Deployment abgeschlossen.<\/p>\n<p><img decoding=\"async\" alt=\"Wie eine ausfallsichere Web-Architektur in der Plattform Mail.ru Cloud Solutions realisiert wird.\" src=\"\/wp-content\/uploads\/2019\/11\/2d889fe1af33653e4bfebabe1cce6552.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<i>Der Aktualisierungszyklus des Services.<\/i><\/p>\n<p>Dieses Schema w\u00e4re nicht funktionsf\u00e4hig, wenn wir nicht eine Regel h\u00e4tten. Wir unterst\u00fctzen gleichzeitig die alte und die neue Version in Betrieb. Vorausgesetzt, in der Softwareentwicklung wird festgelegt, dass selbst wenn es \u00c4nderungen in der Datenbank des Dienstes gibt, sie den vorherigen Code nicht brechen werden. Infolgedessen erfolgt eine schrittweise Aktualisierung der Codebasis.<\/p>\n<h2>Fazit<\/h2>\n<p>\nWenn ich meine Gedanken zur ausfallsicheren WEB-Architektur teile, m\u00f6chte ich die wesentlichen Punkte noch einmal betonen:<\/p>\n<ul>\n<li>physische Ausfallsicherheit;<\/li>\n<li>Netzwerkausfallsicherheit (Lastenausgleich, BGP);<\/li>\n<li>Ausfallsicherheit der verwendeten und entwickelten Software.<\/li>\n<\/ul>\n<p>\nAllen stabile Betriebszeiten!<br \/>\n<br \/>Quelle: <a content=\"nofollow\" rel=\"nofollow\" href=\"https:\/\/habr.com\/ru\/company\/mailru\/blog\/474180\/\">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! \u042f \u0410\u0440\u0442\u0435\u043c \u041a\u0430\u0440\u0430\u043c\u044b\u0448\u0435\u0432, \u0440\u0443\u043a\u043e\u0432\u043e\u0434\u0438\u0442\u0435\u043b\u044c \u043a\u043e\u043c\u0430\u043d\u0434\u044b \u0441\u0438\u0441\u0442\u0435\u043c\u043d\u043e\u0433\u043e \u0430\u0434\u043c\u0438\u043d\u0438\u0441\u0442\u0440\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f Mail.Ru Cloud Solutions (MCS). \u0417\u0430 \u043f\u043e\u0441\u043b\u0435\u0434\u043d\u0438\u0439 \u0433\u043e\u0434 \u0443 \u043d\u0430\u0441 \u0431\u044b\u043b\u043e \u043c\u043d\u043e\u0433\u043e \u0437\u0430\u043f\u0443\u0441\u043a\u043e\u0432 \u043d\u043e\u0432\u044b\u0445 \u043f\u0440\u043e\u0434\u0443\u043a\u0442\u043e\u0432. \u041c\u044b \u0445\u043e\u0442\u0435\u043b\u0438 \u0434\u043e\u0431\u0438\u0442\u044c\u0441\u044f, \u0447\u0442\u043e\u0431\u044b API-\u0441\u0435\u0440\u0432\u0438\u0441\u044b \u043b\u0435\u0433\u043a\u043e \u043c\u0430\u0441\u0448\u0442\u0430\u0431\u0438\u0440\u043e\u0432\u0430\u043b\u0438\u0441\u044c, \u0431\u044b\u043b\u0438 \u043e\u0442\u043a\u0430\u0437\u043e\u0443\u0441\u0442\u043e\u0439\u0447\u0438\u0432\u044b\u043c\u0438 \u0438 \u0433\u043e\u0442\u043e\u0432\u044b\u043c\u0438 \u043a \u0431\u044b\u0441\u0442\u0440\u043e\u043c\u0443 \u0440\u043e\u0441\u0442\u0443 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044c\u0441\u043a\u043e\u0439 \u043d\u0430\u0433\u0440\u0443\u0437\u043a\u0438. \u041d\u0430\u0448\u0430 \u043f\u043b\u0430\u0442\u0444\u043e\u0440\u043c\u0430 \u0440\u0435\u0430\u043b\u0438\u0437\u043e\u0432\u0430\u043d\u0430 \u043d\u0430 OpenStack, \u0438 \u044f \u0445\u043e\u0447\u0443 \u0440\u0430\u0441\u0441\u043a\u0430\u0437\u0430\u0442\u044c, \u043a\u0430\u043a\u0438\u0435 \u043f\u0440\u043e\u0431\u043b\u0435\u043c\u044b \u043e\u0442\u043a\u0430\u0437\u043e\u0443\u0441\u0442\u043e\u0439\u0447\u0438\u0432\u043e\u0441\u0442\u0438 \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442\u043e\u0432 \u043d\u0430\u043c \u043f\u0440\u0438\u0448\u043b\u043e\u0441\u044c \u0437\u0430\u043a\u0440\u044b\u0442\u044c, [&hellip;]<\/p>\n","protected":false,"gt_translate_keys":[{"key":"rendered","format":"html"}]},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[688],"tags":[],"class_list":["post-52389","post","type-post","status-publish","format-standard","hentry","category-administrirovanie"],"aioseo_notices":[],"aioseo_head":"\n\t\t<!-- All in One SEO 5.0.0.1 - aioseo.com -->\n\t<meta name=\"description\" content=\".\" \/>\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\/kak-realizuetsya-otkazoustojchivaya-veb-arhitektura-v-platforme-mail-ru-cloud-solutions\" \/>\n\t<meta name=\"generator\" content=\"All in One SEO (AIOSEO) 5.0.0.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\u041a\u0430\u043a \u0440\u0435\u0430\u043b\u0438\u0437\u0443\u0435\u0442\u0441\u044f \u043e\u0442\u043a\u0430\u0437\u043e\u0443\u0441\u0442\u043e\u0439\u0447\u0438\u0432\u0430\u044f \u0432\u0435\u0431-\u0430\u0440\u0445\u0438\u0442\u0435\u043a\u0442\u0443\u0440\u0430 \u0432 \u043f\u043b\u0430\u0442\u0444\u043e\u0440\u043c\u0435 Mail.ru Cloud Solutions | ProHoster\" \/>\n\t\t<meta property=\"og:description\" content=\".\" \/>\n\t\t<meta property=\"og:url\" content=\"https:\/\/prohoster.info\/de\/blog\/administrirovanie\/kak-realizuetsya-otkazoustojchivaya-veb-arhitektura-v-platforme-mail-ru-cloud-solutions\" \/>\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-11-06T21:00:00+00:00\" \/>\n\t\t<meta property=\"article:modified_time\" content=\"2020-02-18T11:00:05+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\udd47Wie eine ausfallsichere Webarchitektur auf der Plattform Mail.ru Cloud Solutions umgesetzt wird | ProHoster","description":".","canonical_url":"https:\/\/prohoster.info\/de\/blog\/administrirovanie\/kak-realizuetsya-otkazoustojchivaya-veb-arhitektura-v-platforme-mail-ru-cloud-solutions","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\u041a\u0430\u043a \u0440\u0435\u0430\u043b\u0438\u0437\u0443\u0435\u0442\u0441\u044f \u043e\u0442\u043a\u0430\u0437\u043e\u0443\u0441\u0442\u043e\u0439\u0447\u0438\u0432\u0430\u044f \u0432\u0435\u0431-\u0430\u0440\u0445\u0438\u0442\u0435\u043a\u0442\u0443\u0440\u0430 \u0432 \u043f\u043b\u0430\u0442\u0444\u043e\u0440\u043c\u0435 Mail.ru Cloud Solutions | ProHoster","og:description":".","og:url":"https:\/\/prohoster.info\/de\/blog\/administrirovanie\/kak-realizuetsya-otkazoustojchivaya-veb-arhitektura-v-platforme-mail-ru-cloud-solutions","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-11-06T21:00:00+00:00","article:modified_time":"2020-02-18T11:00:05+00:00","article:publisher":"https:\/\/www.facebook.com\/prohoster","article:author":"https:\/\/www.facebook.com\/prohoster"},"aioseo_meta_data":{"post_id":"52389","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-01-24 03:27:21","breadcrumb_settings":null,"limit_modified_date":false,"reviewed_by":null,"ai":null,"created":"2021-02-28 20:44:43","updated":"2026-01-24 03:27:21","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\/52389","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=52389"}],"version-history":[{"count":0,"href":"https:\/\/prohoster.info\/de\/wp-json\/wp\/v2\/posts\/52389\/revisions"}],"wp:attachment":[{"href":"https:\/\/prohoster.info\/de\/wp-json\/wp\/v2\/media?parent=52389"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/prohoster.info\/de\/wp-json\/wp\/v2\/categories?post=52389"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/prohoster.info\/de\/wp-json\/wp\/v2\/tags?post=52389"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}