Coroutines
Le coroutines sono un meccanismo di concorrenza a livello utente più leggero rispetto ai thread, che consente la programmazione multi-tasking all'interno di un processo. Realizzano il cambio tra coroutines attraverso il controllo manuale della sospensione e del ripristino, evitando il costo del cambio di contesto del processo. Workerman fornisce un'interfaccia generica per le coroutines, compatibile automaticamente con i driver Swoole/Swow/Fiber.
Suggerimento
Questa funzionalità richiede workerman>=5.1.0
Attenzione
- Le coroutines supportano solo i driver
Swoole,Swow,Fiber - Se si utilizza il driver
Fiber, è necessario installarecomposer require revolt/event-loop - I driver
SwooleoSwowpossono automatizzare la coroutine per le funzioni di blocco di PHP, consentendo l'esecuzione asincrona del codice originariamente sincrono - Tuttavia,
Fibernon può automatizzare le coroutine comeSwooleeSwow; quando incontra funzioni di blocco fornite da PHP, blocca l'intero processo e non avviene alcun cambio di coroutine - Quando si utilizzano i driver
Swoole,Swow,Fiber,workermancrea automaticamente una coroutine ad ogni chiamata delle callbackonWorkerStart,onMessage,onConnect,onClose, ecc. - È possibile utilizzare
$worker->eventLoop=xxx;per impostare driver di coroutine diversi per diversiworker
<?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; // Utilizza 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; // Utilizza la coroutine Fiber integrata
$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();
Interfaccia fornita dalle coroutines
interface CoroutineInterface
{
/**
* Crea una coroutine ed eseguila immediatamente
*/
public static function create(callable $callable, ...$data): CoroutineInterface;
/**
* Inizia l'esecuzione della coroutine
*/
public function start(mixed ...$args): mixed;
/**
* Riprendi l'esecuzione della coroutine
*/
public function resume(mixed ...$args): mixed;
/**
* Ottieni l'id della coroutine
*/
public function id(): int;
/**
* Imposta il callback da eseguire al momento della distruzione della coroutine
*/
public static function defer(callable $callable): void;
/**
* Sospendi la coroutine corrente
*/
public static function suspend(mixed $value = null): mixed;
/**
* Ottieni la coroutine corrente
*/
public static function getCurrent(): CoroutineInterface|Fiber|SwowCoroutine|static;
/**
* Verifica se si è in un ambiente di coroutine
*/
public static function isCoroutine(): bool;
}
Informazioni sulle coroutines
Vantaggi
L'introduzione delle coroutines in PHP consente di scrivere codice asincrono in modo sincrono, evitando il "callback hell", migliorando la leggibilità e la manutenibilità del codice. Le coroutines possono migliorare significativamente la resilienza delle operazioni I/O intensive, consentendo a meno processi di fornire una maggiore capacità di throughput.
Svantaggi
Tuttavia, con l'introduzione delle coroutines, gli sviluppatori devono prestare attenzione alla contaminazione delle variabili globali, alla concorrenza delle risorse, alla modifica delle librerie di terze parti, e così via, il che aumenta il costo di sviluppo e manutenzione e aumenta significativamente il carico mentale.
L'introduzione delle coroutines comporta costi aggiuntivi per la creazione, la pianificazione, la distruzione delle coroutines e il pooling delle connessioni. Dall'analisi dei dati sui test di carico, si osserva che, in condizioni di utilizzo ottimale della CPU, le performance massime con l'introduzione delle coroutines possono diminuire di circa il 10%-20% rispetto all'I/O bloccante.