Heim > Artikel > Backend-Entwicklung > Neue Funktionen von PHP8.1 erklärt: Fasern mit Vorsicht
Dieser Artikel ist übersetzt, Originaladresse: https://stitcher.io/blog/fibers-with-a-grain-of-salt
Fasern mit einem Körnchen Salz
Also habe ich vor, einen zu schreiben Artikel über einen ausführlichen Blogbeitrag zur Verwendung von Fibers in PHP 8.1. Wir erklären sie von Grund auf, beginnend mit einem einfachen Beispiel. Die Idee besteht darin, asynchrone HTTP-Anfragen zu senden und diese mithilfe von Fibers parallel zu verarbeiten.
Aber als ich damit herumspielte, stellte ich fest, dass der RFC keine Witze machte, als er sagte: „Die Fiber-API sollte nicht direkt im Code auf Anwendungsebene verwendet werden.“ Fibers bietet eine einfache Flusssteuerungs-API auf niedriger Ebene, um höhere Werte zu erstellen. Level-Level-Abstraktion“, die dann im Anwendungscode verwendet wird.
Anstatt also diesen Weg einzuschlagen und die Dinge zu kompliziert zu machen, werden wir diskutieren, was Glasfaserkonzepte sind, warum sie im Anwendungscode kaum verwendbar sind und wie genau Sie asynchrones PHP verwenden können.
Zuerst eine kleine Theorie.
Angenommen, Sie möchten drei HTTP-Anfragen senden und deren kombinierte Ergebnisse verarbeiten. Die synchrone Vorgehensweise besteht darin, die erste zu senden, auf eine Antwort zu warten, dann die zweite zu senden, zu warten und so weiter.
Lassen Sie uns ein möglichst einfaches Diagramm verwenden, um einen solchen Programmablauf darzustellen. Sie müssen dieses Diagramm von oben nach unten lesen, wobei die Zeit weiter nach unten geht. Jede Farbe repräsentiert eine HTTP-Anfrage. Der farbige Teil jeder Anfrage stellt den tatsächlich ausgeführten PHP-Code dar, wobei die CPU auf Ihrem Server die Arbeit erledigt, und die transparenten Blöcke stellen die Wartezeit dar: Die Anfrage muss über das Netzwerk gesendet werden, und andere Server müssen sie verarbeiten und senden Erst wenn die Antwort eintrifft, können wir wieder arbeiten.
Dies ist ein synchroner Ausführungsprozess: Senden, Warten, Verarbeiten, Wiederholen.
In der Welt der Parallelverarbeitung senden wir Anfragen, warten aber nicht. Dann senden wir die nächste Anfrage und dann noch eine. Erst dann warten wir auf alle Anfragen. Während wir warten, überprüfen wir regelmäßig, ob eine unserer Anfragen abgeschlossen wurde. Sollte dies der Fall sein, können wir uns sofort darum kümmern.
Sie können sehen, wie dieser Ansatz die Ausführungszeit verkürzt, da wir die Wartezeit optimaler nutzen.
Fasern sind ein neuer Mechanismus in PHP 8.1, der es Ihnen ermöglicht, diese parallelen Ausführungspfade effizienter zu verwalten. Mit Generatoren und ist bereits ein Ertrag möglich, Fasern stellen jedoch eine deutliche Verbesserung dar, da sie speziell für diesen Anwendungsfall entwickelt wurden.
Sie erstellen für jede Anfrage eine Fiber und pausieren die Fiber, nachdem die Anfrage gesendet wurde. Nachdem Sie alle drei Fasern erstellt haben, werden Sie sie durchlaufen und eine nach der anderen wiederherstellen. Auf diese Weise prüft die Glasfaser, ob die Anfrage abgeschlossen wurde, und pausiert andernfalls erneut, andernfalls kann sie die Antwort verarbeiten und schließlich abschließen.
Sie sehen, eine Faser ist ein Mechanismus zum Starten, Anhalten und Fortsetzen isolierter Teile des Ausführungsflusses eines Programms. Fiber wird auch als „grüner Thread“ bezeichnet: ein Thread, der tatsächlich innerhalb desselben Prozesses existiert. Diese Threads werden nicht vom Betriebssystem verwaltet, sondern von der Laufzeit – in unserem Fall der PHP-Laufzeit. Sie sind eine kostengünstige Möglichkeit, einige Formen der parallelen Programmierung zu verwalten.
Aber bitte beachten Sie, dass sie nichts wirklich Asynchrones hinzufügen: Alle Fasern befinden sich im selben PHP-Prozess und es kann jeweils nur eine Faser ausgeführt werden. Dies ist der Hauptprozess, der sie durchläuft und während des Wartens überprüft. Diese Schleife wird oft als „Ereignisschleife“ bezeichnet.
Der schwierige Teil der Parallelität besteht nicht darin, wie Sie Fasern oder Generatoren schleifen oder welchen Mechanismus Sie auch immer verwenden möchten. Es geht darum, einen Vorgang starten, an einen externen Dienst übergeben zu können und ihn nur dann auszuführen, wenn Sie möchten Zeit, die Ergebnisse blockierungsfrei zu überprüfen.
Sehen Sie, im vorherigen Beispiel gingen wir davon aus, dass wir einfach eine Anfrage senden und dann nach deren Antwort suchen könnten, wenn wir wollten, aber das ist tatsächlich nicht so einfach, wie es sich anhört.
Das ist richtig: Die meisten PHP-Funktionen, die E/A verarbeiten, verfügen nicht über diese nicht blockierende Funktionalität. Tatsächlich tun dies nur wenige Funktionen und ihre Verwendung ist umständlich.
Es gibt ein Beispiel für einen Socket, der auf nicht blockierend eingestellt werden kann, wie folgt:
[$read, $write] = stream_socket_pair( STREAM_PF_UNIX, STREAM_SOCK_STREAM, STREAM_IPPROTO_IP ); stream_set_blocking($read, false); stream_set_blocking($write, false);
Durch die Verwendung von stream_socket_pair() werden zwei Sockets erstellt, die für die bidirektionale Kommunikation verwendet werden können. Wie Sie sehen, kann auf sie mit stream_set_blocking() zugegriffen werden.
Nehmen wir an, wir möchten unser Beispiel implementieren und drei Anfragen senden. Wir können dies mithilfe von Sockets tun, aber wir müssen darüber hinaus das HTTP-Protokoll selbst implementieren. Genau das hat nox7 getan, ein Benutzer, der auf Reddit einen kleinen Proof of Concept geteilt hat, um zu zeigen, wie man eine HTTP-GET-Anfrage über Glasfaser und Sockets sendet. Möchten Sie dies wirklich in Ihrem Anwendungscode tun?
Zumindest für mich lautet die Antwort „Nein“. Genau davor warnt der RFC; ich bin nicht beleidigt. Stattdessen empfehlen wir die Verwendung eines der vorhandenen asynchronen Frameworks: Amp oder ReactPHP.
Mit ReactPHP können wir beispielsweise so schreiben:
$loop = React\EventLoop\Factory::create(); $browser = new Clue\React\Buzz\Browser($loop); $promises = [ $browser->get('https://example.com/1'), $browser->get('https://example.com/2'), $browser->get('https://example.com/3'), ]; $responses = Block\awaitAll($promises, $loop);
与手动创建套接字连接相比,这是一个更好的示例。这就是 RFC 的意思:应用程序开发人员不需要担心纤程,它是 Amp 或 ReactPHP 等框架的实现细节。
不过,这给我们带来了一个问题:与我们已经可以用发电机做的事情相比,纤维有什么好处?RFC 是这样解释的:
与无堆栈生成器不同,每个 Fiber 都有自己的调用堆栈,允许它们在深度嵌套的函数调用中暂停。声明中断点的函数(即调用 Fiber::suspend())不需要更改其返回类型,这与使用 yield 的函数必须返回 Generator 实例不同。
Fiber 可以在任何函数调用中挂起,包括那些从 PHP VM 内部调用的函数,例如提供给 array_map 的函数或迭代器对象上的 foreach 调用的方法。
很明显,纤程在语法和灵活性方面都有显着的改进。但与 Go 及其“ goroutines ”相比,它们还不算什么。
要使异步 PHP 在没有框架开销的情况下成为主流,仍然缺少许多功能,而 Fiber 是朝着正确方向迈出的良好一步,但我们还没有做到这一点。
所以就是这样。如果您不是 Amp、ReactPHP 或较小的异步 PHP 框架的维护者,那么实际上没有什么可说的。也许更多的框架或库将开始合并它们?
同时,还有Swoole——一个 PHP 扩展,它实际上将几个核心功能修改为非阻塞。Swoole 本身是一个中文项目,在涉及英语时通常没有很好的文档记录,但最近 Laravel宣布与它进行第一方集成。也许这是将 PHP 推向更异步模型的更好策略:可选择将 Swoole 或其他扩展与 Laravel 和 Symfony 等框架集成?
Das obige ist der detaillierte Inhalt vonNeue Funktionen von PHP8.1 erklärt: Fasern mit Vorsicht. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!