Wie wir den 10-fachen Anstieg der Arbeitsbelastung aus der Ferne überstanden haben und welche Schlussfolgerungen wir daraus gezogen haben

Hallo, Habr! Wir leben seit einigen Monaten in einer sehr interessanten Situation und ich möchte unsere Geschichte der Infrastrukturskalierung erzählen. In dieser Zeit ist die Zahl der Bestellungen bei SberMarket um das Vierfache gestiegen und der Dienst wurde in 4 neuen Städten eingeführt. Das explosionsartige Wachstum der Nachfrage nach Lebensmittellieferungen erforderte eine Skalierung unserer Infrastruktur. Lesen Sie die interessantesten und nützlichsten Schlussfolgerungen unter dem Schnitt.

Wie wir den 10-fachen Anstieg der Arbeitsbelastung aus der Ferne überstanden haben und welche Schlussfolgerungen wir daraus gezogen haben

Mein Name ist Dima Bobylev, ich bin der technische Direktor von SberMarket. Da dies der erste Beitrag in unserem Blog ist, möchte ich ein paar Worte über mich und das Unternehmen sagen. Letzten Herbst habe ich an einem Wettbewerb für junge Runet-Leiter teilgenommen. Für den Wettbewerb I hat eine Kurzgeschichte geschrieben darüber, wie wir bei SberMarket die interne Kultur und den Ansatz zur Serviceentwicklung sehen. Und obwohl es mir nicht gelungen ist, den Wettbewerb zu gewinnen, habe ich für mich die Grundprinzipien für die Entwicklung des IT-Ökosystems formuliert.

Bei der Leitung eines Teams ist es wichtig, die Bedürfnisse des Unternehmens und die Bedürfnisse jedes einzelnen Entwicklers zu verstehen und ein Gleichgewicht zwischen ihnen zu finden. Jetzt wächst SberMarket Jahr für Jahr um das 13-fache, was sich auf das Produkt auswirkt und eine ständige Steigerung des Volumens und der Entwicklungsgeschwindigkeit erfordert. Dennoch geben wir den Entwicklern genügend Zeit für die Voranalyse und Qualitätscodierung. Der geformte Ansatz hilft nicht nur bei der Erstellung eines funktionierenden Produkts, sondern auch bei dessen weiterer Skalierung und Entwicklung. Durch dieses Wachstum hat sich SberMarket bereits zu einem Spitzenreiter unter den Lebensmittellieferdiensten entwickelt: Wir liefern jeden Tag etwa 18 Bestellungen aus, Anfang Februar waren es jedoch etwa 3500.

Wie wir den 10-fachen Anstieg der Arbeitsbelastung aus der Ferne überstanden haben und welche Schlussfolgerungen wir daraus gezogen haben
Eines Tages bat ein Kunde einen SberMarket-Kurier, ihm Lebensmittel kontaktlos zu liefern – direkt auf den Balkon

Aber kommen wir zu den Einzelheiten. In den letzten Monaten haben wir die Infrastruktur unseres Unternehmens aktiv skaliert. Dieser Bedarf wurde durch externe und interne Faktoren erklärt. Mit der Ausweitung des Kundenstamms wuchs auch die Zahl der angeschlossenen Filialen von 90 zu Jahresbeginn auf über 200 bis Mitte Mai. Wir waren natürlich vorbereitet, reservierten die Hauptinfrastruktur und rechneten mit der Möglichkeit der vertikalen und horizontalen Skalierung aller in der Yandex-Cloud gehosteten virtuellen Maschinen. Doch die Praxis zeigt: „Alles, was schief gehen kann, wird schief gehen.“ Und heute möchte ich die interessantesten Situationen teilen, die sich in diesen Wochen ereignet haben. Ich hoffe, dass unsere Erfahrung für Sie von Nutzen sein wird.

Der Sklave ist in voller Kampfbereitschaft

Schon vor Beginn der Pandemie waren wir mit einem Anstieg der Anfragen an unsere Backend-Server konfrontiert. Der Trend, Lebensmittel für die Lieferung nach Hause zu bestellen, nahm Fahrt auf, und mit der Einführung der ersten Selbstisolationsmaßnahmen aufgrund von COVID-19 nahm die Arbeitsbelastung im Laufe des Tages dramatisch zu. Es bestand die Notwendigkeit, die Master-Server der Hauptdatenbank schnell zu entlasten und einen Teil der Leseanforderungen an Replika-Server (Slave-Server) zu übertragen.

Wir haben uns im Vorfeld auf diesen Schritt vorbereitet und bereits zwei Slave-Server für ein solches Manöver gestartet. Sie wurden hauptsächlich für Batch-Aufgaben zur Generierung von Informations-Feeds zum Datenaustausch mit Partnern verwendet. Diese Prozesse stellten eine zusätzliche Belastung dar und wurden zu Recht ein paar Monate zuvor aus der Gleichung gestrichen. 

Da die Replikation auf dem Slave erfolgte, hielten wir an dem Konzept fest, dass Anwendungen nur im schreibgeschützten Modus mit ihnen arbeiten konnten. Der Disaster Recovery Plan ging davon aus, dass wir im Katastrophenfall einfach den Slave anstelle des Masters einbauen und alle Schreib- und Leseanforderungen an den Slave weiterleiten könnten. Wir wollten jedoch auch Replikate für die Bedürfnisse der Analyseabteilung verwenden, sodass die Server nicht vollständig auf den Nur-Lese-Status umgestellt wurden, sondern jeder Host über einen eigenen Benutzersatz verfügte und einige über Schreibrechte zum Speichern von Zwischenberechnungsergebnissen verfügten.

Bis zu einem bestimmten Lastlevel hatten wir bei der Verarbeitung von http-Anfragen genügend Master sowohl zum Schreiben als auch zum Lesen. Mitte März, gerade als Sbermarket beschloss, vollständig auf Remote-Arbeit umzustellen, begann unser RPS exponentiell zu wachsen. Immer mehr unserer Kunden begaben sich in Selbstisolation oder arbeiteten von zu Hause aus, was sich auf unsere Arbeitsbelastungsindikatoren auswirkte.

Da die Leistung des „Masters“ nicht mehr ausreichte, begannen wir, einige der umfangreichsten Leseanfragen an das Replikat zu übertragen. Um Schreibanfragen transparent an den Master und Leseanfragen an den Slave weiterzuleiten, haben wir Ruby Gem verwendet.Krake" Wir haben einen speziellen Benutzer mit dem Postfix _readonly ohne Schreibrechte erstellt. Aufgrund eines Fehlers in der Konfiguration eines der Hosts gingen jedoch einige der Schreibanfragen im Namen eines Benutzers mit den entsprechenden Rechten an den Slave-Server.

Das Problem trat nicht sofort auf, weil... Die erhöhte Last erhöhte die Verzögerung der Slaves. Die Inkonsistenz der Daten wurde am Morgen entdeckt, als die Slaves nach nächtlichen Importen den Master nicht „einholten“. Wir führten dies auf die hohe Belastung des Dienstes selbst und die Importe im Zusammenhang mit der Eröffnung neuer Filialen zurück. Das Senden von Daten mit einer Verzögerung von mehreren Stunden war jedoch nicht akzeptabel, und wir haben die Prozesse auf den zweiten analytischen Slave umgestellt, da dieser über eine Verzögerung verfügteоgrößere Ressourcen und wurde nicht mit Leseanfragen belastet (wodurch wir uns die fehlende Replikationsverzögerung erklärten).

Als wir die Gründe für die „Ausbreitung“ des Hauptsklaven herausfanden, war die Analyse bereits aus demselben Grund gescheitert. Trotz der Anwesenheit von zwei zusätzlichen Servern, auf die wir die Last im Falle eines Master-Ausfalls übertragen wollten, stellte sich aufgrund eines bedauerlichen Fehlers heraus, dass im kritischen Moment keine verfügbar waren.

Da wir aber nicht nur einen Dump der Datenbank erstellt haben (die Wiederherstellung dauerte damals etwa 5 Stunden), sondern auch einen Snapshot des Master-Servers, konnten wir die Replik innerhalb von 2 Stunden starten. Zwar waren wir danach lange Zeit mit einem Rollover des Replikationsprotokolls konfrontiert (da der Prozess im Single-Threaded-Modus läuft, aber das ist eine ganz andere Geschichte).

Fazit: Nach einem solchen Vorfall wurde klar, dass es notwendig war, die Schreibbeschränkung für Benutzer aufzugeben und den gesamten Server als schreibgeschützt zu deklarieren. Bei diesem Ansatz besteht kein Zweifel daran, dass Replikate zu kritischen Zeiten verfügbar sein werden.

Die Optimierung auch nur einer umfangreichen Abfrage kann die Datenbank wieder zum Leben erwecken

Obwohl wir den Katalog auf der Website ständig aktualisieren, kam es bei den Anfragen, die wir an die Slave-Server sendeten, zu einer leichten Verzögerung gegenüber dem Master. Die Zeit, in der wir das Problem entdeckten und beseitigten, dass Sklaven „plötzlich die Distanz verließen“, war mehr als die „psychologische Barriere“ (während dieser Zeit hätten die Preise aktualisiert werden können, und die Kunden hätten veraltete Daten gesehen), und wir waren dazu gezwungen Leiten Sie alle Anfragen an den Hauptdatenbankserver weiter. Infolgedessen war die Seite langsam ... aber zumindest funktionierte sie. Und während sich Slave erholte, blieb uns keine andere Wahl als die Optimierung. 

Während sich die Slave-Server erholten, vergingen die Minuten langsam, der Master blieb überlastet und wir haben alle unsere Anstrengungen in die Optimierung aktiver Aufgaben gemäß der „Pareto-Regel“ gesteckt: Wir haben die TOP-Anfragen ausgewählt, die den Großteil der Last erzeugen, und mit der Optimierung begonnen . Dies geschah direkt im Handumdrehen.

Ein interessanter Effekt war, dass MySQL, wenn es voll ausgelastet war, bereits auf eine leichte Verbesserung der Prozesse reagierte. Die Optimierung einiger Abfragen, die nur 5 % der Gesamtlast verursachten, zeigte bereits eine spürbare CPU-Last. Dadurch konnten wir dem Master eine akzeptable Ressourcenversorgung für die Arbeit mit der Datenbank bereitstellen und die nötige Zeit für die Wiederherstellung von Replikaten gewinnen. 

Fazit: Selbst eine kleine Optimierung ermöglicht es Ihnen, mehrere Stunden unter Überlastung zu „überleben“. Dies reichte gerade aus, um die Server mit Replikaten wiederherzustellen. Auf die technische Seite der Abfrageoptimierung gehen wir übrigens in einem der folgenden Beiträge ein. Abonnieren Sie daher bitte unseren Blog, wenn Sie ihn nützlich finden.

Organisieren Sie die Überwachung der Leistung von Partnerdiensten

Wir verarbeiten Bestellungen von Kunden und daher interagieren unsere Dienste ständig mit APIs von Drittanbietern – das sind Gateways für den SMS-Versand, Zahlungsplattformen, Routingsysteme, Geocoder, Federal Tax Service und viele andere Systeme. Und als die Auslastung schnell zu wachsen begann, stießen wir auf API-Einschränkungen unserer Partnerdienste, an die wir vorher noch nicht einmal gedacht hatten.

Eine unerwartete Überschreitung der Kontingente von Partnerdiensten kann zu Ausfallzeiten bei Ihnen führen. Viele APIs blockieren Clients, die Grenzwerte überschreiten, und in manchen Fällen können zu viele Anfragen die Produktion eines Partners überlasten. 

Wenn beispielsweise die Anzahl der Lieferungen zunahm, waren die begleitenden Dienste nicht in der Lage, die Aufgaben der Verteilung und Festlegung der Routen zu bewältigen. Es stellte sich heraus, dass zwar Bestellungen aufgegeben wurden, der Dienst, der die Route erstellt hatte, jedoch nicht funktionierte. Man muss sagen, dass unsere Logistiker unter diesen Bedingungen das fast Unmögliche geschafft haben und durch das klare Zusammenspiel des Teams konnten vorübergehende Serviceausfälle kompensiert werden. Es ist jedoch unrealistisch, eine solche Menge an Aufträgen ständig manuell zu bearbeiten, und nach einiger Zeit würden wir mit einer inakzeptablen Lücke zwischen Aufträgen und ihrer Ausführung konfrontiert werden. 

Es wurden eine Reihe organisatorischer Maßnahmen ergriffen und die gut koordinierte Arbeit des Teams trug dazu bei, Zeit zu gewinnen, während wir uns auf neue Bedingungen einigten und auf die Modernisierung der Dienstleistungen einiger Partner warteten. Es gibt andere APIs, die sich durch eine hohe Ausdauer und unglaubliche Geschwindigkeiten bei hohem Datenverkehr auszeichnen. Am Anfang haben wir beispielsweise eine bekannte Mapping-API verwendet, um die Adresse des Zustellpunkts zu ermitteln. Aber am Ende des Monats erhielten wir eine ordentliche Rechnung über fast 2 Millionen Rubel. Danach beschlossen sie, es schnell zu ersetzen. Ich werde keine Werbung machen, aber ich muss sagen, dass unsere Ausgaben deutlich gesunken sind.
Wie wir den 10-fachen Anstieg der Arbeitsbelastung aus der Ferne überstanden haben und welche Schlussfolgerungen wir daraus gezogen haben

Fazit: Es ist zwingend erforderlich, die Betriebsbedingungen aller Partnerdienste zu überwachen und im Auge zu behalten. Auch wenn es heute den Anschein hat, dass sie für Sie „mit großem Spielraum“ sind, heißt das nicht, dass sie morgen nicht zu einem Wachstumshindernis werden. Und natürlich ist es besser, die finanziellen Bedingungen für eine erhöhte Nachfrage nach der Dienstleistung im Voraus zu vereinbaren. 

Manchmal stellt sich heraus, dass „Benötigen Sie mehr Gold„(c) hilft nicht

Wir sind an „Gags“ in der Hauptdatenbank oder auf Anwendungsservern gewöhnt, aber bei der Skalierung können Probleme dort auftreten, wo sie nicht erwartet wurden. Für die Volltextsuche auf der Website verwenden wir die Apache Solr-Engine. Mit zunehmender Auslastung stellten wir eine Verkürzung der Antwortzeit fest und die Auslastung des Serverprozessors erreichte bereits 100 %. Was könnte einfacher sein: Geben wir dem Container mit Solr mehr Ressourcen.

Statt der erwarteten Leistungssteigerung ist der Server einfach „abgestorben“. Es wurde sofort mit 100 % geladen und reagierte noch langsamer. Anfangs hatten wir 2 Kerne und 2 GB RAM. Wir haben uns für das entschieden, was normalerweise hilft: Wir haben dem Server 8 Kerne und 32 GB gegeben. Alles wurde noch viel schlimmer (wie und warum genau, verraten wir Ihnen in einem separaten Beitrag). 

Innerhalb weniger Tage haben wir die Feinheiten dieses Problems herausgefunden und mit 8 Kernen und 32 GB eine optimale Leistung erzielt. Diese Konfiguration ermöglicht es uns, die Auslastung heute weiter zu erhöhen, was sehr wichtig ist, da das Wachstum nicht nur bei den Kunden, sondern auch bei der Anzahl der angeschlossenen Geschäfte zu verzeichnen ist – in zwei Monaten hat sich ihre Zahl verdoppelt. 

Fazit: Standardmethoden wie „mehr Eisen hinzufügen“ funktionieren nicht immer. Wenn Sie also einen Dienst skalieren, müssen Sie gut verstehen, wie er Ressourcen nutzt, und seinen Betrieb unter neuen Bedingungen im Voraus testen. 

Stateless ist der Schlüssel zur einfachen horizontalen Skalierung

Generell verfolgt unser Team einen bekannten Ansatz: Dienste sollten keinen internen Zustand haben (stateless) und unabhängig von der Ausführungsumgebung sein. Dadurch konnten wir das Lastwachstum durch einfache horizontale Skalierung bewältigen. Aber wir hatten einen Ausnahmedienst – einen Handler für lange Hintergrundaufgaben. Er war am Versenden von E-Mails und SMS, der Verarbeitung von Ereignissen, der Generierung von Feeds, dem Import von Preisen und Beständen sowie der Verarbeitung von Bildern beteiligt. Zufällig war es auf die lokale Dateispeicherung angewiesen und befand sich in einer einzigen Kopie. 

Als die Anzahl der Aufgaben in der Prozessorwarteschlange zunahm (und dies geschah natürlich mit einer Erhöhung der Anzahl der Bestellungen), wurde die Leistung des Hosts, auf dem sich der Prozessor und der Dateispeicher befanden, zum limitierenden Faktor. Infolgedessen wurden die Aktualisierung des Sortiments und der Preise, das Versenden von Benachrichtigungen an Benutzer und viele andere wichtige Funktionen, die in der Warteschlange steckten, gestoppt. Das Ops-Team migrierte den Dateispeicher schnell auf einen S3-ähnlichen Netzwerkspeicher, und dies ermöglichte es uns, mehrere leistungsstarke Maschinen zu betreiben, um den Hintergrundaufgabenprozessor zu skalieren.

Fazit: Die Stateless-Regel müsse ausnahmslos für alle Komponenten eingehalten werden, auch wenn es den Anschein habe, „wir werden hier definitiv nicht widerstehen können.“ Es ist besser, ein wenig Zeit damit zu verbringen, den Betrieb aller Systeme richtig zu organisieren, als den Code hastig neu zu schreiben und einen überlasteten Dienst zu reparieren.

7 Prinzipien für intensives Wachstum

Trotz der Verfügbarkeit zusätzlicher Kapazitäten haben wir im Wachstumsprozess mehrere Fehler begangen. In dieser Zeit hat sich die Zahl der Bestellungen um mehr als das Vierfache erhöht. Mittlerweile liefern wir bereits mehr als 4 Bestellungen pro Tag in 17 Städten aus und planen, die Geographie noch weiter auszudehnen – im ersten Halbjahr 000 wird der Service voraussichtlich in ganz Russland eingeführt. Um der wachsenden Arbeitsbelastung gerecht zu werden, haben wir unter Berücksichtigung unserer bereits vollen Kegel 62 Grundprinzipien für das Arbeiten unter Bedingungen ständigen Wachstums entwickelt:

  1. Vorfallmanagement. Wir haben in Jira ein Board erstellt, auf dem jeder Vorfall in Form eines Tickets angezeigt wird. Dies hilft bei der tatsächlichen Priorisierung und Ausführung vorfallbezogener Aufgaben. Schließlich ist es im Grunde nicht beängstigend, Fehler zu machen, aber es ist beängstigend, bei derselben Gelegenheit zweimal Fehler zu machen. Für den Fall, dass sich Vorfälle wiederholen, bevor die Ursache behoben werden kann, sollten Handlungsanweisungen bereitgehalten werden, denn in Zeiten hoher Belastung ist es wichtig, blitzschnell zu reagieren.
  2. Überwachung ausnahmslos für alle Infrastrukturelemente erforderlich. Dank ihm konnten wir das Wachstum der Belastung vorhersagen und die „Engpässe“ richtig auswählen, um deren Beseitigung Vorrang einzuräumen. Höchstwahrscheinlich geht unter hoher Last alles kaputt, woran Sie nie gedacht haben, oder wird langsamer. Daher ist es am besten, sofort nach Auftreten der ersten Vorfälle neue Warnungen zu erstellen, um diese zu überwachen und vorherzusehen.
  3. Korrekte Warnungen einfach notwendig, wenn die Belastung stark ansteigt. Zuerst müssen sie melden, was genau kaputt ist. Zweitens sollte es nicht viele Warnungen geben, da die Fülle an unkritischen Warnungen dazu führt, dass alle Warnungen insgesamt ignoriert werden.
  4. Bewerbungen müssen staatenlos sein. Wir sind davon überzeugt, dass es von dieser Regel keine Ausnahmen geben sollte. Wir brauchen völlige Unabhängigkeit von der Laufzeitumgebung. Dazu können Sie gemeinsame Daten in einer Datenbank oder beispielsweise direkt in S3 speichern. Besser noch: Befolgen Sie die Regeln. https://12factor.net. Bei einem starken Zeitanstieg gibt es einfach keine Möglichkeit, den Code zu optimieren, und Sie müssen die Belastung durch direkte Erhöhung der Rechenressourcen und horizontale Skalierung bewältigen.
  5. Quoten und Leistung externer Dienstleistungen. Bei schnellem Wachstum kann ein Problem nicht nur in Ihrer Infrastruktur, sondern auch bei einem externen Dienst auftreten. Am ärgerlichsten ist es, wenn dies nicht aufgrund eines Fehlers geschieht, sondern aufgrund des Erreichens von Quoten oder Limits. Daher sollten externe Dienste genauso gut skalierbar sein wie Sie. 
  6. Separate Prozesse und Warteschlangen. Dies hilft sehr, wenn an einem der Gateways eine Blockade vorliegt. Wir hätten keine Verzögerungen bei der Datenübertragung erlebt, wenn nicht volle SMS-Versandwarteschlangen den Austausch von Benachrichtigungen zwischen Informationssystemen beeinträchtigt hätten. Und es wäre einfacher, die Zahl der Arbeitnehmer zu erhöhen, wenn sie getrennt arbeiten würden.
  7. Finanzielle Realitäten. Wenn der Datenfluss explosionsartig wächst, bleibt keine Zeit, über Tarife und Abonnements nachzudenken. Aber Sie müssen sich daran erinnern, insbesondere wenn Sie ein kleines Unternehmen sind. Sowohl dem Eigentümer einer API als auch Ihrem Hosting-Anbieter kann eine hohe Rechnung entstehen. Daher müssen Sie die Verträge sorgfältig lesen.

Fazit

Nicht ohne Verluste, aber wir haben diese Phase überstanden und versuchen heute, alle gefundenen Prinzipien einzuhalten, und jede Maschine hat die Fähigkeit, die Leistung problemlos um das Vierfache zu steigern, um mit einigen unerwarteten Ereignissen fertig zu werden. 

In den folgenden Beiträgen werden wir unsere Erfahrungen bei der Untersuchung von Leistungseinbußen in Apache Solr teilen und auch über die Abfrageoptimierung sprechen und darüber, wie die Interaktion mit dem Federal Tax Service dem Unternehmen hilft, Geld zu sparen. Abonnieren Sie unseren Blog, damit Sie nichts verpassen, und teilen Sie uns in den Kommentaren mit, ob Sie während des Traffic-Anstiegs ähnliche Probleme hatten.

Wie wir den 10-fachen Anstieg der Arbeitsbelastung aus der Ferne überstanden haben und welche Schlussfolgerungen wir daraus gezogen haben

An der Umfrage können nur registrierte Benutzer teilnehmen. Einloggenbitte.

Haben Sie jemals eine Verlangsamung/Einbuße des Dienstes aufgrund eines starken Anstiegs der Auslastung erlebt, und zwar aus folgenden Gründen:

  • 55,6%Unfähigkeit, schnell Rechenressourcen hinzuzufügen10

  • 16,7%Einschränkungen der Hosting-Provider-Infrastruktur3

  • 33,3%Grenzen von Drittanbieter-APIs6

  • 27,8%Verstöße gegen die staatenlosen Grundsätze ihrer Anwendungen5

  • 88,9%Nicht optimaler Code eigener Dienste16

18 Benutzer haben abgestimmt. 6 Benutzer enthielten sich der Stimme.

Source: habr.com

Kaufen Sie zuverlässiges Hosting für Websites mit DDoS-Schutz und VPS-VDS-Servern 🔥 Kaufen Sie zuverlässiges Webhosting mit DDoS-Schutz, VPS- und VDS-Server | ProHoster