Coletinas
Coletinas são um mecanismo de concorrência de nível de usuário mais leve do que threads, capaz de implementar agendamento de múltiplas tarefas dentro de um processo. Elas permitem a troca entre coletinas por meio do controle manual de suspensão e retomada, evitando o custo de troca de contexto de processo.
O Workerman fornece uma interface genérica para coletinas, com compatibilidade automática para drivers Swoole/Swow/Fiber.
Dica
Esse recurso requer workerman>=5.1.0
Atenção
- Coletinas suportam apenas os drivers
SwooleSwowFiber - Se utilizar o driver
Fiber, é necessário instalarcomposer require revolt/event-loop - Os drivers
SwooleouSwowpodem realizar a corotização automática de funções bloqueantes do PHP, permitindo que o código síncrono original execute de forma assíncrona - No entanto, o
Fibernão pode ser automaticamente corotizado como os driversSwooleeSwow, e ao encontrar funções bloqueantes nativas do PHP, bloqueará todo o processo, sem ocorrer troca de coletinas - Ao usar os drivers
SwooleSwowFiber, oworkermancriará automaticamente uma coletina para executar sempre que chamar os callbacksonWorkerStart,onMessage,onConnect,onClose, etc. - É possível utilizar
$worker->eventLoop=xxx;para definir diferentes drivers de coletina 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; // Usando coletina 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; // Usando coletina Fiber nativa
$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();
Interfaces oferecidas pelas coletinas
interface CoroutineInterface
{
/**
* Criar coletina e executar imediatamente
*/
public static function create(callable $callable, ...$data): CoroutineInterface;
/**
* Iniciar a execução da coletina
*/
public function start(mixed ...$args): mixed;
/**
* Retomar a execução da coletina
*/
public function resume(mixed ...$args): mixed;
/**
* Obter o id da coletina
*/
public function id(): int;
/**
* Definir um callback para quando a coletina for destruída
*/
public static function defer(callable $callable): void;
/**
* Pausar a coletina atual
*/
public static function suspend(mixed $value = null): mixed;
/**
* Obter a coletina atual
*/
public static function getCurrent(): CoroutineInterface|Fiber|SwowCoroutine|static;
/**
* Verificar se estamos em um ambiente de coletina
*/
public static function isCoroutine(): bool;
}
Sobre Coletinas
Vantagens
A maior vantagem da introdução de coletinas no PHP é que elas permitem escrever código assíncrono de forma síncrona, evitando o chamado "callback hell" e aumentando a legibilidade e a manutenibilidade do código.
Coletinas podem aumentar significativamente a resiliência de serviços que são intensivos em I/O, permitindo oferecer uma maior capacidade de processamento com menos processos.
Desvantagens
No entanto, a introdução de coletinas requer que os desenvolvedores estejam sempre atentos a problemas de poluição de variáveis globais, competição por recursos e transformações em bibliotecas de terceiros, o que aumenta o custo de desenvolvimento e a carga mental.
A introdução de coletinas resulta em despesas adicionais relacionadas à criação, agendamento, destruição e gerenciamento de pools de conexões.
Dados de testes extensivos mostram que, ao utilizar de maneira eficaz o CPU, a performance máxima com coletinas é cerca de 10%-20% inferior em comparação com I/O bloqueante.