Eisen oder Optimierung? Badoo, Avito und Mamba - über die PHP-Leistung

Das PHP-Leistungsproblem für Badoo ist eines der wichtigsten. Die Qualität des PHP-Backends hängt direkt von der Menge der Ressourcen ab, die wir für Entwicklung und Betrieb ausgeben, von der Geschwindigkeit des Dienstes und von dem Eindruck, den es auf die Benutzer macht.

Aus diesem Grund haben wir beim Thema des dritten Treffens der Community von PHP-Entwicklern in unserem Büro Backend-Performance gemacht und Kollegen von Avito und Mamba zur Diskussion eingeladen.



Lesen Sie unter dem Zwischensequenzprotokoll der Diskussion, in der ich das Glück hatte, Moderator zu sein: Wie die Infrastruktur der drei Unternehmen aufgebaut ist, wie wir die Produktivität messen und auf welche Metriken wir uns konzentrieren, welche Tools wir verwenden, wie wir zwischen Hardware und Optimierung wählen.

Und am 15. Februar kommen Sie zum nächsten Badoo PHP Meetup : Besprechen Sie Legacy.



Wir haben nur den Teil der Diskussion entschlüsselt, der uns am interessantesten erschien. Die Vollversion ist als Video verfügbar.

Experten:

  • Semyon Kataev, Leiter der Entwicklungsabteilung bei Core Services Avito
  • Pavel Murzakov pmurzakov, PHP Timlid in Badoo
  • Mikhail Buylov mipxtx, IT-Direktor von Mamba


Erzählen Sie eine Geschichte über Optimierung aus Ihrer Praxis: Großer Erfolg oder großer Misserfolg ist etwas, das interessant zu teilen ist.

Mikhail Buylov, Mamba


Ich habe ein Gleichnis.

Ungefähr alle sechs Monate schauen wir uns die Metriken an und suchen, was langsamer wird, nicht gut funktioniert und was optimiert werden muss. Einmal bemerkten wir unseren Symfony-Abhängigkeitscontainer, der auf 52.000 Zeilen angewachsen war. Wir entschieden, dass er, der Schurke, für alles verantwortlich war: 20 ms Overhead für jede Anfrage. Wir haben es gesägt. Wir haben es reduziert. Wir haben irgendwie versucht, es zu trennen, aber nichts hat geholfen.

Und dann stellte sich heraus, dass wir Anti-Spam haben, das in 20 Datenbanken gehen muss, um alle erforderlichen Anforderungen zu erfüllen.

Die Lösungen, die zuerst kommen, sind nicht immer die richtigen. Sehen Sie sich die Spuren, Protokolle und Benchmarks Ihrer Anforderungen besser an und brechen Sie nicht direkt ab. Hier ist eine Geschichte.

Pavel Murzakov, Badoo


Wir haben ein ziemlich großes Ökosystem in PHP, daher führen wir regelmäßig Optimierungen durch. Wir wachsen, wir erreichen ein gewisses Niveau in der CPU, wir verstehen, dass wir entweder Hardware kaufen oder optimieren müssen. Wägen Sie die Argumente für und gegen jede Option ab und entscheiden Sie. Meistens - zugunsten der Optimierung, weil Eisen viel braucht.

An einem dieser Punkte haben wir eine ganze Gruppe identifiziert, die verschiedene nicht optimale Dinge in PHP-Skripten gesucht und optimiert hat. Dies geschah buchstäblich „Tropfen für Tropfen“: Hier fanden sie einen Prozentsatz, dort fanden sie einen Prozentsatz - mehrere Personen fanden innerhalb eines Monats einen Prozentsatz. Irgendwann war unser Sishnik in der Näheeinstein_man. Er beschloss zu sehen, was er tun konnte: Er ging abends, startete Perf, fand ein paar Probleme mit PHP-Erweiterungen - und beschleunigte alles an ein paar Abenden um 13%!

Semyon Kataev, Avito


Ich habe zwei Geschichten. Einer über die Datei, der andere über den Superentwickler.

Über den Fehler. Wir haben viele Microservices, einschließlich PHP. Jeder arbeitet bei Kubernetes. Ich habe an einem dieser Microservices gearbeitet. Es gab eine erhebliche CPU-Auslastung: Sie verbrachten eine Woche damit, Probleme zu optimieren und zu finden. Es stellte sich heraus, dass einer der Entwickler Xdebug zu den Basis-Images hinzufügte, um Code-Coverage-Tests in seinem (anderen) Service zu berechnen. Danach arbeiteten alle Microservices in der Produktion ein Viertel lang mit Xdebug! Nach einem Viertel entdeckten wir diese grundlegenden Bilder - und fingen an, unerwartete Geschenke zu fangen: Ich rollte meinen Dienst neu und es begann schneller zu funktionieren. Bei jeder Bereitstellung wird unser Service-Image neu erstellt und jetzt ohne Xdebug.

Erfolgsgeschichte. Wir haben viele Microservices, und sie wurden immer mehr. In dieser Situation wird die Anzahl der RPC-Aufrufe zum Problem. Auf einer Ankündigungskarte - und dies ist eine der häufigsten Seiten in Avito - sind beispielsweise etwa 30 Microservices am Rendern einer Seite beteiligt. Darüber hinaus wurde dies alles nicht sehr explizit durchgeführt: Es scheint, als würden Sie eine Art Abstraktion aufrufen, und darunter werden fünf RPC-Aufrufe an andere Dienste nacheinander ausgeführt.

Im Laufe der Jahre wurde die Ankündigungskarte stark verschlechtert. Ein starker Entwickler kämpfte um ein Viertel, optimierte und brachte alle RPC-Aufrufe heraus. Als er dazu in der Lage war, parallelisierte er sie über Guzzle Multi Request - und statt 30 aufeinanderfolgender synchroner Anfragen erhielt er dieselben 30 Anfragen, aber parallele, was die Arbeit erheblich beschleunigte. Nach diesem Refactoring entspricht die Antwortzeit der Karte der maximalen Antwortzeit eines der Dienste. Aber er brauchte ein ganzes Viertel, um den Anzeigecode der Ankündigungskarte zu optimieren / umzuschreiben.

Sagen Sie uns, wie groß Ihr PHP-Cluster ist, wie er konfiguriert ist - zumindest PHP-FPM oder vielleicht irgendwo, wo Apache in Schwierigkeiten geraten ist?

Mikhail Buylov, Mamba


Wir haben ungefähr 15.000 RPS. Ein Cluster von 80 FPM-Servern, die vor einigen Jahren gekauft wurden. In jedem Cluster wird FPM (maximal 50 Kinder) in die Statik gestartet. Es lud ungefähr zehn in der Spitze zur Hauptsendezeit. Die durchschnittliche Reaktionszeit beträgt 100 ms und wir versuchen sie zu halten (wenn sie 100 ms überschreitet, beginnen wir mit der Suche nach Bremsstücken).

Wir haben ein eigenes Leistungsüberwachungssystem. Wir haben viele Zähler im Code verteilt, ungefähr 120 pro Anfrage. Wir überwachen viele Ereignisse, die innerhalb des Codes in PHP auftreten.

Pavel Murzakov, Badoo


Bei uns ist alles Standard: Nginx, PHP-FPM. Ungefähr 600 Server mit FPM. Wenn Sie überhaupt über PHP sprechen möchten, dann gibt es wahrscheinlich etwa 300 weitere Server für verschiedene Zwecke, wie z. B. Skript, Backoffice und andere.

Von den Konfigurationsfunktionen gibt es zwei. Erstens haben wir einen BMA-Proxy - dies ist ein Proxy für Mobilgeräte. Das heißt, bevor eine Anforderung in nginx eintrifft, gelangt sie zu einem speziellen Proxy, der eine dauerhafte Verbindung hält, und sendet Anforderungen an nginx. Die zweite Funktion - manchmal müssen Sie den CLI-Opcache deaktivieren (wir haben ihn auf Skriptmaschinen aktiviert). Einmal haben wir es nicht ausgeschaltet und dabei 30% der CPU verloren. Nachdem sie ihren Fehler erkannt hatten, waren sie überrascht, wie viel Sie mit einer Einstellung sparen können.

Wir haben PHP-Patches, aber sie hängen fast nicht mit der Leistung zusammen.

Es gibt einen Punkt mit der wettbewerbsfähigen APCu-Sperre - wenn Sie viel auf denselben Schlüssel schreiben müssen. Die interne Architektur von APCu ist so aufgebaut, dass es eine globale Tastensperre gibt und während der intensiven Aufzeichnung die Bremsen beginnen. Daher haben wir dort eine benutzerdefinierte Erweiterung, die dieses Problem löst. Dies bezieht sich nur teilweise auf die Leistung, da es die Antwortzeit beeinflusst, nicht jedoch den CPU-Verbrauch.

Semyon Kataev, Avito


Wir haben ungefähr 2 Millionen Anfragen pro Minute (~ 33 kRPS). Eine in PHP geschriebene monolithische Anwendung wurde über 11 Jahre lang geschrieben. Es befindet sich in einer Phase schnellen Wachstums. Als das Unternehmen anfing, befanden sich 65 LXCs auf 65 physischen Servern. Auf jedem Container mit der Anwendung werden PHP-FPM, Nginx und Hilfssoftware für Metriken und Protokollierung ausgeführt. Nichts Besonderes.

Im Laufe der Jahre haben wir noch nie Eisen für einen Monolithen hinzugefügt. Wir erhöhen die Besucherzahlen, die Anzahl der Anzeigen und die Anzahl der Nutzertransaktionen und optimieren ständig, verbessern den Code und optimieren die Software. Der CPU- und Speicherverbrauch ist in den letzten Jahren gesunken: 65 Container für einen Monolithen reichen uns jetzt.

Wie messen Sie die Leistung? Mit welchem ​​Tool messen Sie die Antwortzeit des Kunden?

Mikhail Buylov, Mamba


Wir haben ein Protokollsammelsystem. Es werden zwei Indikatoren protokolliert - die Zeit vom Start des FPM bis zum Herunterfahren und bis zum Ende des Skripts. Die zweite Metrik wird benötigt, um zu sehen, was nach dem Herunterfahren passiert.

Wir messen JS. Dies ist in der Tat eine mittelmäßige Metrik, Netzwerkkanäle werden sehr oft verletzt. Infolgedessen beginnt das Laden irgendwo im russischen Outback zu stumpfen. Deshalb sehen wir so aus: "Oh, gesprungen - es bedeutet, dass irgendwo etwas abgefallen ist." Außerdem verzerrt Werbung von Drittanbietern die Metrik erheblich. Und vor allem kommen Spammer, und dies ist im Allgemeinen eine Art Zufälligkeit.

Semyon Kataev, Avito


Übrigens haben wir Pinba von Badoo sehr aktiv eingesetzt . Ich mag sie jetzt. Die meisten Metriken wurden von ihm gesammelt, dann aber auf das StatsD-Protokoll umgestellt. Jetzt nehmen wir Messungen von verschiedenen Punkten aus vor: von vorne, von den Servern vor der Anwendung, von Nginx und von der PHP-Anwendung selbst. Wir haben ein engagiertes Leistungsteam. Sie begann mit der Leistung der Front, wechselte dann aber zum Backing. Von vorne erfasst es nicht nur JS, CSS und andere Statiken, sondern gleichzeitig auch die Serverantwortzeit. Zunächst konzentrieren wir uns auf die Reaktionszeit der Anwendung.

Pavel Murzakov, Badoo


Alles ist ähnlich wie die Jungs uns erzählt haben. Mit dem klassischen Pinba für PHP messen wir die Laufzeit eines PHP-Skripts in Bezug auf PHP. Wir haben aber zum Beispiel auch Pinba für Nginx, das die Reaktionszeit aus Sicht von Nginx misst. Wir sammeln auch Metriken auf dem Client.

Was schauen wir uns an? Einerseits die Reaktionszeit. Es hat nichts mit Ressourcenplanung zu tun. Wenn es schlecht ist, muss es verbessert werden, weil es in der Tat die Qualität des Service ist. Eine andere Sache ist, dass Sie das Eisen irgendwie planen müssen. Unsere ITOps und Überwachungsteams überwachen die gesamte Hardware. Es gibt einige Balken im Netzwerk auf der Festplatte. Es gibt einige Werte, nach denen die Warnung auftritt - und wir tun etwas. Wie die Praxis gezeigt hat, optimieren wir normalerweise für die CPU: Wir stoßen darauf.

Semyon Kataev, Avito


Bei uns misst sich die PHP-Anwendung selbst und wirft in register_shutdown_function () Metriken aus. Jeder LXC verfügt über einen StatsD-Server, der diese Metriken sammelt und über die Kollektoren an den Graphite-Cluster (einschließlich ClickHouse) sendet, wo die Daten gespeichert werden. Dies ist eine Selbstdiagnose.

Auf jedem Behälter befindet sich auch Nginx, d. H. Nginx + PHP-FPM. Mit nginx erfassen wir externe Metriken, die sich auf die Laufzeit einer PHP-Anwendung beziehen. Sie sind auch mit separaten Servern (wir nennen sie avi-http) nginx konfrontiert, die ein grundlegendes Routing durchführen, das auch übergeordnete Metriken wie die Antwortzeit, die Anzahl von 500 Antwortcodes und andere erfasst.

Welche Tools haben Sie für einen Performance-Track? Was benutzt du am häufigsten?

Mikhail Buylov, Mamba


Wir haben unser eigenes Tool geschrieben. Als Pinba gerade herauskam - 2012, vor sehr langer Zeit - war es ein Modul für MySQL, das so etwas über UDP erhalten hat. Es war schwierig, die Grafiken herauszunehmen, da sie nicht sehr leistungsoptimiert waren. Und wir haben uns nichts Besseres ausgedacht, als unser eigenes Ding namens Better Than Pinba zu schreiben. Es ist nur ein Zählerserver, der sie von einem PHP-Client akzeptiert.

Wir haben viele Timer im Code verstreut: Jedes Mal, wenn wir etwas messen möchten, setzen wir den Start und Stopp des Timers im Code. Das Modul selbst berechnet die Zählerlaufzeit, fasst die akkumulierten Zähler zu einem Paket zusammen und sendet sie an den Dämon. Die Schnittstelle selbst extrahiert alles, was Sie benötigen, und erstellt verbundene Diagramme auf dem gewünschten Zähler.

Eines der Probleme von Pinba war das Fehlen einer eigenen Schnittstelle - es war notwendig, Daten an RRD zu übertragen (dann gab es eine solche Dunkelheit). Deshalb haben wir unsere eigene Oberfläche geschrieben. Jedes Mal, wenn wir sehen, was gesprungen ist, können wir das Skript installieren. Im Skript werden alle aggregierten Zähler an uns gesendet, die an uns gesendet werden. Wir können sehen, wo welcher Zähler gewachsen ist, oder die Antwortzeit am Zähler hat sich erhöht oder die Anzahl der Zähler hat sich erhöht.

Es kann gesehen werden, wenn die Leistung sinkt. Wir fangen an, auf diese Weise zu graben. Vor PHP 7 haben wir XHProf verwendet, dann hat es aufgehört, mit uns zu bauen. Deshalb haben wir auf Xdebug umgestellt. Xdebug stupsen wir nur, wenn das Problem sichtbar ist.

Pavel Murzakov, Badoo


Dies ist eine verbreitete Überzeugung, dass XHProf nicht in PHP 7 erstellt wird. Dies ist wahr, aber nur teilweise. Wenn Sie XHProf aus dem Assistenten nehmen, wird dies wirklich nicht der Fall sein. Aber wenn Sie auf GitHub zu einem Zweig namens Experimental (oder so ähnlich) wechseln, funktioniert alles gut für PHP 7, produktionsbereit. Überprüft.

Mikhail Buylov, Mamba


Nein, ich habe gewechselt. Bei mir hat es nicht funktioniert.

Pavel Murzakov, Badoo


Ich möchte über Pinba hinzufügen. Sie sind bis zu einem gewissen Grad Propheten geworden. Auch wir haben irgendwann an Produktivität verloren. Wir haben Pinba2 gemacht , was sehr schnell ist. Es kann als Ersatz für Pinba verwendet werden.

Semyon Kataev, Avito


Bei uns ist alles bescheiden. Wir haben nur die Richtung der Leistung in die Arbeit einbezogen: Wir sammeln Metriken wie die Antwortzeit. Wir verwenden StatsD. Wir verwenden noch keine regelmäßigen Profiler, aber ich weiß mit Sicherheit, dass einige Teams sie in ihren in PHP geschriebenen Microservices verwenden. Meiner Meinung nach gibt sogar jemand New Relic weiter. Aber im Kontext der monolithischen Hauptanwendung nähern wir uns bisher nur diesem.

Pavel Murzakov, Badoo


Die Eisengeschichte wird in Grafana, Zabbix, überwacht. Was den PHP-Teil betrifft, haben wir Pinba, wir haben eine Reihe von Timern; Wir bauen praktische Grafiken darauf. Wir verwenden XHProf, in der Produktion fahren wir es für einen Teil der Anfragen. Wir haben immer frische XHProf-Profile zur Verfügung. Wir haben liveprof: Dies ist unser Tool, das Sie lesen können, auch in meinem Artikel . Es passiert alles automatisch, man muss nur zuschauen. Wir benutzen phpspy. Bei uns fängt es nicht immer an: Wenn jemand etwas sehen will, steigt er ins Auto, nimmt sein Profil ab. Grundsätzlich wie bei Perf.

Semyon Kataev, Avito


XHProf hat die gleiche Geschichte. Wir haben es vor langer Zeit einmal benutzt: Es war eine persönliche Initiative einiger Entwickler und hat sich tatsächlich nicht durchgesetzt. Er hörte auf zu sammeln. Wir sammeln eine Reihe von Metriken aus Anrufen von Routern, Controllern und verschiedenen Modellen. Etwa 60–70% des internen Netzwerks des Rechenzentrums sind mit UDP-Paketen mit Metriken belegt. Im Moment reicht uns das. Jetzt werden wir nach neuen Orten für die Optimierung suchen.

Seit wir den Punkt des Eisens erreicht haben: Ist jemand in Ihrem Unternehmen systematisch mit der Kapazitätsplanung beschäftigt? Wie ist dieser Prozess aufgebaut?

Semyon Kataev, Avito


Eine monolithische Anwendung läuft mindestens fünf Jahre lang mit mindestens 65 LXC. Wir optimieren den Code, verbessern ihn: Er verfügt über genügend Ressourcen. Unsere Hauptkapazitätsplanung geht an Kubernetes, wo ungefähr 400 mehr oder weniger lebende Microservices in PHP / Go geschrieben sind. Wir schneiden langsam Stücke aus dem Monolithen, aber er wächst immer noch. Wir können ihn nicht aufhalten.

Im Allgemeinen ist PHP eine coole Sprache. Es implementiert schnell Geschäftslogik.

Pavel Murzakov, Badoo


Zunächst stellen ITOps und Überwachungsteams sicher, dass genügend Ressourcen vorhanden sind. Wenn wir uns dem Schwellenwert nähern, bemerken dies die Kollegen. Sie sind wahrscheinlich hauptsächlich für die globale Kapazitätsplanung verantwortlich. Der PHP-Teil hat die Haupt-CPU-Ressource, daher folgen wir ihm selbst.

Wir setzen uns selbst Maßstäbe: Wir sollten nicht mehr als 60% des Clusters "essen". 60% und nicht 95%, weil wir Hypertreading haben, das zusätzlich mehr aus dem Prozessor herausdrückt, als Sie ohne es herausdrücken können. Dafür zahlen wir dafür, dass wir nach 50% unseres CPU-Verbrauchs auf unvorhersehbare Weise wachsen können, weil hyperlesende Kernel nicht ganz ehrlich sind.

Mikhail Buylov, Mamba


Wir führen eine Bereitstellung durch und stellen fest, dass bei uns etwas fehlgeschlagen ist - eine solche Kapazitätsplanung. Mit dem Auge! Wir haben einen gewissen Produktivitätsspielraum, der uns dies ermöglicht. Wir versuchen dabei zu bleiben.

Darüber hinaus führen wir eine Post-Factum-Optimierung durch. Wenn wir sehen, dass etwas abgefallen ist, rollen wir zurück, wenn alles völlig schlecht ist. Das passiert aber praktisch nicht.

Oder wir sehen nur, dass "hier nicht optimal ist, jetzt werden wir schnell alles reparieren und alles wird so funktionieren, wie es sollte."

Wir kümmern uns nicht besonders darum: Es ist sehr schwierig und der Auspuff wird nicht sehr groß sein.

Sie sprechen von Microservices. Wie interagieren sie? Ist es REST oder verwenden Sie binäre Protokolle?

Semyon Kataev, Avito


Kafka wird verwendet, um Ereignisse zwischen Diensten zu senden. JSON-RPC wird verwendet, um die Interaktion zwischen Diensten sicherzustellen, jedoch nicht vollständig, sondern die vereinfachte Version, die wir nicht loswerden können. Es gibt schnellere Implementierungen: das gleiche Protokoll, gRPC. Dies ist in unseren Plänen, aber sicherlich keine Priorität. Bei über 400 Microservices ist es schwierig, alle auf das neue Protokoll zu portieren. Es gibt unzählige andere Orte, die optimiert werden müssen. Wir sind jetzt definitiv nicht in der Lage.

Pavel Murzakov, Badoo


Wir als solche haben keine Microservices. Es gibt Dienste, es gibt auch Kafka, ein eigenes Protokoll über Google Protobuf. Wahrscheinlich würden wir gRPC verwenden, weil es cool ist, alle Sprachen unterstützt und sehr einfach verschiedene Teile binden kann. Aber als wir es brauchten, war gRPC noch nicht da. Aber es gab einen Protobuf, und wir haben ihn genommen. Darüber hinaus wurden verschiedene Dinge hinzugefügt, so dass es sich nicht nur um eine Serialisierung, sondern um ein vollständiges Protokoll handelte.

Mikhail Buylov, Mamba


Wir haben auch keine Microservices. Es gibt Dienste, die hauptsächlich in C geschrieben sind. Wir verwenden JSON-RPC, weil es praktisch ist. Sie haben gerade den Socket geöffnet, als Sie Ihren Code debuggen, und schnell geschrieben, was Sie wollten. Etwas ist zu dir zurückgekehrt. Protobuf ist schwieriger, da Sie einige zusätzliche Tools verwenden müssen. Es gibt einen kleinen Overhead, aber wir glauben, dass Sie für die Bequemlichkeit bezahlen müssen, und dies ist kein großer Preis.

Sie haben riesige Datenbanken. Wie machen Sie es, wenn Sie die Schaltung in einem von ihnen ändern müssen? Irgendeine Art von Migrationen? Wie wirkt sich dies auf die Leistung aus, wenn diese Migrationen mehrere Tage dauern?

Mikhail Buylov, Mamba


Wir haben große Tische, monolithisch. Es gibt eine Scherbe. Die Scherbe ändert sich ziemlich schnell, weil es viele parallele Änderungen gleichzeitig gibt. Ein großer Tisch mit Profilen änderte sich etwa drei Stunden. Wir verwenden Perkonovskie-Tools, die nicht gelesen und geschrieben werden können. Darüber hinaus stellen wir Änderungen bereit, sodass der Code beide Status unterstützt. Nach der Änderung stellen wir auch bereit: Die Bereitstellung ist schneller als das Anwenden von Schemata.

Pavel Murzakov, Badoo


Wir haben den größten Speicher (wir nennen es "Spots") - dies ist eine riesige Sharded-Datenbank. Wenn wir die "Benutzer" -Tabelle nehmen, dann hat sie viele Scherben. Ich werde Ihnen nicht genau sagen, wie viele Tabellen sich auf einem Server befinden werden. Die Idee ist, dass es viele kleine Tabellen gibt. Wenn wir die Schaltung ändern, nehmen wir tatsächlich nur eine Änderung vor. Auf jedem kleinen Tisch geht es schnell. Es gibt andere Repositories - es gibt bereits andere Ansätze. Wenn es eine riesige Basis gibt, gibt es perkonische Werkzeuge.

Im Allgemeinen verwenden wir je nach Bedarf unterschiedliche Dinge. Die häufigste Änderung ist eine Änderung dieser riesigen Basis aus Splittern, in der wir bereits einen Prozess aufgebaut haben. Es funktioniert alles sehr einfach.

Semyon Kataev, Avito


Dieselbe monolithische Anwendung, die den größten Teil des Datenverkehrs bedient, wird fünf- bis sechsmal täglich bereitgestellt. Fast alle zwei Stunden.

In Bezug auf die Arbeit mit der Datenbank ist dies ein separates Problem. Es gibt Migrationen, sie rollen automatisch. Dies ist eine DBA-Überprüfung. Es besteht die Möglichkeit, die Migration zu überspringen und manuell zu rollen. Die Migration wird beim Testen von Code automatisch in die Bereitstellung übernommen. Wenn es in der Produktion jedoch eine zweifelhafte Migration gibt, die eine Reihe von Ressourcen beansprucht, startet der DBA sie manuell.

Der Code sollte so sein, dass er mit den alten und neuen Datenbankstrukturen funktioniert. Wir führen häufig mehrere Reisen durch, um Funktionen bereitzustellen. Für zwei oder drei Roll-Outs ist es möglich, den gewünschten Zustand zu erhalten. Ebenso gibt es riesige Datenbanken, Sharded-Datenbanken. Wenn wir für alle Microservices zählen, gibt es definitiv 100-150 Bereitstellungen pro Tag.

Ich würde gerne wissen, wie hoch die Standard-Backend-Antwortzeit für Sie ist, der Sie folgen. Wann verstehen Sie, was Sie zur weiteren Optimierung benötigen, oder wann ist die Zeit bis zum Abschluss? Gibt es einen „Krankenhausdurchschnitt“?

Pavel Murzakov, Badoo


Nein. Hängt vom Endpunkt ab. Wir betrachten alles separat. Ich versuche zu verstehen, wie kritisch das ist. Einige Endpunkte werden im Allgemeinen im Hintergrund angefordert. Dies hat keinerlei Auswirkungen auf den Benutzer, selbst wenn die Antwortzeit 20 s beträgt. Dies wird im Hintergrund passieren, es gibt keinen Unterschied. Die Hauptsache ist, dass einige wichtige Dinge schnell erledigt werden. Vielleicht sind 200 ms noch in Ordnung, aber ein kleiner Anstieg ist schon wichtig.

Mikhail Buylov, Mamba


Wir wechseln vom HTML-Rendering zu API-Anfragen. Tatsächlich reagiert die API hier viel schneller als die große, schwere HTML-Antwort. Daher ist es schwierig, beispielsweise einen Wert von 100 ms zu unterscheiden. Wir haben uns auf 200 ms konzentriert. Dann passierte PHP 7 - und wir begannen uns auf 100 ms zu konzentrieren. Dies ist der "Durchschnitt für das Krankenhaus". Dies ist eine sehr vage Metrik, die darauf hindeutet, dass es Zeit ist, zumindest dort nachzuschauen. Deshalb konzentrieren wir uns eher auf die Bereitstellung und überspringen die Reaktionszeit danach.

Semyon Kataev, Avito


Wir haben eine Skizze eines der Leistungsteams gemacht. Die Kollegen haben gemessen, wie viel mehr ein Unternehmen verdient, indem es das Laden von Seiten in verschiedenen Szenarien beschleunigt. Wir haben berechnet, wie viel mehr Käufer, Transaktionen, Anrufe, Übergänge usw. stattfinden. Nach diesen Daten kann verstanden werden, dass die Beschleunigung irgendwann keinen Sinn mehr ergibt. Wenn beispielsweise die Antwortzeit einer der Seiten von 90 ms auf 70 ms beschleunigt wurde, ergab dies + 2% der Käufer. Und wenn Sie von 70 ms auf 60 ms beschleunigen, gibt es bereits plus 0,1% der Käufer, was im Allgemeinen im Fehler enthalten ist. Genau wie bei den Jungs hängt alles stark von der Seite ab, mit der wir arbeiten. Im Allgemeinen Avito 75. Perzentil - etwa 75 ms. Meiner Meinung nach ist das langsam. Wir suchen jetzt nach Orten zur Optimierung. Vor dem Übergang zu Microservices ging für uns alles viel schneller und wir versuchen, die Leistung zu optimieren.



Und die ewige Frage: Eisen oder Optimierung? Wie kann man verstehen, ob es sich lohnt, Hardware zu kaufen, oder ob es besser ist, in die Optimierung zu investieren? Wo ist die Grenze?

Semyon Kataev, Avito


Meine Meinung: Ein echter Programmierer ist die Optimierung. Es scheint mir, dass es in großen Unternehmen wie Badoo, Mine, Yandex viele Entwickler auf verschiedenen Ebenen gibt. Es gibt sowohl Nachwuchsentwickler / Praktikanten als auch führende Entwickler. Es scheint mir, dass die Anzahl der Stellen für die Optimierung / Überarbeitung dort immer hinzugefügt wird. Eisen ist der letzte Schritt. Für einen Monolithen auf 65 LXC haben wir lange Zeit kein Eisen hinzugefügt. CPU-Auslastung - 20%. Wir denken bereits darüber nach, sie in den Kubernetes-Cluster zu übertragen.

Pavel Murzakov, Badoo


Ich mag die Position von Semyon sehr. Aber ich habe einen völlig entgegengesetzten Standpunkt. Zuerst würde ich mir das Eisen ansehen. Kann man Eisen fallen lassen und ist es billiger? Wenn ja, ist es einfacher, das Problem mit Eisen zu lösen. Der Entwickler kann etwas anderes tun, das zu diesem Zeitpunkt nützlich ist. Entwicklerzeit kostet Geld. Eisen kostet auch Geld, also müssen Sie vergleichen.

Welche davon wichtiger ist, ist unklar. Wenn beide gleich viel kosten, gewinnt die Hardware, da der Entwickler zu diesem Zeitpunkt etwas tun kann. Insbesondere in Bezug auf das PHP-Backend können wir dies nicht tun. Optimierung kostet uns viel billiger als der Kauf von Eisen.

Über zu stoppen. In Bezug auf die Planung haben wir eine Art Bar. Wenn wir den CPU-Verbrauch darunter senken, hören wir auf. Zum anderen gibt es auch die Servicequalität. Wenn wir feststellen, dass die Reaktionszeit nicht zu uns passt, müssen wir optimieren.

Mikhail Buylov, Mamba


Mir scheint, dass alles von der Größe des Teams und des Projekts abhängt. Je kleiner das Projekt ist, desto einfacher ist es, Hardware zu kaufen, da das Gehalt des Entwicklers konstant ist und der Code, der funktioniert, die Benutzer, die damit arbeiten, sehr unterschiedlich sind. Wenn es nur wenige Benutzer gibt, ist es einfacher, Hardware zu kaufen und den Entwickler mit der Entwicklung des Projekts zu beauftragen. Wenn es viele Benutzer gibt, kann ein Entwickler den größten Teil der Serverkosten kompensieren.

Semyon Kataev, Avito


Alles hängt wirklich von der Größe ab. Wenn Sie über tausend Server verfügen und die Optimierung dazu führt, dass Sie keine weiteren tausend Server benötigen, ist eine Optimierung eindeutig besser. Wenn Sie einen Server haben, können Sie sicher zwei oder drei weitere Server kaufen und bei der Optimierung punkten. Wenn der Befehl klein ist, starten Sie den Kauf der Server. Wenn das Team groß ist und Sie zwei oder drei Rechenzentren haben, ist der Kauf von sechs Rechenzentren bereits nicht so billig und nicht so schnell.

Da wir ein PHP-Mitap haben, sollte dieser Satz klingen: Warum brauchen wir PHP, da wir ständig solche Probleme haben? Lassen Sie uns Go, C, C #, Rust, Node.js umschreiben!
Halten Sie den Ansatz des Umschreibens im Allgemeinen für gerechtfertigt? Gibt es Probleme, für deren Lösung es sich lohnt, dies zu tun und zu investieren?

Semyon Kataev, Avito


Im Allgemeinen ist PHP eine sehr gute Sprache. Es ermöglicht Ihnen wirklich, geschäftliche Probleme zu lösen. Er ist schnell genug. Alle Leistungsprobleme sind Probleme mit Fehlern, Fehlern und altem Code (eine Art unterbewerteter Code, suboptimale Dinge, die auf die gleiche Weise in einer anderen Sprache aufgenommen worden wären). Wenn Sie sie roh nach Golang, Java, Python portieren, erhalten Sie die gleiche Leistung. Das ganze Problem ist, dass es viel Vermächtnis gibt.

Die Einführung einer neuen Sprache ist meiner Meinung nach sinnvoll, um den Stapel und die Beschäftigungsmöglichkeiten zu erweitern. Jetzt ist es schwierig genug, gute PHP-Entwickler zu finden. Wenn wir Golang in den Techradar einführen, können wir Gophers einstellen. Es gibt nur wenige PHP-Shniks und wenige Gophers auf dem Markt, und zusammen gibt es bereits viele davon. Zum Beispiel hatten wir ein Experiment. Wir haben C # -Entwickler mitgenommen, die bereit sind, neue Sprachen zu lernen - wir haben einfach den Einstellungsstapel erweitert. Wenn wir den Leuten sagen, dass wir ihnen das Schreiben in PHP beibringen, sagen sie, dass es besser ist, dies nicht zu tun. Und wenn wir ihnen anbieten, das Schreiben in PHP zu lernen, gehen Sie und versprechen Sie trotzdem die Möglichkeit, in Python zu schreiben, dann sind die Leute eher bereit zu antworten. Für mich ist dies eine Erweiterung der Beschäftigungsmöglichkeiten. In anderen Sprachen fehlen einige Dinge in PHP wirklich. Im Allgemeinen reicht PHP jedoch hervorragend aus, um geschäftliche Probleme zu lösen und große Projekte zu implementieren.

Pavel Murzakov, Badoo


Ich stimme Semyon wahrscheinlich vollkommen zu. Das Umschreiben macht einfach keinen Sinn. PHP ist eine ziemlich produktive Sprache. Wenn Sie es mit anderen nicht kompilierten Skriptsprachen vergleichen, ist es wahrscheinlich fast die schnellste. In einige Sprachen wie Go und andere umschreiben? Dies sind andere Sprachen, sie haben andere Probleme. Es ist noch schwieriger, darüber zu schreiben: nicht so schnell und es gibt viele Nuancen.

Trotzdem gibt es Dinge, die in PHP entweder schwierig oder unpraktisch zu schreiben sind. Einige Dinge mit mehreren Prozessen und mehreren Threads lassen sich besser in einer anderen Sprache schreiben. Ein Beispiel für eine Aufgabe, bei der die Nichtverwendung von PHP gerechtfertigt ist, ist im Prinzip jeder Speicher. Wenn dies ein Dienst ist, der viel im Speicher speichert, ist PHP wahrscheinlich nicht die beste Sprache, da es aufgrund der dynamischen Typisierung einen sehr großen Speicheraufwand hat. Es stellt sich heraus, dass Sie ein 4-Byte-Int speichern und 50 Bytes verbraucht werden. Natürlich übertreibe ich, aber dieser Aufwand ist immer noch sehr groß. Wenn Sie über eine Art Speicher verfügen, ist es besser, ihn in einer anderen kompilierten Sprache mit statischer Typisierung zu schreiben. Genau wie einige Dinge, die eine Multithread-Ausführung erfordern.

Mikhail Buylov, Mamba


Warum wird PHP nicht als sehr schnell angesehen? Weil es dynamisch ist. Die Go-Übersetzung ist eine Lösung für das Problem der Übersetzung von Code von dynamischer Typisierung in statische. Dadurch geht alles schneller. Speziell für Go gibt es in meinem Plan Aufgaben eines bestimmten Datenstroms. Wenn beispielsweise ein Datenstrom in bequemere Formate konvertiert werden muss, ist dies eine ideale Sache. Von einem Daemon ausgelöst, empfängt er einen Datenstrom an der Eingabe, gibt einen anderen aus. Wenig Erinnerung frisst. PHP verbraucht in diesem Fall viel Speicher: Sie müssen sorgfältig sicherstellen, dass es gereinigt wird.

Transfer to Go ist eine Übertragung auf Microservices, da Sie nicht den gesamten Code ausschneiden. Sie werden es nicht vollständig nehmen und neu schreiben. Die Übersetzung in Microservices ist eine tiefere Aufgabe als die Übersetzung von einer Sprache in eine andere. Es ist notwendig, es zuerst zu lösen und dann darüber nachzudenken, welche Sprache geschrieben werden soll. Der schwierigste Teil ist das Erlernen von Microservices.

Semyon Kataev, Avito


Es ist nicht erforderlich, Go in Microservices zu verwenden. Viele Dienste sind in PHP geschrieben und haben eine akzeptable Antwortzeit. Das Team, das sie unterstützt, hat selbst entschieden, dass sie sehr schnell Geschäftslogik schreiben und Funktionen einführen müssen. Sie machen tatsächlich manchmal schneller als Gophers.

Wir neigen dazu, Gophers einzustellen und in Go zu übersetzen. Aber wir haben immer noch den größten Teil des Codes in PHP geschrieben, und so wird es noch mindestens ein paar Jahre dauern. Es gibt kein richtiges Rennen, wir haben nicht entschieden, dass Go besser oder schlechter ist. Täglich werden sechs Releases in den Monolithen eingeführt. Unser Chat "Avito Deploy" enthält eine Liste der Aufgaben, die bereitgestellt werden. In jeder Version werden mindestens 20 Aufgaben pro Tag ausgeführt: mindestens fünf oder sechs Versionen pro Tag, ungefähr 80 Aufgaben, die Benutzer für diese Aufgaben ausgeführt haben. All dies geschieht in PHP.

? -, ?

,


Das ist sehr schwer. Es gibt einen psychologischen Moment: Ich habe eine neue Funktion gestartet - Sie sind fertig. Startete eine gigantische neue Funktion - du bist super jung! Wenn ein Manager oder Entwickler angibt, dass er eine Funktion entfernt (außer Betrieb genommen) hat, erhält er keine solche Anerkennung. Seine Arbeit ist nicht sichtbar. Zum Beispiel kann ein Team einen Bonus für die erfolgreiche Implementierung neuer Funktionen erhalten, aber ich habe keine Auszeichnungen für tote oder experimentelle Funktionen gesehen. Und das Ergebnis kann wirklich kolossal sein.

Eine Reihe von Legacy-Funktionen, die noch niemand verwendet, verlangsamt die Entwicklung. Es gibt Hunderte von Fällen, in denen eine neue Person zu einem Unternehmen kommt und einen toten Code überarbeitet, der niemals aufgerufen wird, weil sie nicht weiß, dass es sich um einen toten Code handelt.

Wir versuchen irgendwie mit Managern zu verhandeln, herauszufinden, was für ein Feature es war, mit Analysten überlegen wir, wie viel Geld es bringt, wer es braucht, und erst danach versuchen wir es zu reduzieren. Dies ist ein komplizierter Prozess.

Mikhail Buylov, Mamba


Wir schneiden toten Code ab, wenn wir dazu kommen. Und es ist bei weitem nicht immer möglich, es schnell zu schneiden. Zuerst schreiben Sie einen Code, dann einen anderen, über einen dritten, und dann stellt sich heraus, dass diese Funktion nicht benötigt wird. Sie zieht eine wilde Anzahl von Abhängigkeiten, die ebenfalls behoben werden müssen. Dies ist nicht immer möglich, und Manager müssen dies melden.

Der Manager legt die Aufgabe fest, Sie bewerten sie. Sie sagen: "Weißt du, Mann, ich mache das sechs Monate lang. Bist du bereit, ein halbes Jahr zu tolerieren? “ Er sagt: "Nein, lass uns überlegen, was geschnitten werden muss, was übrig bleiben kann. Was ist grundsätzlich notwendig und was ist nötig, um herumzuspielen. “ So läuft das.

Pavel Murzakov, Badoo


Wenn ein Entwickler ein Feature erhält, bewertet er, wie schwierig es in Bezug auf die Entwicklung ist, wie schwierig es in Bezug auf die Leistung ist. Wenn er das eine oder andere sieht, klärt er mit dem Produktmanager, ob dies wirklich notwendig ist, ob wir irgendwo etwas entfernen können. Manchmal kommt es vor, dass Änderungen nicht kritisch sind und Manager schnell Zugeständnisse machen, wenn sie feststellen, dass diese Sache kompliziert ist oder Ressourcen verbraucht. Es passiert einfach: Sie sagen "Entfernen wir es" - und das war's.

Es kommt vor, dass ein Feature verlassen wird, und danach stellen wir fest, dass es nicht so gut funktioniert, wie wir es möchten. Und dann können Sie wieder mit dem Manager sprechen. Oft endet alles erfolgreich.

Es gibt keinen integrierten Prozess zum Entfernen von Funktionen. Dies geschieht sporadisch. Wir sehen, dass es eine Funktion gibt, wir kommen und bieten an, sie auszuschalten. Wir schalten es aus, beobachten, was es gibt, und schneiden es aus. Eine andere Sache ist toter Code. Wir haben eine spezielle Erweiterung, sogar eine ganze Infrastruktur, für die Erkennung von totem Code. Wir sehen diesen toten Code. Wir versuchen es langsam abzuschneiden. Eine andere Frage ist, ob es wirklich tot ist und die Anfrage es nie eingibt, dann hat es keinerlei Auswirkungen auf die Leistung. Dies wirkt sich auf die Unterstützbarkeit aus. Die Leute lesen es ständig, obwohl sie es vielleicht nicht lesen. Es gibt keinen besonderen Zusammenhang mit der Leistung.

15 Badoo PHP Meetup. , : SuperJob, ManyChat, , Badoo FunCorp .

, , YouTube-. , - .

, .

Source: https://habr.com/ru/post/undefined/


All Articles