Wie eine fehlertolerante Webarchitektur in der Mail.ru Cloud Solutions-Plattform implementiert wird

Wie eine fehlertolerante Webarchitektur in der Mail.ru Cloud Solutions-Plattform implementiert wird

Hallo, Habr! Ich bin Artem Karamyshev, Leiter des Systemadministrationsteams Mail.Ru Cloud-Lösungen (MCS). Wir haben im vergangenen Jahr viele neue Produkteinführungen durchgeführt. Wir wollten sicherstellen, dass API-Dienste leicht skalierbar, fehlertolerant und für ein schnelles Wachstum der Benutzerlast bereit sind. Unsere Plattform ist auf OpenStack implementiert, und ich möchte Ihnen sagen, welche Komponentenfehlertoleranzprobleme wir lösen mussten, um ein fehlertolerantes System zu erhalten. Ich denke, das wird für diejenigen interessant sein, die auch Produkte auf OpenStack entwickeln.

Die Gesamtfehlertoleranz einer Plattform besteht aus der Belastbarkeit ihrer Komponenten. Wir werden also nach und nach alle Ebenen durchgehen, auf denen wir Risiken identifiziert und geschlossen haben.

Videoversion dieser Geschichte, deren Hauptquelle ein Bericht auf der Uptime Day 4-Konferenz war, organisiert von ESumma, du kannst sehen auf dem YouTube-Kanal der Uptime Community.

Ausfallsicherheit der physischen Architektur

Der öffentliche Teil der MCS-Cloud ist nun in zwei Tier-III-Rechenzentren angesiedelt, dazwischen gibt es eine eigene Dark Fiber, die auf physischer Ebene über verschiedene Routen reserviert ist, mit einem Durchsatz von 200 Gbit/s. Tier III bietet das erforderliche Maß an Fehlertoleranz für die physische Infrastruktur.

Dark Fiber ist sowohl auf der physischen als auch auf der logischen Ebene reserviert. Der Kanalreservierungsprozess war iterativ, es traten Probleme auf und wir verbessern ständig die Kommunikation zwischen Rechenzentren.

Beispielsweise brach vor nicht allzu langer Zeit bei Arbeiten in einem Brunnen in der Nähe eines der Rechenzentren ein Bagger ein Rohr, und in diesem Rohr befanden sich sowohl ein Haupt- als auch ein Backup-Glasfaserkabel. Unser fehlertoleranter Kommunikationskanal mit dem Rechenzentrum erwies sich an einer Stelle im Bohrloch als anfällig. Dementsprechend haben wir einen Teil der Infrastruktur verloren. Wir haben Schlussfolgerungen gezogen und eine Reihe von Maßnahmen ergriffen, darunter die Installation zusätzlicher Optiken im angrenzenden Bohrloch.

In Rechenzentren gibt es Präsenzpunkte von Kommunikationsanbietern, an die wir unsere Präfixe über BGP senden. Für jede Netzwerkrichtung wird die beste Metrik ausgewählt, wodurch verschiedene Clients mit der besten Verbindungsqualität versorgt werden können. Wenn die Kommunikation über einen Anbieter ausfällt, bauen wir unser Routing über die verfügbaren Anbieter neu auf.

Fällt ein Anbieter aus, wechseln wir automatisch zum nächsten. Im Falle eines Ausfalls eines der Rechenzentren verfügen wir über eine Spiegelkopie unserer Dienste im zweiten Rechenzentrum, die die gesamte Last übernimmt.

Wie eine fehlertolerante Webarchitektur in der Mail.ru Cloud Solutions-Plattform implementiert wird
Ausfallsicherheit der physischen Infrastruktur

Was wir für Fehlertoleranz auf Anwendungsebene verwenden

Unser Service basiert auf einer Reihe von Open-Source-Komponenten.

ExaBGP ist ein Dienst, der eine Reihe von Funktionen mithilfe des BGP-basierten dynamischen Routing-Protokolls implementiert. Wir nutzen es aktiv, um unsere Whitelist-IP-Adressen bekannt zu machen, über die Benutzer auf die API zugreifen.

HAProxy ist ein High-Load-Balancer, mit dem Sie sehr flexible Verkehrsausgleichsregeln auf verschiedenen Ebenen des OSI-Modells konfigurieren können. Wir nutzen es, um alle Dienste auszugleichen: Datenbanken, Nachrichtenbroker, API-Dienste, Webdienste, unsere internen Projekte – alles steht hinter HAProxy.

API-Anwendung — eine in Python geschriebene Webanwendung, mit der der Benutzer seine Infrastruktur und seinen Dienst verwaltet.

Arbeitnehmeranwendung (im Folgenden einfach Worker) – in OpenStack-Diensten ist dies ein Infrastruktur-Daemon, der es Ihnen ermöglicht, API-Befehle an die Infrastruktur zu senden. Die Festplattenerstellung erfolgt beispielsweise im Worker und die Erstellungsanforderung erfolgt in der Anwendungs-API.

Standard-OpenStack-Anwendungsarchitektur

Die meisten für OpenStack entwickelten Dienste versuchen, einem einzigen Paradigma zu folgen. Ein Dienst besteht normalerweise aus zwei Teilen: API und Workern (Backend-Ausführer). In der Regel handelt es sich bei einer API um eine WSGI-Anwendung in Python, die entweder als eigenständiger Prozess (Daemon) oder über einen vorgefertigten Nginx- oder Apache-Webserver gestartet wird. Die API verarbeitet die Benutzeranfrage und übergibt weitere Anweisungen zur Ausführung an die Worker-Anwendung. Die Übertragung erfolgt über einen Nachrichtenbroker, normalerweise RabbitMQ, die anderen werden schlecht unterstützt. Wenn Nachrichten den Broker erreichen, werden sie von Workern verarbeitet und geben bei Bedarf eine Antwort zurück.

Dieses Paradigma beinhaltet isolierte gemeinsame Fehlerquellen: RabbitMQ und die Datenbank. Aber RabbitMQ ist innerhalb eines Dienstes isoliert und kann theoretisch für jeden Dienst individuell sein. Deshalb trennen wir bei MCS diese Dienste so weit wie möglich; für jedes einzelne Projekt erstellen wir eine separate Datenbank, ein separates RabbitMQ. Dieser Ansatz ist gut, da bei einem Unfall an einigen gefährdeten Stellen nicht die gesamte Versorgung, sondern nur ein Teil davon ausfällt.

Die Anzahl der Worker-Anwendungen ist unbegrenzt, sodass die API problemlos horizontal hinter Balancern skaliert werden kann, um die Leistung und Fehlertoleranz zu erhöhen.

Einige Dienste erfordern eine Koordination innerhalb des Dienstes, wenn komplexe sequentielle Vorgänge zwischen APIs und Workern stattfinden. In diesem Fall wird ein einzelnes Koordinationszentrum verwendet, ein Clustersystem wie Redis, Memcache usw., das es einem Arbeiter ermöglicht, einem anderen mitzuteilen, dass ihm diese Aufgabe zugewiesen ist („Bitte nimm sie nicht an“). Wir verwenden etcd. In der Regel kommunizieren Mitarbeiter aktiv mit der Datenbank, schreiben und lesen Informationen von dort. Als Datenbank nutzen wir mariadb, die in einem Multimaster-Cluster liegt.

Dieser klassische Einzeldienst ist in einer für OpenStack allgemein üblichen Weise organisiert. Es kann als geschlossenes System betrachtet werden, für das die Methoden der Skalierung und Fehlertoleranz ziemlich offensichtlich sind. Für die API-Fehlertoleranz reicht es beispielsweise aus, einen Balancer davor zu platzieren. Die Skalierung der Arbeitskräfte wird durch die Erhöhung ihrer Zahl erreicht.

Der Schwachpunkt im gesamten Schema sind RabbitMQ und MariaDB. Ihre Architektur verdient einen eigenen Artikel. In diesem Artikel möchte ich mich auf die API-Fehlertoleranz konzentrieren.

Wie eine fehlertolerante Webarchitektur in der Mail.ru Cloud Solutions-Plattform implementiert wird
Openstack-Anwendungsarchitektur. Balancing und Fehlertoleranz der Cloud-Plattform

Den HAProxy-Balancer mithilfe von ExaBGP fehlertolerant machen

Um unsere APIs skalierbar, schnell und fehlertolerant zu machen, haben wir ihnen einen Load Balancer vorangestellt. Wir haben uns für HAProxy entschieden. Meiner Meinung nach verfügt es über alle notwendigen Eigenschaften für unsere Aufgabe: Balancing auf mehreren OSI-Ebenen, eine Verwaltungsschnittstelle, Flexibilität und Skalierbarkeit, eine große Anzahl von Balancing-Methoden, Unterstützung für Sitzungstabellen.

Das erste Problem, das gelöst werden musste, war die Fehlertoleranz des Balancers selbst. Auch die einfache Installation eines Balancers führt zu einer Fehlerquelle: Der Balancer geht kaputt und der Dienst stürzt ab. Um dies zu verhindern, haben wir HAProxy in Verbindung mit ExaBGP verwendet.

Mit ExaBGP können Sie einen Mechanismus zur Überprüfung des Status eines Dienstes implementieren. Wir haben diesen Mechanismus verwendet, um die Funktionalität von HAProxy zu überprüfen und bei Problemen den HAProxy-Dienst von BGP zu deaktivieren.

ExaBGP+HAProxy-Schema

  1. Wir installieren die notwendige Software ExaBGP und HAProxy auf drei Servern.
  2. Wir erstellen auf jedem Server eine Loopback-Schnittstelle.
  3. Auf allen drei Servern weisen wir dieser Schnittstelle die gleiche weiße IP-Adresse zu.
  4. Über ExaBGP wird dem Internet eine weiße IP-Adresse bekannt gegeben.

Fehlertoleranz wird dadurch erreicht, dass von allen drei Servern dieselbe IP-Adresse bekannt gegeben wird. Aus Netzwerksicht ist dieselbe Adresse von drei verschiedenen nächsten Hops aus zugänglich. Der Router sieht drei identische Routen, wählt anhand seiner eigenen Metrik die höchste Priorität aus (normalerweise ist dies dieselbe Option) und der Datenverkehr geht nur an einen der Server.

Bei Problemen mit dem Betrieb von HAProxy oder einem Serverausfall stoppt ExaBGP die Ankündigung der Route und der Datenverkehr wechselt reibungslos auf einen anderen Server.

Dadurch haben wir eine Fehlertoleranz des Balancers erreicht.

Wie eine fehlertolerante Webarchitektur in der Mail.ru Cloud Solutions-Plattform implementiert wird
Fehlertoleranz von HAProxy-Balancern

Das Schema erwies sich als unvollkommen: Wir lernten, wie man HAProxy reserviert, aber nicht, wie man die Last innerhalb der Dienste verteilt. Deshalb haben wir dieses Schema ein wenig erweitert: Wir sind zum Ausgleich zwischen mehreren weißen IP-Adressen übergegangen.

Ausgleich basierend auf DNS plus BGP

Das Problem des Lastausgleichs für unseren HAProxy bleibt ungelöst. Es lässt sich jedoch ganz einfach lösen, wie wir es hier getan haben.

Um drei Server auszugleichen, benötigen Sie drei weiße IP-Adressen und das gute alte DNS. Jede dieser Adressen wird auf der Loopback-Schnittstelle jedes HAProxys ermittelt und dem Internet bekannt gegeben.

In OpenStack wird zum Verwalten von Ressourcen ein Dienstverzeichnis verwendet, das die Endpunkt-API eines bestimmten Dienstes angibt. In diesem Verzeichnis registrieren wir einen Domainnamen – public.infra.mail.ru, der über DNS durch drei verschiedene IP-Adressen aufgelöst wird. Dadurch erhalten wir eine Lastverteilung zwischen drei Adressen über DNS.

Da wir jedoch bei der Bekanntgabe weißer IP-Adressen keine Kontrolle über die Serverauswahlprioritäten haben, ist dies noch kein Ausgleich. Normalerweise wird nur ein Server basierend auf der Seniorität der IP-Adresse ausgewählt, und die anderen beiden bleiben inaktiv, da im BGP keine Metriken angegeben sind.

Wir haben begonnen, Routen über ExaBGP mit unterschiedlichen Metriken zu senden. Jeder Balancer bewirbt alle drei weißen IP-Adressen, aber eine davon, die Hauptadresse für diesen Balancer, wird mit der Mindestmetrik beworben. Während also alle drei Balancer in Betrieb sind, gehen Anrufe an die erste IP-Adresse an den ersten Balancer, Anrufe an den zweiten an den zweiten und Anrufe an die dritte an den dritten.

Was passiert, wenn einer der Balancer herunterfällt? Wenn ein Balancer ausfällt, wird seine Hauptadresse weiterhin von den anderen beiden bekannt gegeben und der Datenverkehr wird zwischen ihnen neu verteilt. Daher geben wir dem Benutzer über DNS mehrere IP-Adressen auf einmal. Durch den Ausgleich per DNS und verschiedenen Metriken erhalten wir eine gleichmäßige Lastverteilung auf alle drei Balancer. Und gleichzeitig verlieren wir nicht die Fehlertoleranz.

Wie eine fehlertolerante Webarchitektur in der Mail.ru Cloud Solutions-Plattform implementiert wird
Ausgleich von HAProxy basierend auf DNS + BGP

Interaktion zwischen ExaBGP und HAProxy

Deshalb haben wir eine Fehlertoleranz für den Fall implementiert, dass der Server ausfällt, basierend auf dem Stoppen der Routenankündigung. HAProxy kann jedoch aus anderen Gründen als einem Serverausfall heruntergefahren werden: Verwaltungsfehler, Ausfälle innerhalb des Dienstes. Auch in diesen Fällen wollen wir den kaputten Balancer unter der Last entfernen und benötigen dazu einen anderen Mechanismus.

Daher haben wir als Erweiterung des vorherigen Schemas einen Heartbeat zwischen ExaBGP und HAProxy implementiert. Hierbei handelt es sich um eine Softwareimplementierung der Interaktion zwischen ExaBGP und HAProxy, bei der ExaBGP benutzerdefinierte Skripte verwendet, um den Status von Anwendungen zu überprüfen.

Dazu müssen Sie in der ExaBGP-Konfiguration einen Health Checker konfigurieren, der den Status von HAProxy überprüfen kann. In unserem Fall haben wir das Gesundheits-Backend in HAProxy konfiguriert und von der ExaBGP-Seite aus überprüfen wir es mit einer einfachen GET-Anfrage. Wenn die Ankündigung nicht mehr erfolgt, funktioniert HAProxy höchstwahrscheinlich nicht und es besteht keine Notwendigkeit, dies anzukündigen.

Wie eine fehlertolerante Webarchitektur in der Mail.ru Cloud Solutions-Plattform implementiert wird
HAProxy-Gesundheitscheck

HAProxy-Peers: Sitzungssynchronisierung

Als nächstes mussten die Sitzungen synchronisiert werden. Bei der Arbeit mit verteilten Balancern ist es schwierig, die Speicherung von Informationen über Client-Sitzungen zu organisieren. Aufgrund der Peers-Funktionalität – der Möglichkeit, Sitzungstabellen zwischen verschiedenen HAProxy-Prozessen zu übertragen – ist HAProxy jedoch einer der wenigen Balancer, der dies kann.

Es gibt verschiedene Auswuchtmethoden: einfache wie z Round-Robin, und verlängert, wenn die Sitzung des Clients gespeichert wird und er jedes Mal auf demselben Server wie zuvor landet. Wir wollten die zweite Option umsetzen.

HAProxy verwendet Stick-Tabellen, um Client-Sitzungen dieses Mechanismus zu speichern. Sie speichern die ursprüngliche IP-Adresse des Clients, die ausgewählte Zieladresse (Backend) und einige Serviceinformationen. In der Regel werden Stick-Tabellen zum Speichern eines Quell-IP- und Ziel-IP-Paars verwendet. Dies ist besonders nützlich für Anwendungen, die den Benutzersitzungskontext nicht übertragen können, wenn zu einem anderen Balancer gewechselt wird, beispielsweise im RoundRobin-Balancing-Modus.

Wenn einem Stick-Table beigebracht wird, sich zwischen verschiedenen HAProxy-Prozessen zu bewegen (zwischen denen ein Ausgleich stattfindet), können unsere Balancer mit einem Pool von Stick-Tables arbeiten. Dies ermöglicht einen nahtlosen Wechsel des Client-Netzwerks, wenn einer der Balancer ausfällt; die Arbeit mit Client-Sitzungen wird auf denselben Backends fortgesetzt, die zuvor ausgewählt wurden.

Für einen ordnungsgemäßen Betrieb muss das Problem der Quell-IP-Adresse des Balancers, von dem aus die Sitzung aufgebaut wurde, gelöst werden. In unserem Fall ist dies eine dynamische Adresse auf der Loopback-Schnittstelle.

Eine korrekte Arbeit von Kollegen wird nur unter bestimmten Bedingungen erreicht. Das heißt, die TCP-Zeitüberschreitungen müssen groß genug sein oder die Umschaltung muss schnell genug erfolgen, damit die TCP-Sitzung keine Zeit zum Beenden hat. Es ermöglicht jedoch einen nahtlosen Wechsel.

Bei IaaS verfügen wir über einen Dienst, der auf der gleichen Technologie basiert. Das Load Balancer als Dienst für OpenStack, die Octavia heißt. Es basiert auf zwei HAProxy-Prozessen und beinhaltet zunächst die Unterstützung von Peers. Sie haben sich in diesem Dienst hervorragend bewährt.

Das Bild zeigt schematisch die Bewegung von Peer-Tabellen zwischen drei HAProxy-Instanzen. Es wird eine Konfiguration vorgeschlagen, wie dies konfiguriert werden kann:

Wie eine fehlertolerante Webarchitektur in der Mail.ru Cloud Solutions-Plattform implementiert wird
HAProxy Peers (Sitzungssynchronisierung)

Wenn Sie dasselbe Schema implementieren, muss seine Funktionsweise sorgfältig getestet werden. Es ist keine Tatsache, dass es immer zu 100 % auf die gleiche Weise funktioniert. Aber Sie verlieren zumindest keine Stick-Tabellen, wenn Sie sich die Quell-IP des Clients merken müssen.

Begrenzung der Anzahl gleichzeitiger Anfragen desselben Clients

Alle öffentlich verfügbaren Dienste, einschließlich unserer APIs, können einer Flut von Anfragen ausgesetzt sein. Die Gründe dafür können völlig unterschiedlich sein, von Benutzerfehlern bis hin zu gezielten Angriffen. Wir werden regelmäßig DDoS-Angriffen auf IP-Adressen unterzogen. Kunden machen oft Fehler in ihren Skripten und geben uns Mini-DDoSs.

Auf die eine oder andere Weise muss für zusätzlichen Schutz gesorgt werden. Die offensichtliche Lösung besteht darin, die Anzahl der API-Anfragen zu begrenzen und keine CPU-Zeit mit der Verarbeitung böswilliger Anfragen zu verschwenden.

Um solche Einschränkungen umzusetzen, verwenden wir Ratenlimits, die auf der Basis von HAProxy unter Verwendung derselben Stick-Tabellen organisiert sind. Das Einrichten von Limits ist recht einfach und ermöglicht es Ihnen, den Benutzer durch die Anzahl der Anfragen an die API zu begrenzen. Der Algorithmus merkt sich die Quell-IP, von der aus Anfragen gestellt werden, und begrenzt die Anzahl gleichzeitiger Anfragen von einem Benutzer. Natürlich haben wir für jeden Dienst das durchschnittliche API-Lastprofil berechnet und einen Grenzwert von ≈ dem 10-fachen dieses Wertes festgelegt. Wir beobachten die Situation weiterhin genau und bleiben am Puls der Zeit.

Wie sieht das in der Praxis aus? Wir haben Kunden, die unsere Autoscaling-APIs ständig nutzen. Sie erstellen morgens etwa zwei- bis dreihundert virtuelle Maschinen und löschen sie abends. Für OpenStack sind für die Erstellung einer virtuellen Maschine, auch mit PaaS-Diensten, mindestens 1000 API-Anfragen erforderlich, da auch die Interaktion zwischen Diensten über die API erfolgt.

Eine solche Aufgabenübertragung verursacht eine ziemlich große Belastung. Wir bewerteten diese Belastung, sammelten tägliche Spitzenwerte, erhöhten sie um das Zehnfache und das wurde zu unserem Ratenlimit. Wir bleiben am Puls der Zeit. Wir sehen oft Bots und Scanner, die versuchen, uns zu untersuchen, um zu sehen, ob wir CGA-Skripte haben, die ausgeführt werden können. Wir schneiden sie aktiv ab.

So aktualisieren Sie Ihre Codebasis, ohne dass Benutzer es bemerken

Wir implementieren Fehlertoleranz auch auf der Ebene von Code-Bereitstellungsprozessen. Während des Rollouts kann es zu Störungen kommen, deren Auswirkungen auf die Serviceverfügbarkeit jedoch minimiert werden können.

Wir aktualisieren unsere Dienste ständig und müssen sicherstellen, dass die Codebasis aktualisiert wird, ohne dass dies Auswirkungen auf die Benutzer hat. Mithilfe der Verwaltungsfunktionen von HAProxy und der Implementierung von Graceful Shutdown in unseren Diensten ist es uns gelungen, dieses Problem zu lösen.

Um dieses Problem zu lösen, war es notwendig, die Kontrolle über den Balancer und das „richtige“ Herunterfahren der Dienste sicherzustellen:

  • Im Fall von HAProxy erfolgt die Steuerung über eine Statistikdatei, die im Wesentlichen ein Socket ist und in der HAProxy-Konfiguration definiert ist. Sie können über stdio Befehle an ihn senden. Da unser Haupttool zur Konfigurationssteuerung jedoch ansible ist, verfügt es über ein integriertes Modul zur Verwaltung von HAProxy. Was wir aktiv nutzen.
  • Die meisten unserer API- und Engine-Dienste unterstützen Technologien zum ordnungsgemäßen Herunterfahren: Beim Herunterfahren warten sie auf den Abschluss der aktuellen Aufgabe, sei es eine http-Anfrage oder eine Dienstaufgabe. Das Gleiche passiert mit dem Arbeiter. Es kennt alle Aufgaben, die es erledigt, und endet, wenn es alles erfolgreich erledigt hat.

Dank dieser beiden Punkte sieht der sichere Algorithmus für unsere Bereitstellung so aus.

  1. Der Entwickler stellt ein neues Codepaket zusammen (für uns ist das RPM), testet es in der Entwicklungsumgebung, testet es im Stage und belässt es im Stage-Repository.
  2. Der Entwickler legt die Aufgabe für die Bereitstellung mit der detailliertesten Beschreibung der „Artefakte“ fest: der Version des neuen Pakets, einer Beschreibung der neuen Funktionalität und bei Bedarf weitere Details zur Bereitstellung.
  3. Der Systemadministrator beginnt mit der Aktualisierung. Startet das Ansible-Playbook, das wiederum Folgendes bewirkt:
    • Entnimmt ein Paket aus dem Staging-Repository und verwendet es, um die Version des Pakets im Produkt-Repository zu aktualisieren.
    • Stellt eine Liste der Backends des aktualisierten Dienstes zusammen.
    • Fährt den ersten Dienst herunter, der in HAProxy aktualisiert wird, und wartet, bis die Ausführung seiner Prozesse abgeschlossen ist. Dank des ordnungsgemäßen Herunterfahrens sind wir zuversichtlich, dass alle aktuellen Kundenanfragen erfolgreich abgeschlossen werden.
    • Nachdem die API und die Worker vollständig gestoppt und HAProxy ausgeschaltet wurden, wird der Code aktualisiert.
    • Ansible führt Dienste aus.
    • Für jeden Dienst werden bestimmte „Handles“ gezogen, die Unit-Tests für eine Reihe vordefinierter Schlüsseltests durchführen. Es erfolgt eine Grundprüfung des neuen Codes.
    • Wurden im vorherigen Schritt keine Fehler gefunden, wird das Backend aktiviert.
    • Fahren wir mit dem nächsten Backend fort.
  4. Nachdem alle Backends aktualisiert wurden, werden Funktionstests gestartet. Fehlen sie, prüft der Entwickler alle von ihm erstellten neuen Funktionen.

Damit ist die Bereitstellung abgeschlossen.

Wie eine fehlertolerante Webarchitektur in der Mail.ru Cloud Solutions-Plattform implementiert wird
Service-Update-Zyklus

Dieses Schema würde nicht funktionieren, wenn wir keine Regel hätten. Wir unterstützen sowohl die alte als auch die neue Version im Kampf. Im Vorfeld der Softwareentwicklung wird festgelegt, dass selbst bei Änderungen in der Servicedatenbank der bisherige Code nicht beschädigt wird. Dadurch wird die Codebasis nach und nach aktualisiert.

Fazit

Ich teile meine eigenen Gedanken über eine fehlertolerante WEB-Architektur und möchte noch einmal auf die wichtigsten Punkte hinweisen:

  • physische Fehlertoleranz;
  • Netzwerkfehlertoleranz (Balancer, BGP);
  • Fehlertoleranz der verwendeten und entwickelten Software.

Stabile Betriebszeit an alle!

Source: habr.com

Kommentar hinzufügen