Coroutines
Les coroutines sont un mécanisme de concurrence léger au niveau des utilisateurs, plus léger que les threads, permettant une planification multitâche au sein d'un processus. Elles réalisent des changements entre coroutines par un contrôle manuel de la suspension et de la reprise, évitant ainsi le coût des changements de contexte de processus. Workerman fournit une interface de coroutine générique, compatible automatiquement avec les pilotes Swoole/Swow/Fiber en sous-jacent.
Remarque
Cette fonctionnalité nécessite workerman>=5.1.0
Attention
- Les coroutines ne supportent que les pilotes
Swoole,Swow,Fiber - Si vous utilisez le pilote
Fiber, il est nécessaire d'installercomposer require revolt/event-loop - Les pilotes
SwooleouSwowpeuvent transformer automatiquement les fonctions bloquantes PHP en coroutines, permettant ainsi l'exécution asynchrone du code original synchronisé - Toutefois,
Fiberne peut pas effectuer cette transformation automatique commeSwooleetSwow, et lorsqu'il rencontre des fonctions bloquantes fournies par PHP, il bloque tout le processus sans effectuer de changement de coroutine - Lorsque vous utilisez les pilotes
Swoole,SwowouFiber,workermancréera automatiquement une coroutine à chaque exécution des rappelsonWorkerStart,onMessage,onConnect,onClose, etc. - Vous pouvez utiliser
$worker->eventLoop=xxx;pour définir des pilotes de coroutine différents pour différentsworkers
<?php
use Workerman\Connection\TcpConnection;
use Workerman\Coroutine;
use Workerman\Events\Swoole;
use Workerman\Events\Fiber;
use Workerman\Protocols\Http\Request;
use Workerman\Worker;
require_once __DIR__ . '/vendor/autoload.php';
$worker1 = new Worker('http://0.0.0.0:8001');
$worker1->eventLoop = Swoole::class; // Utiliser la coroutine Swoole
$worker1->onMessage = function (TcpConnection $connection, Request $request) {
Coroutine::create(function () {
echo file_get_contents("http://www.example.com/event/notify");
});
$connection->send('ok');
};
$worker2 = new Worker('http://0.0.0.0:8001');
$worker2->eventLoop = Fiber::class; // Utiliser la coroutine Fiber intégrée
$worker2->onMessage = function (TcpConnection $connection, Request $request) {
Coroutine::create(function () {
echo file_get_contents("http://www.example.com/event/notify");
});
$connection->send('ok');
};
Worker::runAll();
Interface fournie par les coroutines
interface CoroutineInterface
{
/**
* Créer une coroutine et l'exécuter immédiatement
*/
public static function create(callable $callable, ...$data): CoroutineInterface;
/**
* Démarrer l'exécution de la coroutine
*/
public function start(mixed ...$args): mixed;
/**
* Reprendre l'exécution de la coroutine
*/
public function resume(mixed ...$args): mixed;
/**
* Obtenir l'ID de la coroutine
*/
public function id(): int;
/**
* Définir le rappel lors de la destruction de la coroutine
*/
public static function defer(callable $callable): void;
/**
* Suspendre la coroutine actuelle
*/
public static function suspend(mixed $value = null): mixed;
/**
* Obtenir la coroutine actuelle
*/
public static function getCurrent(): CoroutineInterface|Fiber|SwowCoroutine|static;
/**
* Vérifier si l'environnement est celui d'une coroutine
*/
public static function isCoroutine(): bool;
}
À propos des coroutines
Avantages
L'introduction des coroutines en PHP permet d'écrire du code asynchrone de manière synchrone, évitant ainsi le "callback hell", et améliore la lisibilité et la maintenabilité du code.
Les coroutines peuvent considérablement améliorer la flexibilité des applications à forte intensité d'E/S, permettant de fournir un débit plus élevé avec moins de processus.
Inconvénients
Cependant, l'introduction des coroutines exige que les développeurs soient constamment attentifs à la pollution des variables globales, à la concurrence des ressources et à la modification des bibliothèques tierces, augmentant ainsi les coûts de développement et la charge cognitive.
L'introduction des coroutines entraîne des coûts supplémentaires tels que la création, la planification, la destruction des coroutines et les pools de connexions.
D'après de nombreuses données de tests de charge, dans des conditions d'utilisation optimale du CPU, l'introduction de coroutines diminue les performances maximales d'environ 10 % à 20 % par rapport à l'E/S bloquante.