{"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 wird eine ausfallsichere Web-Architektur in der Plattform Mail.ru Cloud Solutions implementiert","gt_translate_keys":[{"key":"rendered","format":"text"}]},"content":{"rendered":"<p><img decoding=\"async\" alt=\"Wie wird eine ausfallsichere Web-Architektur in der Plattform Mail.ru Cloud Solutions implementiert\" src=\"\/wp-content\/uploads\/2019\/11\/fe7af07f3ac5ca4e75009993b742293e.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<br \/>\nHallo, Habr! Ich bin Artem Karamishev, Leiter des Systemadministrationsteams <noindex><a rel=\"nofollow\" href=\"https:\/\/mcs.mail.ru\/\">Mail.Ru Cloud Solutions (MCS)<\/a><\/noindex>. Im vergangenen Jahr haben wir viele neue Produkte gestartet. Wir wollten, dass API-Dienste skalierbar, ausfallsicher und f\u00fcr schnelles Wachstum der Benutzerlast bereit sind. Unsere Plattform basiert auf OpenStack und ich m\u00f6chte erz\u00e4hlen, welche Herausforderungen zur Ausfallsicherheit von Komponenten wir bew\u00e4ltigen mussten, um ein ausfallsicheres System zu erhalten. Ich denke, das wird f\u00fcr diejenigen interessant sein, die ebenfalls Produkte auf OpenStack entwickeln.<\/p>\n<p>Die allgemeine Ausfallsicherheit der Plattform setzt sich aus der Robustheit ihrer Komponenten zusammen. Wir werden also schrittweise alle Ebenen durchgehen, auf denen wir Risiken identifiziert und behoben haben.<\/p>\n<p>Die Video-Version dieser Geschichte, die urspr\u00fcnglich aus einem Vortrag auf der Uptime day 4 Konferenz stammt, organisiert von <noindex><a rel=\"nofollow\" href=\"http:\/\/www.itsumma.ru\">ITSumma<\/a><\/noindex>, 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 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 basiert derzeit auf zwei Tier III-Rechenzentren, zwischen denen ein eigenes dunkles Glasfaser vorhanden ist, das auf physischer Ebene durch verschiedene Routen reserviert ist und eine Bandbreite von 200 Gbit\/s bietet. Tier III bietet das erforderliche Ma\u00df an Ausfallsicherheit f\u00fcr die physische Infrastruktur. <\/p>\n<p>Das dunkle Glasfaser ist sowohl auf physischer als auch auf logischer Ebene reserviert. Der Prozess der Kanalsicherung war iterativ, es traten Probleme auf und wir verbessern st\u00e4ndig die Verbindung zwischen den Rechenzentren. <\/p>\n<blockquote><p>Zum Beispiel wurde vor kurzem bei Arbeiten in einem Schacht neben einem der Rechenzentren mit einem Bagger ein Rohr durchbohrt, in diesem Rohr befanden sich sowohl das Haupt- als auch das \u0440\u0435\u0437\u0435\u0440\u0432\u043d\u044b\u0439 optische Kabel. Unser ausfallsicherer Kommunikationskanal mit dem Rechenzentrum war an einem Punkt im Schacht anf\u00e4llig. Entsprechend haben wir einen Teil der Infrastruktur verloren. Wir haben Lehren daraus gezogen, eine Reihe von Ma\u00dfnahmen ergriffen und unter anderem optische Kabel im benachbarten Schacht verlegt.<\/p><\/blockquote>\n<p>\nIn den Rechenzentren gibt es Standorte von Netzwerkdienstanbietern, an die wir unsere Pr\u00e4fixe \u00fcber BGP \u00fcbertragen. F\u00fcr jede Netzwerkrichtung wird die beste Metrik ausgew\u00e4hlt, was es uns erm\u00f6glicht, unseren Kunden die beste Verbindungsqualit\u00e4t zu bieten. Wenn die Verbindung \u00fcber einen Anbieter unterbrochen wird, stellen wir unsere Routing-Strategie auf die verf\u00fcgbaren Anbieter um.<\/p>\n<p>Im Falle eines Ausfalls des Anbieters wechseln wir automatisch zum n\u00e4chsten. 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 wird eine ausfallsichere Web-Architektur in der Plattform Mail.ru Cloud Solutions implementiert\" 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>Was wir f\u00fcr die Ausfallsicherheit auf Anwendungsebene verwenden<\/h2>\n<p>\nUnser Service basiert auf einer Reihe von Open-Source-Komponenten. <\/p>\n<p><b>ExaBGP<\/b> \u2014 ein Service, der eine Reihe von Funktionen mithilfe des dynamischen Routing-Protokolls auf Basis von BGP implementiert. Wir nutzen ihn aktiv, um unsere \u00f6ffentlichen IP-Adressen anzuk\u00fcndigen, \u00fcber die Benutzer Zugriff auf die API erhalten.<\/p>\n<p><b>HAProxy<\/b> \u2014 ein hochbelasteter Load Balancer, der es erm\u00f6glicht, sehr flexible Regeln zur Lastverteilung auf verschiedenen Ebenen des OSI-Modells zu konfigurieren. Wir verwenden ihn zur Lastverteilung vor allen Diensten: Datenbanken, Nachrichtenbroker, API-Dienste, Web-Dienste, unsere internen Projekte \u2013 alles l\u00e4uft hinter HAProxy.<\/p>\n<p><b>API-Anwendung<\/b> \u2014 eine Webanwendung, die in Python geschrieben wurde und es dem Benutzer erm\u00f6glicht, seine Infrastruktur und seinen Service zu verwalten.<\/p>\n<p><b>Worker-Anwendung <\/b>(im Folgenden einfach Worker) \u2013 in den OpenStack-Diensten ist dies ein Infrastrukturd\u00e4mon, der es erm\u00f6glicht, API-Befehle an die Infrastruktur zu \u00fcbertragen. Beispielsweise wird die Erstellung einer Festplatte genau im Worker durchgef\u00fchrt, 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, versuchen, einer einheitlichen Paradigma zu folgen. Ein Dienst besteht typischerweise 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 konfigurierten Webserver wie Nginx oder Apache l\u00e4uft. Die API verarbeitet die Benutzeranfragen und gibt die weiteren Anweisungen zur Durchf\u00fchrung an die Worker-Anwendung weiter. Die \u00dcbertragung erfolgt \u00fcber einen Nachrichtenbroker, der in der Regel RabbitMQ ist, w\u00e4hrend andere schlecht unterst\u00fctzt werden. Wenn die Nachrichten den Broker erreichen, werden sie von den Workern verarbeitet, die bei Bedarf eine Antwort zur\u00fcckgeben. <\/p>\n<p>Dieses Paradigma impliziert isolierte gemeinsame Ausfallpunkte: RabbitMQ und die Datenbank. RabbitMQ ist jedoch innerhalb eines Dienstes isoliert und kann theoretisch f\u00fcr jeden Dienst individuell sein. Daher trennen wir in MCS diese Dienste so weit wie m\u00f6glich, erstellen f\u00fcr jedes einzelne Projekt eine separate Datenbank und ein separates RabbitMQ. Dieser Ansatz hat den Vorteil, dass im Falle eines Ausfalls in bestimmten verwundbaren Punkten nicht der gesamte Dienst ausf\u00e4llt, sondern nur ein Teil davon.<\/p>\n<p>Die Anzahl der Worker-Anwendungen ist nicht begrenzt, sodass die API leicht horizontal skaliert werden kann, um die Leistung und Ausfallsicherheit zu erh\u00f6hen.<\/p>\n<blockquote><p>In einigen Diensten ist eine Koordination innerhalb des Dienstes erforderlich \u2013 wenn komplexe aufeinanderfolgende Operationen zwischen APIs und Workern stattfinden. In diesem Fall wird ein zentraler Koordinationspunkt verwendet, ein Clustersystem wie Redis, Memcache, etcd, das einem Worker erm\u00f6glicht, einem anderen mitzuteilen, dass diese Aufgabe ihm zugewiesen ist (\u201ebitte nimm sie nicht an\u201c). Wir verwenden etcd. In der Regel kommunizieren die Worker aktiv mit der Datenbank, schreiben und lesen Informationen daraus. Als Datenbank verwenden wir MariaDB, die sich in einem Multi-Master-Cluster befindet.\n<\/p><\/blockquote>\n<p>\nEin solcher klassischer Einzelservice ist auf die allgemein anerkannte Weise f\u00fcr OpenStack organisiert. Er kann als geschlossenes System betrachtet werden, f\u00fcr das die Skalierung und Ausfallsicherheit recht offensichtlich sind. Zum Beispiel ist es f\u00fcr die Ausfallsicherheit ausreichend, einen Lastenausgleichsserver vor der API zu setzen. Die Skalierung der Worker erfolgt durch Erh\u00f6hung ihrer Anzahl. <\/p>\n<p>Ein Schwachpunkt in der gesamten Architektur 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 wird eine ausfallsichere Web-Architektur in der Plattform Mail.ru Cloud Solutions implementiert\" 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-Load-Balancer ausfallsicher mit ExaBGP<\/h2>\n<p>\nUm sicherzustellen, dass unsere APIs skalierbar, schnell und ausfallsicher sind, haben wir einen Load-Balancer vor sie gesetzt. Wir haben uns f\u00fcr HAProxy entschieden. Meiner Meinung nach bietet er alle notwendigen Eigenschaften f\u00fcr unsere Aufgabe: Lastverteilung auf mehreren OSI-Ebenen, Verwaltungsoberfl\u00e4che, Flexibilit\u00e4t und Skalierbarkeit, eine gro\u00dfe Anzahl von Lastverteilungsmethoden, Unterst\u00fctzung f\u00fcr Sitzungstabellen.<\/p>\n<p>Das erste Problem, das gel\u00f6st werden musste, war die Ausfallsicherheit des Load-Balancers selbst. Die blo\u00dfe Installation eines Load-Balancers schafft ebenfalls einen Ausfallpunkt: Bricht der Load-Balancer zusammen, f\u00e4llt der Dienst aus. Um das zu verhindern, haben wir HAProxy zusammen mit ExaBGP verwendet.<\/p>\n<p>ExaBGP erm\u00f6glicht die Implementierung eines Mechanismus zur \u00dcberpr\u00fcfung des Dienststatus. Wir haben diesen Mechanismus genutzt, um die Funktionsf\u00e4higkeit von HAProxy zu \u00fcberpr\u00fcfen und im Falle von Problemen den HAProxy-Dienst aus BGP herauszunehmen. <\/p>\n<p><b>Schema ExaBGP+HAProxy<\/b><\/p>\n<ol>\n<li>Wir installieren die notwendige Software ExaBGP und HAProxy auf drei Servern. <\/li>\n<li>Auf jedem Server erstellen wir ein Loopback-Interface.<\/li>\n<li>Auf allen drei Servern weisen wir diesem Interface die gleiche \u00f6ffentliche IP-Adresse zu.<\/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 aus angek\u00fcndigt wird. Aus Sicht des Netzwerks ist die gleiche Adresse von drei verschiedenen Next Hops erreichbar. Der Router sieht drei identische Routen und w\u00e4hlt die bevorzugteste aus, basierend auf seiner Metrik (in der Regel ist dies dieselbe Option), und der Verkehr geht nur an einen der Server. <\/p>\n<p>Im Falle von Problemen mit HAProxy oder einem Ausfall des Servers h\u00f6rt ExaBGP auf, die Route anzuk\u00fcndigen, und der Verkehr wechselt sanft zu einem anderen Server. <\/p>\n<p>So haben wir die Ausfallsicherheit des Load-Balancers erreicht.<\/p>\n<p><img decoding=\"async\" alt=\"Wie wird eine ausfallsichere Web-Architektur in der Plattform Mail.ru Cloud Solutions implementiert\" 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 ideal ausgefallen: Wir haben gelernt, HAProxy ausfallsicher zu machen, aber nicht gelernt, die Last innerhalb der Dienste zu verteilen. Daher haben wir dieses Schema etwas erweitert: Wir haben auf die Lastverteilung zwischen mehreren \u00f6ffentlichen IP-Adressen umgestellt.<\/p>\n<h2>DNS- und BGP-basierte Lastenverteilung<\/h2>\n<p>\nDas Problem der Lastenverteilung vor unseren HAProxy ist noch ungel\u00f6st. Dennoch kann es recht einfach gel\u00f6st werden, wie wir es bei uns getan haben.<\/p>\n<p>F\u00fcr die Lastenverteilung von drei Servern werden 3 \u00f6ffentliche IP-Adressen und der gute alte DNS ben\u00f6tigt. Jede dieser Adressen wird auf das Loopback-Interface jedes HAProxy zugeordnet und im Internet angek\u00fcndigt. <\/p>\n<p>In OpenStack wird ein Dienstekatalog zur Verwaltung von Ressourcen verwendet, in dem der API-Endpunkt eines jeden Dienstes festgelegt wird. In diesem Katalog geben wir den Domainnamen \u2013 public.infra.mail.ru \u2013 an, der \u00fcber DNS auf drei verschiedene IP-Adressen aufgel\u00f6st wird. Dadurch erhalten wir eine Lastenverteilung \u00fcber die drei Adressen mittels DNS. <\/p>\n<p>Da wir bei der Ank\u00fcndigung der \u00f6ffentlichen IP-Adressen die Priorit\u00e4ten der Serverauswahl nicht steuern, handelt es sich bislang nicht um eine Lastenverteilung. In der Regel wird nur ein Server basierend auf der IP-Adressen-Hierarchie 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 verschiedenen Metriken anzubieten. Jeder Lastenverteilung hat alle drei \u00f6ffentlichen IP-Adressen angek\u00fcndigt, aber eine davon, die Hauptadresse f\u00fcr diesen Lastenverteilung, wird mit der minimalen Metrik angek\u00fcndigt. Solange alle drei Lastenverteilung aktiv sind, gelangen Anfragen an die erste IP-Adresse zum ersten Lastenverteilung, Anfragen an die zweite zur zweiten, und an die dritte zur dritten.<\/p>\n<p>Was passiert, wenn einer der Lastenverteilungen ausf\u00e4llt? Im Falle eines Ausfalls eines Lastenverteilung wird dessen Hauptadresse weiterhin von zwei anderen angek\u00fcndigt, und der Traffic zwischen ihnen wird umverteilt. So bieten wir dem Benutzer \u00fcber DNS mehrere IP-Adressen an. Durch die Lastenverteilung \u00fcber DNS und unterschiedliche Metriken erreichen wir eine gleichm\u00e4\u00dfige Lastenverteilung auf alle drei Lastenverteilungen, ohne die Fehlertoleranz zu verlieren.<\/p>\n<p><img decoding=\"async\" alt=\"Wie wird eine ausfallsichere Web-Architektur in der Plattform Mail.ru Cloud Solutions implementiert\" src=\"\/wp-content\/uploads\/2019\/11\/1485367a934aea06b68c6d05c184d263.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<i>Lastenverteilung von HAProxy basierend auf DNS + BGP<\/i><\/p>\n<h2>Interaktion zwischen ExaBGP und HAProxy<\/h2>\n<p>\nWir haben also die Fehlertoleranz f\u00fcr den Fall eines Serverausfalls implementiert, basierend auf dem Einsetzen der Routenank\u00fcndigungen. Aber HAProxy kann aus verschiedenen Gr\u00fcnden ausfallen, neben dem Ausfall eines Servers: Administrationsfehler, interne Dienstst\u00f6rungen. In diesen F\u00e4llen m\u00f6chten wir den defekten Lastenverteilung aus der Lastenverteilung entfernen, und daf\u00fcr ist ein anderer Mechanismus erforderlich. <\/p>\n<p>Daher haben wir das vorherige Schema erweitert und ein Heartbeat zwischen ExaBGP und HAProxy implementiert. Dies ist eine softwarebasierte Implementierung der Interaktion zwischen ExaBGP und HAProxy, wobei ExaBGP benutzerdefinierte Skripte zur \u00dcberpr\u00fcfung des Status der Anwendungen verwendet.<\/p>\n<p>Dazu muss im ExaBGP-Config ein Health Checker konfiguriert werden, der den Status von HAProxy \u00fcberpr\u00fcfen kann. In unserem Fall haben wir das Health Backend in HAProxy eingerichtet, und von Seiten ExaBGP pr\u00fcfen wir den Status mit einer einfachen GET-Anfrage. Wenn die Ank\u00fcndigung aufh\u00f6rt, dann funktioniert HAProxy h\u00f6chstwahrscheinlich nicht, und wir brauchen ihn nicht anzuk\u00fcndigen. <\/p>\n<p><img decoding=\"async\" alt=\"Wie wird eine ausfallsichere Web-Architektur in der Plattform Mail.ru Cloud Solutions implementiert\" 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: Sitzungsynchronisierung <\/h2>\n<p>\nDas N\u00e4chste, was zu tun war, war die Synchronisierung der Sitzungen. Bei der Arbeit mit verteilten Lastverteilern ist es schwierig, Informationen \u00fcber die Sitzungen der Kunden zu speichern. Doch HAProxy ist einer der wenigen Lastverteiler, die dies erm\u00f6glichen, dank der Funktionalit\u00e4t Peers \u2014 der M\u00f6glichkeit, zwischen verschiedenen HAProxy-Prozessen Sitzungstabellen zu \u00fcbertragen. <\/p>\n<p>Es gibt verschiedene Methoden der Lastverteilung: 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 und er jedes Mal denselben Server erreicht wie zuvor. Wir wollten die zweite Variante umsetzen.<\/p>\n<p>In HAProxy wird f\u00fcr die Speicherung der Sitzungen des Kunden dieser Mechanismus stick-tables verwendet. Diese speichern die urspr\u00fcngliche IP-Adresse des Kunden, die gew\u00e4hlte Zieladresse (Backend) und einige Dienstinformationen. Normalerweise werden Stick-Tabellen verwendet, um das Paar source-IP + destination-IP zu speichern, was besonders n\u00fctzlich ist f\u00fcr Anwendungen, die den Sitzungskontext des Benutzers nicht \u00fcber andere Lastverteiler hinweg \u00fcbertragen k\u00f6nnen, zum Beispiel im RoundRobin-Balancing-Modus.<\/p>\n<p>Wenn wir die Stick-Tabelle lehren, zwischen verschiedenen HAProxy-Prozessen (zwischen denen die Lastverteilung erfolgt) zu migrieren, k\u00f6nnen unsere Lastverteiler mit einem Pool von Stick-Tabellen arbeiten. Dies erm\u00f6glicht nahtloses Client-Netzwerk-Um-Schalten, wenn einer der Lastverteiler ausf\u00e4llt, und die Arbeit mit den Kunden-Sitzungen wird auf denselben Backends fortgesetzt, die zuvor ausgew\u00e4hlt wurden.<\/p>\n<p>F\u00fcr das ordnungsgem\u00e4\u00dfe Funktionieren muss das Problem der Quell-IP-Adresse des Lastverteilers gel\u00f6st werden, von dem die Sitzung hergestellt wurde. In unserem Fall handelt es sich um eine dynamische Adresse am Loopback-Interface. <\/p>\n<p>Die korrekte Funktion von Peers tritt nur unter bestimmten Bedingungen auf. Das bedeutet, dass die TCP-Timeouts gro\u00df genug sein m\u00fcssen oder der Wechsel schnell genug erfolgen muss, damit die TCP-Sitzung nicht abbricht. Dennoch erm\u00f6glicht dies nahtloses Umschalten. <\/p>\n<p>Wir haben in IaaS einen Dienst, der auf derselben Technologie basiert. Das ist <noindex><a rel=\"nofollow\" href=\"https:\/\/mcs.mail.ru\/app\/services\/infra\/balancers-list\/\">Load Balancer als Service f\u00fcr OpenStack<\/a><\/noindex>, der Octavia hei\u00dft. Er basiert auf zwei HAProxy-Prozessen und unterst\u00fctzt von Anfang an 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, ein vorgeschlagener Konfigurationsansatz, wie dies eingerichtet werden kann:<\/p>\n<p><img decoding=\"async\" alt=\"Wie wird eine ausfallsichere Web-Architektur in der Plattform Mail.ru Cloud Solutions implementiert\" 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, sollten Sie dessen Funktionalit\u00e4t sorgf\u00e4ltig testen. Es ist nicht garantiert, dass es in dieser Form in 100 % der F\u00e4lle funktioniert. Aber zumindest verlieren Sie keine Stick-Tabellen, wenn es notwendig ist, die Quell-IP des Clients im Ged\u00e4chtnis zu behalten.<\/p>\n<h2>Begrenzung der Anzahl gleichzeitiger Anfragen von demselben Client<\/h2>\n<p>\nAlle Dienste, die \u00f6ffentlich zug\u00e4nglich sind, einschlie\u00dflich unserer APIs, k\u00f6nnen von Anfragefluten betroffen sein. Ihre Ursachen k\u00f6nnen sehr unterschiedlich sein, von Benutzerfehlern bis hin zu gezielten Angriffen. Gelegentlich werden wir per DDoS-Angriff \u00fcber IP-Adressen angegriffen. Kunden machen oft Fehler in ihren Skripten und verursachen damit Mini-DDoS-Attacken.<\/p>\n<p>Wie auch immer, es ist notwendig, zus\u00e4tzlichen Schutz vorzusehen. Eine offensichtliche L\u00f6sung ist es, die Anzahl der Anfragen an die API zu begrenzen und keine Prozessorzeit f\u00fcr die Verarbeitung sch\u00e4dlicher Anfragen aufzuwenden.<\/p>\n<p>Um solche Begrenzungen umzusetzen, verwenden wir Rate Limits, die auf Grundlage von HAProxy organisiert sind, unter Verwendung derselben Stick-Tabellen. Die Limits lassen sich relativ einfach einstellen und erm\u00f6glichen es, die Anzahl der Anfragen eines Benutzers an die API zu beschr\u00e4nken. Der Algorithmus merkt sich die Quell-IP, von der die Anfragen kommen, und begrenzt die Anzahl gleichzeitiger Anfragen von einem Benutzer. Nat\u00fcrlich haben wir das durchschnittliche Lastprofil der API f\u00fcr jeden Dienst ermittelt und ein Limit festgelegt, das etwa 10-mal h\u00f6her ist als dieser Wert. Wir beobachten die Situation weiterhin genau und behalten die Kontrolle.<\/p>\n<p>Wie sieht das in der Praxis aus? Wir haben Kunden, die st\u00e4ndig unsere APIs f\u00fcr die automatisierte Skalierung nutzen. Sie erstellen etwa zweihundert bis dreihundert virtuelle Maschinen am Morgen und l\u00f6schen diese gegen Abend. Um in OpenStack eine virtuelle Maschine zu erstellen, zusammen mit PaaS-Diensten, ben\u00f6tigt man mindestens 1000 API-Anfragen, 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 ist unser Rate-Limit geworden. Wir haben die Situation stets im Blick. Oft sehen wir Bots und Scanner, die versuchen herauszufinden, ob wir irgendwelche CGA-Skripte haben, die sie starten k\u00f6nnen, und wir schneiden diese aktiv ab.<\/p>\n<h2>Wie man den Code-Bestand unbemerkt f\u00fcr die Benutzer aktualisiert<\/h2>\n<p>\nWir implementieren auch Ausfallsicherheit auf der Ebene des Code-Deployments. Bei den Rollouts kann es zu Ausf\u00e4llen kommen, jedoch l\u00e4sst sich deren Einfluss auf die Verf\u00fcgbarkeit der Dienste minimieren.<\/p>\n<p>Wir aktualisieren st\u00e4ndig unsere Dienste und m\u00fcssen den Prozess der Aktualisierung des Code-Bestands f\u00fcr die Benutzer ohne Auswirkungen gew\u00e4hrleisten. Diese Aufgabe konnten wir l\u00f6sen, indem wir die M\u00f6glichkeiten der Verwaltung von HAProxy und die Implementierung von Graceful Shutdown in unseren Diensten genutzt haben.<\/p>\n<p>Um diese Aufgabe zu l\u00f6sen, musste die Verwaltung des Load Balancers und das \u201ekorrekte\u201c Ausschalten der Dienste sichergestellt werden:<\/p>\n<ul>\n<li>Im Falle von HAProxy erfolgt die Verwaltung \u00fcber eine Stats-Datei, die im Wesentlichen ein Socket darstellt und in der HAProxy-Konfiguration definiert ist. Kommandos k\u00f6nnen \u00fcber stdio an ihn \u00fcbergeben werden. Unser prim\u00e4res Werkzeug 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: Bei der Abschaltung warten sie auf den vollst\u00e4ndigen Abschluss der aktuellen Aufgabe, sei es ein HTTP-Request oder eine andere Dienstaufgabe. Das Gleiche gilt f\u00fcr den Worker. Er kennt alle Aufgaben, die er ausf\u00fchrt, und wird beendet, wenn er alles erfolgreich abgeschlossen hat. <\/li>\n<\/ul>\n<p>\nDank dieser beiden Aspekte sieht unser sicherer Deployment-Algorithmus wie folgt aus.<\/p>\n<ol>\n<li>Der Entwickler stellt ein neues Code-Paket (bei uns ist das RPM) zusammen, testet es in der Entwicklungsumgebung, testet es im Staging und l\u00e4sst es im Staging-Repository.<\/li>\n<li>Der Entwickler gibt die Aufgabe f\u00fcr das Deployment mit einer m\u00f6glichst detaillierten Beschreibung der \u201eArtefakte\u201c an: Version des neuen Pakets, Beschreibung der neuen Funktionalit\u00e4t und andere Einzelheiten zum Deployment, falls erforderlich.<\/li>\n<li>Der Systemadministrator beginnt mit dem Update. Er startet das Ansible-Playbook, welches folgendes tut: \n<ul>\n<li>Es nimmt das Paket aus dem Stage-Repository und aktualisiert die Version des Pakets im Produkt-Repository.<\/li>\n<li>Es erstellt eine Liste der Backends des aktualisierten Dienstes.<\/li>\n<li>Es schaltet den ersten zu aktualisierenden Dienst in HAProxy aus und wartet, bis die Prozesse abgeschlossen sind. Dank des sanften Herunterfahrens sind wir sicher, dass alle aktuellen Kundenanfragen erfolgreich abgeschlossen werden.<\/li>\n<li>Nach der vollst\u00e4ndigen Stoppausf\u00fchrung des API, der Worker und der Abschaltung von HAProxy erfolgt die Aktualisierung des Codes.<\/li>\n<li>Ansible startet die Dienste.<\/li>\n<li>F\u00fcr jeden Dienst zieht es bestimmte \u201eRegler\u201c, die Unit-Tests anhand einer Reihe von zuvor definierten Schl\u00fcsseltests durchf\u00fchren. Es erfolgt eine grundlegende \u00dcberpr\u00fcfung des neuen Codes.<\/li>\n<li>Wenn bei dem vorherigen Schritt keine Fehler entdeckt wurden, wird das Backend aktiviert.<\/li>\n<li>Wir gehen zum n\u00e4chsten Backend \u00fcber.<\/li>\n<\/ul>\n<\/li>\n<li>Nach der Aktualisierung aller Backends werden funktionale Tests durchgef\u00fchrt. Wenn diese nicht ausreichen, schaut der Entwickler sich jede neue Funktionalit\u00e4t an, die er erstellt hat.<\/li>\n<\/ol>\n<p>\nDamit ist das Deployment abgeschlossen.<\/p>\n<p><img decoding=\"async\" alt=\"Wie wird eine ausfallsichere Web-Architektur in der Plattform Mail.ru Cloud Solutions implementiert\" src=\"\/wp-content\/uploads\/2019\/11\/2d889fe1af33653e4bfebabe1cce6552.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<i>Der Update-Zyklus des Dienstes<\/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 im Live-Betrieb. Bereits in der Entwicklungsphase der Software wird festgelegt, dass selbst wenn \u00c4nderungen an der Datenbank des Dienstes vorgenommen werden, sie den alten Code nicht brechen werden. Dadurch erfolgt ein schrittweises Update der Codebasis.<\/p>\n<h2>Fazit<\/h2>\n<p>\nWenn ich meine Gedanken zur ausfallsicheren WEB-Architektur teile, m\u00f6chte ich nochmals ihre Schl\u00fcsselpunkte hervorheben:<\/p>\n<ul>\n<li>physische Ausfallsicherheit;<\/li>\n<li>netzwerkbasierte Ausfallsicherheit (Lastverteiler, BGP);<\/li>\n<li>Ausfallsicherheit der verwendeten und entwickelten Software.<\/li>\n<\/ul>\n<p>\nAllen eine stabile Betriebszeit!<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.1.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.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\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 Web-Architektur in 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}]}}