Asynchrones PHP. Warum?

Bild

Asynchrone Programmierung ist heute gefragt, insbesondere in der Webentwicklung, wo die Reaktionsfähigkeit von Anwendungen besonders wichtig ist. Niemand möchte warten, bis die Anwendung "durchhängt", selbst wenn sie zu diesem Zeitpunkt eine Abfrage an die Datenbank ausführt, eine E-Mail sendet oder andere Aufgaben bearbeitet, die viel Zeit in Anspruch nehmen können. Der Kunde möchte sofort eine Antwort auf seine Aktion. Wenn Ihre Anwendung langsam ist, verlieren Sie Kunden. Angesichts einer schwebenden Anwendung schließt der Benutzer diese meistens einfach und kehrt nie zurück. Aus Sicht des Benutzers hat die Anwendung gerade gehangen, er kann nicht verstehen, warum dies passiert ist: Führt sie einen komplexen Vorgang aus oder funktioniert sie im Prinzip nicht mehr.

Einführung in die Übersetzung eines Artikels des Skyeng-Backend-Entwicklers Sergey Zhuk.

App Reaktionsfähigkeit


Moderne Anwendungen reagieren häufig, aber einige Aufgaben oder Vorgänge, z. B. der Datenaustausch über ein Netzwerk, Datei-E / A oder das Abfragen einer Datenbank, können zeitaufwändig sein und die Anwendung erheblich verlangsamen. Um zu verhindern, dass solche Vorgänge die Anwendung blockieren, können Sie sie im Hintergrund ausführen und so die von ihnen verursachte Verzögerung verbergen. Gleichzeitig reagiert die Anwendung weiterhin, da sie weiterhin andere Aufgaben ausführen kann, z. B. den Steuerungsfluss an die Benutzeroberfläche zurückgeben oder auf andere Ereignisse reagieren kann.

Parallelität und Asynchronität


Wenn Leute asynchronen Code sehen, denken sie meistens sofort: „Großartig, ich kann Prozesse parallelisieren!“. Ich kann Sie enttäuschen, aber in der Tat ist es nicht. Asynchronität und Parallelität sind nicht dasselbe. Es kann schwierig sein, diesen Unterschied zu erkennen. Versuchen wir also, ihn herauszufinden.

Wenn Aufgaben asynchron ausgeführt werden, blockieren sie sich nicht gegenseitig und die Ausführung einer Aufgabe hängt nicht vom Abschluss einer anderen Aufgabe ab. Parallelität bedeutet wiederum, dass mehrere separate Aufgaben gleichzeitig als unabhängige Arbeitseinheiten gestartet werden.

Asynchronität:
Gehen Sie und erledigen Sie die Aufgabe selbst . Lassen Sie mich wissen, wenn Sie fertig sind und zeigen Sie mir das Ergebnis. Zu diesem Zeitpunkt kann ich meine Arbeit fortsetzen.

Asynchroner Code erfordert die Verarbeitung von Abhängigkeiten, die während der Ausführung von Aufgaben auftreten, und dies wird mithilfe von Rückrufen implementiert. Wenn eine Aufgabe abgeschlossen ist, benachrichtigt der Code eine andere Aufgabe. Bei asynchronem Code handelt es sich im Wesentlichen um die Zeit, die die Aufgabe benötigt (Reihenfolge der Ereignisse).
Bild
Parallelität:
Stellen Sie so viele Mitarbeiter ein, wie Sie möchten, und teilen Sie die Aufgabe zwischen ihnen, um sie schneller zu erledigen, und benachrichtigen Sie mich, wenn Sie fertig sind. Ich kann weiterhin andere Dinge tun oder, wenn die Aufgabe dringend ist, bleiben und warten, bis Sie mit den Ergebnissen zurückkehren. Dann kann ich das Endergebnis aller Mitarbeiter zusammenstellen. Die parallele Ausführung erfordert häufig mehr Ressourcen, daher hängt dies hier im Wesentlichen von der Hardware ab.

Bild
Um den Unterschied zwischen asynchroner und paralleler Ausführung anhand eines Beispiels aus der Praxis zu verstehen, vergleichen wir zwei beliebte Webserver: Apache und Nginx. Sie veranschaulichen diesen Unterschied perfekt. Nginx verwendet ein ereignisbasiertes asynchrones Modell, während Apache parallele Threads verwendet. Apache erstellt für jede zusätzliche Verbindung neue Threads. Daher hängt die maximal zulässige Anzahl von Verbindungen hier von der Menge des verfügbaren Speichers im System ab. Wenn das Verbindungslimit erreicht ist, stellt Apache die Erstellung zusätzlicher Verbindungen ein. Der einschränkende Faktor bei der Konfiguration von Apache ist der Speicher (denken Sie daran, dass die parallele Ausführung häufig von der Hardware abhängt). Wenn der Thread stoppt, wartet der Client auf eine Antwort, bis der Thread frei ist und eine Antwort senden kann.

Nginx funktioniert nicht wie Apache - es erstellt nicht für jede eingehende Anfrage neue Threads. Nginx verfügt über einen Hauptworkflow (oder mehrere Worker, häufig gibt es für einen Prozessor einen Workflow), der aus einem Thread besteht. Dieser Worker kann Tausende von Verbindungen "gleichzeitig" verarbeiten und dies asynchron in einem Thread und nicht parallel in mehreren Threads.

"Asynchronität" ist also die Art und Weise, wie wir das System aufbauen. Es ist eine Zusammensetzung von Prozessen, die unabhängig voneinander sind. Mit "paralleler Ausführung" ist die Ausführung mehrerer Prozesse zum gleichen Zeitpunkt gemeint, während sie miteinander verbunden sein können oder nicht. Bei der asynchronen Ausführung verarbeiten wir mehrere Aufgaben gleichzeitig und bei der parallelen Ausführung starten wir mehrere Prozesse gleichzeitig. Dies scheint dasselbe zu sein, ist es aber nicht. Asynchronität beschreibt eine Struktur, Parallelität beschreibt einen Weg, dies zu tun.

Die asynchrone Ausführung kann mit E / A-Geräten auf Ihrem Computer (Maus, Tastatur, Display) verglichen werden. Sie werden alle vom Betriebssystem verwaltet, aber jeder von ihnen ist ein unabhängiger Teil des Kernels. Diese Prozesse sind asynchron, sie können parallel sein, dies ist jedoch nicht erforderlich. Um die Konsistenz zu gewährleisten, müssen Sie daher eine Verknüpfung zwischen diesen unabhängigen Teilen herstellen, um sie zu koordinieren.

Was ist mit diesem Backend?


Man kann sagen, dass die Reaktionsfähigkeit im Backend nicht so wichtig ist. All diese coolen asynchronen Dinge mit JavaScript passieren auf einem Freeend, und Ihr Server reagiert nur auf Anfragen. Daher sollte ein Freeend für die Reaktionsfähigkeit der Anwendung verantwortlich sein, nicht Sie. Ja, das stimmt, aber die Aufgabe des Servers ist nicht auf API-Antworten beschränkt. Manchmal müssen Sie komplexe Aufgaben verwalten, z. B. das Herunterladen eines Videos. In diesem Fall ist die Reaktionsfähigkeit möglicherweise kein Schlüsselfaktor, aber der Mangel an Ressourcen wird verschwendet, da die Anwendung inaktiv sein muss. Es kann auf den Abschluss von Dateisystemoperationen, Netzwerkinteraktionen, Datenbankabfragen und dergleichen warten. Oft sind diese E / A-Vorgänge im Vergleich zu Prozessorberechnungen sehr langsam, beispielsweise wenn wir Videodateien konvertieren. Und während wir die Datei langsam speichern oder lesen, muss der Prozessor in den Standby-Modus wechseln, anstatt nützliche Arbeit zu leisten. Wie wir bereits herausgefunden haben, können wir diese Aufgaben im Hintergrund ausführen, anstatt zu warten. Wie? Mach weiter.

Asynchrones PHP


In JavaScript stehen sofort integrierte Unterstützung und Lösungen zum Schreiben von asynchronem Code zur Verfügung. Es gibt auch Node.js, mit dem Sie asynchrone Serveranwendungen schreiben können. In JavaScript können wir die Funktion setTimeout () verwenden, um ein Beispiel für asynchronen Code zu demonstrieren:
Bild

Wenn wir diesen Code ausführen, sehen wir Folgendes:
Bild

Die Funktion setTimeout () sendet den Code an die Warteschlange und führt ihn am Ende des aktuellen Aufrufstapels aus. Dies bedeutet, dass wir den synchronen Codefluss stören und die Ausführung verzögern. Der zweite Aufruf von console.log () wird vor dem Aufruf der Warteschlange im Aufruf von setTimeout () ausgeführt.

Was ist mit PHP? In PHP verfügen wir nicht über geeignete angepasste Tools zum Schreiben von wirklich asynchronem Code. Es gibt kein Äquivalent zu setTimeout (), und wir können keinen Code einfach verzögern oder in die Warteschlange stellen. Aus diesem Grund tauchten Frameworks und Bibliotheken wie Amp und ReactPHP auf. Ihre Idee ist es, Sprachdetails auf niedriger Ebene auszublenden und dem Benutzer Tools auf hoher Ebene zur Verfügung zu stellen, mit denen Sie asynchronen Code schreiben und die wettbewerbsfähige Ausführung von Prozessen wie JavaScript und Node.js steuern können.

Warum sollte ich PHP verwenden, wenn es Node.js und Go gibt?


Diese Frage stellt sich häufig, wenn es um asynchrones PHP geht. Aus irgendeinem Grund sind viele gegen die Verwendung von PHP zum Schreiben von asynchronem Code. Jemand schlägt immer vor, Go oder Node.js. anstelle von PHP zu verwenden.

Der Assertchris- Tweet beschreibt diese Situationen perfekt:

Bild

Als PHP gerade erstellt wurde, gab es natürlich keinen Zweck, es zu einer Programmiersprache zu machen, mit der große komplexe Anwendungen erstellt werden können. Zu dieser Zeit dachte niemand an JavaScript oder Asynchronität. Aber jetzt haben wir ein völlig anderes PHP, das bereits eigene Funktionen zum Schreiben von asynchronem Code hat (zum Beispiel die Funktion stream_select ()).

Ja, Sie können Go oder Node.js verwenden, um asynchrone Serveranwendungen zu erstellen. Dies löst das Problem jedoch nicht immer. Wenn Sie bereits über umfangreiche Erfahrungen mit PHP verfügen, ist es für Sie viel einfacher, die für Ihre Situation geeigneten Bibliotheken und Tools zu erlernen, als eine neue Sprache und ein neues Ökosystem zu erlernen. Mit Tools wie ReactPHP oder Amp können Sie asynchronen Code schreiben, genau wie Sie es in Node.js tun. Diese Tools sind ziemlich entwickelt und haben stabile Versionen, sodass Sie sie sicher in der Produktion verwenden können.

Nicht nur CLI


Ich werde keinen Chat, Server oder ähnliches schreiben. Ich möchte nur die Seite beschleunigen.

Es ist allgemein anerkannt, dass asynchroner Code nur in CLI-Skripten verwendet werden kann. Es ist absolut normal, einige asynchrone Komponenten in eine herkömmliche synchrone Umgebung zu integrieren, selbst in eine herkömmliche Webanwendung. Beispielsweise können Sie eine Anfrage empfangen und dann mehrere verschiedene Ressourcen asynchron aufrufen. Wenn diese Anrufe abgeschlossen sind, können Sie den Lebenszyklus von Anfrage und Antwort fortsetzen. Infolgedessen wird die Seite schneller angezeigt.

Oder Sie müssen einige externe API-Aufrufe durchführen. Wenn ein Benutzer beispielsweise eine Zahlung abschließt, möchten Sie eine E-Mail oder eine Push-Benachrichtigung senden. Sie können diese API-Aufrufe asynchron ausführen und dann Ihren herkömmlichen synchronen Codestream fortsetzen. Es ist nicht erforderlich, die Anwendung vollständig neu zu schreiben und alles zu löschen, was langsamer wird. Identifizieren Sie einfach Engpässe, die die Leistung beeinträchtigen, und es ist möglich, dass sie mithilfe von asynchronem Code behoben werden können.

Ja, asynchroner Code wird in den meisten Fällen immer noch in CLI-Skripten verwendet, ist jedoch nicht auf Echtzeit-Chats und -Server beschränkt. Wenn Sie Ihre Site nur beschleunigen möchten, müssen Sie Ihr Symfony- oder Laravel-Framework nicht aufgeben und Ihren eigenen vollständig asynchronen Anwendungsserver erstellen.

Fazit


Haben Sie keine Angst, ein neues Paradigma zu lernen. PHP ist viel mehr als "ein Skript ausführen, Code ausführen und sterben". Sie werden überrascht sein, wenn Sie feststellen, dass Sie das vertraute PHP auf eine völlig neue Art und Weise verwenden können, als hätten Sie es nie verwendet! Asynchroner Code und ereignisorientierte Programmierung erweitern Ihr Verständnis von PHP und die Möglichkeiten der Verwendung dieser Sprache. Sie müssen keine neue Sprache zum Schreiben asynchroner Anwendungen lernen, nur weil "PHP ein unangemessenes Tool ist" oder "Ich habe dies immer getan, es kann nicht verbessert werden." Probieren Sie es einfach aus!

Wir erinnern Sie auch daran, dass wir immer viele interessante Stellen für Entwickler haben!

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


All Articles