Maison >développement back-end >PHP8 >Explication des nouvelles fonctionnalités de PHP8.1 : Les fibres avec un grain de sel
Cet article est traduit, adresse originale : https://stitcher.io/blog/fibers-with-a-grain-of-salt
Des fibres avec un grain de sel
Je prévois donc d'écrire un article sur Un article de blog approfondi sur l'utilisation de Fibers dans PHP 8.1. Nous les expliquerons de A à Z, en commençant par un exemple simple. L’idée est d’envoyer des requêtes HTTP asynchrones et de les traiter en parallèle grâce à des fibres.
Mais en jouant avec eux, j'ai appris que la RFC ne plaisantait pas lorsqu'elle disait "L'API Fiber ne doit pas être utilisée directement dans le code au niveau de l'application. Fibers fournit une API de contrôle de flux de base de bas niveau pour créer des applications de niveau supérieur". niveau abstraction de niveau" qui est ensuite utilisé dans le code d'application.
Donc, plutôt que de suivre cette voie et de trop compliquer les choses, nous allons discuter de ce que sont les concepts de fibre, pourquoi ils sont à peine utilisables dans le code d'application et comment exactement vous pouvez utiliser PHP asynchrone.
Tout d’abord, un peu de théorie.
Supposons que vous souhaitiez envoyer trois requêtes HTTP et traiter leurs résultats combinés. La manière synchrone de procéder consiste à envoyer le premier, à attendre une réponse, puis à envoyer le second, à attendre, et ainsi de suite.
Utilisons le diagramme le plus simple possible pour représenter un tel déroulement de programme. Vous devez lire ce graphique de haut en bas, le temps descendant plus bas. Chaque couleur représente une requête HTTP. La partie colorée de chaque requête représente le code PHP en cours d'exécution, le processeur de votre serveur effectuant le travail et les blocs transparents représentent le temps d'attente : la requête doit être envoyée sur le réseau et d'autres serveurs doivent la traiter et l'envoyer. ce n'est que lorsque la réponse arrive que nous pouvons travailler à nouveau.
Il s'agit d'un processus d'exécution synchrone : envoyer, attendre, traiter, répéter.
Dans le monde du traitement parallèle, on envoie des demandes mais on n'attend pas. Ensuite, nous envoyons la demande suivante, puis une autre. Alors seulement, nous attendons toutes les demandes. En attendant, nous vérifions périodiquement si une de nos demandes a abouti. Si tel est le cas, nous pouvons le gérer immédiatement.
Vous pouvez voir comment cette approche réduit le temps d'exécution car nous utilisons le temps d'attente de manière plus optimale.
Les fibres sont un nouveau mécanisme de PHP 8.1 qui vous permet de gérer plus efficacement ces chemins d'exécution parallèles. Il est déjà possible d'obtenir un rendement en utilisant des générateurs et des fibres, mais les fibres constituent une amélioration significative car elles sont spécifiquement conçues pour ce cas d'utilisation.
Vous créerez une fibre pour chaque demande et mettrez la fibre en pause après l'envoi de la demande. Après avoir créé les trois fibres, vous les parcourirez en boucle et les restaurerez une par une. En faisant cela, la fibre vérifie si la demande est terminée et s'arrête à nouveau si ce n'est pas le cas, sinon elle peut traiter la réponse et éventuellement la terminer.
Vous voyez, une fibre est un mécanisme permettant de démarrer, de mettre en pause et de reprendre des parties isolées du flux d'exécution d'un programme. La fibre est également connue sous le nom de « fil vert » : un fil qui existe réellement au sein du même processus. Ces threads ne sont pas gérés par le système d'exploitation, mais par le runtime - dans notre cas le runtime PHP. Ils constituent un moyen rentable de gérer certaines formes de programmation parallèle.
Mais veuillez noter qu'ils n'ajoutent rien de vraiment asynchrone : toutes les fibres sont dans le même processus PHP, et une seule fibre peut être exécutée à la fois. C'est le processus principal qui les parcourt et les vérifie en attendant, cette boucle est souvent appelée "boucle d'événement".
La partie difficile du parallélisme n'est pas la façon dont vous effectuez une boucle sur des fibres ou des générateurs, ou quel que soit le mécanisme que vous souhaitez utiliser ; il s'agit de pouvoir démarrer une opération, la transmettre à un service externe et le faire uniquement lorsque vous le souhaitez. il est temps de vérifier les résultats de manière non bloquante.
Vous voyez, dans l'exemple précédent, nous avons supposé que nous pouvions simplement envoyer une demande, puis vérifier sa réponse lorsque nous le souhaitions, mais ce n'est en réalité pas aussi simple qu'il y paraît.
C'est vrai : la plupart des fonctions PHP qui gèrent les E/S n'ont pas cette fonctionnalité non bloquante intégrée. En fait, seules quelques fonctions le font, et leur utilisation est fastidieuse.
Il existe un exemple de socket qui peut être défini comme non bloquant, comme celui-ci :
[$read, $write] = stream_socket_pair( STREAM_PF_UNIX, STREAM_SOCK_STREAM, STREAM_IPPROTO_IP ); stream_set_blocking($read, false); stream_set_blocking($write, false);
En utilisant stream_socket_pair(), deux sockets sont créées et peuvent être utilisées pour la communication bidirectionnelle. Comme vous pouvez le voir, ils sont accessibles en utilisant stream_set_blocking()
Disons que nous voulons implémenter notre exemple, en envoyant trois requêtes. Nous pouvons le faire en utilisant des sockets, mais nous devons implémenter nous-mêmes le protocole HTTP par-dessus. C'est exactement ce qu'a fait nox7, un utilisateur qui a partagé une petite preuve de concept sur Reddit pour montrer comment envoyer une requête HTTP GET en utilisant de la fibre et des sockets. Voulez-vous vraiment faire cela dans votre code d’application ?
Pour moi du moins, la réponse est "non". C'est exactement ce contre quoi le RFC met en garde ; je ne suis pas offensé. Au lieu de cela, nous encourageons l'utilisation de l'un des frameworks asynchrones existants : Amp ou ReactPHP.
Par exemple, en utilisant ReactPHP, on peut écrire comme ceci :
$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 等框架集成?
Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!