Corutinas
Las corutinas son un mecanismo de concurrencia a nivel de usuario más ligero que los hilos, que permite programar múltiples tareas dentro de un proceso. Se realiza el cambio entre corutinas mediante el control manual de la suspensión y la reanudación, evitando el costo del cambio de contexto de procesos.
Workerman ofrece una interfaz de corutinas genérica que es compatible automáticamente con los controladores Swoole/Swow/Fiber en su base.
Sugerencia
Esta característica requiere workerman>=5.1.0
Notas
- Las corutinas solo son compatibles con los controladores
Swoole,SwowyFiber - Si se utiliza el controlador
Fiber, se debe instalarcomposer require revolt/event-loop - Los controladores
SwooleoSwowpueden convertir automáticamente las funciones de bloqueo de PHP en corutinas, permitiendo que el código sincrónico se ejecute de manera asíncrona - Sin embargo,
Fiberno puede convertir automáticamente en corutinas comoSwooleySwow, y si se encuentra con funciones de bloqueo de PHP, bloqueará todo el proceso y no habrá cambio de corutinas - Al usar los controladores
Swoole,SwowoFiber,workermancreará automáticamente una corutina para ejecutar cada vez que se ejecuten los callbacksonWorkerStart,onMessage,onConnect,onClose, etc. - Se puede usar
$worker->eventLoop=xxx;para establecer diferentes controladores de corutinas para diferentesworkers
<?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; // Utilizar corutinas de 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; // Utilizar corutinas Fiber integradas
$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();
Interfaz de Corutina
interface CoroutineInterface
{
/**
* Crear una corutina y ejecutarla inmediatamente
*/
public static function create(callable $callable, ...$data): CoroutineInterface;
/**
* Iniciar la ejecución de la corutina
*/
public function start(mixed ...$args): mixed;
/**
* Reanudar la ejecución de la corutina
*/
public function resume(mixed ...$args): mixed;
/**
* Obtener el id de la corutina
*/
public function id(): int;
/**
* Establecer un callback para cuando se destruya la corutina
*/
public static function defer(callable $callable): void;
/**
* Pausar la corutina actual
*/
public static function suspend(mixed $value = null): mixed;
/**
* Obtener la corutina actual
*/
public static function getCurrent(): CoroutineInterface|Fiber|SwowCoroutine|static;
/**
* Comprobar si actualmente está en un entorno de corutina
*/
public static function isCoroutine(): bool;
}
Sobre las Corutinas
Ventajas
La mayor ventaja de introducir corutinas en PHP es que permite escribir código asíncrono de manera sincrónica, evitando el infierno de los callbacks y mejorando la legibilidad y el mantenimiento del código.
Las corutinas pueden aumentar significativamente la elasticidad de los negocios intensivos en IO, permitiendo ofrecer un mayor rendimiento con menos procesos.
Desventajas
Sin embargo, al introducir corutinas, los desarrolladores deben estar siempre atentos a problemas como contaminación de variables globales, competencia de recursos, y modificaciones en bibliotecas de terceros, lo que incrementa el costo de desarrollo y mantenimiento, así como la carga mental.
La introducción de corutinas genera costos adicionales en la creación, programación, destrucción y los pools de conexión de corutinas.
De acuerdo con una gran cantidad de datos de pruebas de carga, al utilizar completamente la CPU, el rendimiento máximo después de introducir corutinas cae aproximadamente entre un 10% y un 20% en comparación con IO bloqueante.