Servidores de alto desempenho com Swoole
Atenda milhares de conexões com o Swoole baseado em corrotinas.
Servidores de alto desempenho com Swoole é uma aula grátis de PHP Academy no CoddyKit. Esta é a aula 4 de 4. Você pode ler a aula completa abaixo gratuitamente — depois pratica ao vivo no navegador com um editor de código integrado e um tutor de IA 24/7. Faz parte do caminho de aprendizado de PHP Academy, e seu progresso é sincronizado entre a web e o app CoddyKit. O curso de PHP Academy inclui 4 aulas no total.
O que é o Swoole
O Swoole (e seu fork, o OpenSwoole) é uma extensão em C que transforma o PHP em um ambiente de execução de alto desempenho, baseado em corrotinas e orientado a eventos. Em vez de o PHP-FPM criar um processo por solicitação, um servidor Swoole inicializa sua aplicação uma vez e a mantém residente na memória, atendendo às solicitações por meio de um conjunto de processos de trabalho de longa duração com corrotinas integradas. O resultado: ganhos de vazão de várias ordens de grandeza e concorrência nativa em uma única solicitação.
O servidor HTTP persistente
O exemplo clássico: um servidor HTTP completo em um script. Ele escuta, encaminha cada solicitação para um trabalhador e nunca reinicializa o framework. Observe que isso requer ext-swoole — não é executado no PHP CLI padrão.
<?php
$server = new Swoole\Http\Server('0.0.0.0', 9501);
$server->set(['worker_num' => 4]);
$server->on('request', function ($request, $response) {
$response->header('Content-Type', 'application/json');
$response->end(json_encode(['hello' => $request->server['request_uri']]));
});
echo "listening on :9501\n";
$server->start();Corrotinas, não funções de retorno
O grande diferencial do Swoole são as corrotinas: escreva código sequencial no estilo bloqueante, que o ambiente de execução agenda de forma cooperativa. Coroutine\run() abre um contexto de corrotina; go() inicia uma nova corrotina. Cada corrotina tem sua própria pilha, como uma fibra, mas o Swoole as agenda automaticamente nos pontos de E/S.
<?php
use Swoole\Coroutine as Co;
Co\run(function () {
go(function () { Co::sleep(1); echo "A done\n"; });
go(function () { Co::sleep(1); echo "B done\n"; });
// Both sleep concurrently -> total ~1s, not 2s
});Funções bloqueantes interceptadas
A mágica que torna as corrotinas práticas: os ganchos do ambiente de execução. O Swoole reescreve de forma transparente chamadas bloqueantes — PDO, Redis, curl, sleep, file_get_contents — em versões não bloqueantes compatíveis com corrotinas. Seu $pdo->query() comum cede o controle à corrotina em vez de congelar o trabalhador.
<?php
use Swoole\Runtime;
use Swoole\Coroutine as Co;
Runtime::enableCoroutine(SWOOLE_HOOK_ALL); // hook PDO, curl, sleep, etc.
Co\run(function () {
go(function () { sleep(1); echo "task 1\n"; }); // sleep() is now async!
go(function () { sleep(1); echo "task 2\n"; });
}); // finishes in ~1s because sleep was hookedE/S concorrente com WaitGroup
Para distribuir o trabalho e aguardar a conclusão, o Swoole oferece um WaitGroup (como o sync.WaitGroup do Go). Inicie corrotinas, chame add() para cada tarefa, done() ao concluir e wait() para bloquear até que todas terminem — em concorrência.
<?php
use Swoole\Coroutine as Co;
use Swoole\Coroutine\WaitGroup;
Co\run(function () {
$wg = new WaitGroup();
$results = [];
foreach (['eu', 'us', 'asia'] as $region) {
$wg->add();
go(function () use ($wg, $region, &$results) {
Co::sleep(0.5); // simulated API call
$results[$region] = "ok-$region";
$wg->done();
});
}
$wg->wait(); // all three ran in parallel (~0.5s)
var_dump($results);
});Canais para comunicação
As corrotinas se coordenam por meio de canais — filas tipadas e limitadas que suspendem o produtor quando estão cheias e o consumidor quando estão vazias. Trata-se de comunicação no estilo CSP, que evita completamente travas sobre estado compartilhado.
<?php
use Swoole\Coroutine as Co;
use Swoole\Coroutine\Channel;
Co\run(function () {
$chan = new Channel(2);
go(function () use ($chan) {
foreach (range(1, 3) as $n) $chan->push($n);
$chan->push(null); // sentinel
});
go(function () use ($chan) {
while (($v = $chan->pop()) !== null) echo "got $v\n";
});
});Agrupamento de conexões
Um servidor persistente não deve abrir uma conexão com o banco de dados por solicitação. O Swoole fornece agrupamentos de conexões seguros para corrotinas, para que os trabalhadores reutilizem um conjunto fixo de conexões entre milhares de corrotinas concorrentes, eliminando a constante abertura e fechamento de conexões.
<?php
use Swoole\Database\PDOConfig;
use Swoole\Database\PDOPool;
use Swoole\Coroutine as Co;
Co\run(function () {
$pool = new PDOPool((new PDOConfig())
->withHost('127.0.0.1')->withDbname('app')
->withUsername('u')->withPassword('p'), 8);
go(function () use ($pool) {
$pdo = $pool->get(); // borrow
$row = $pdo->query('SELECT NOW()')->fetch();
$pool->put($pdo); // return to pool
var_dump($row);
});
});Vazamentos de estado: a armadilha da memória persistente
Como o processo permanece ativo entre as solicitações, o estado global e estático persiste. Um cache estático que cresce sem limite, um objeto único que mantém dados específicos da solicitação ou uma transação de banco de dados vazada corromperá solicitações posteriores e esgotará a memória. Regras: evite dados específicos da solicitação em estáticos e objetos únicos, redefina o contexto a cada solicitação e defina max_request para que os trabalhadores sejam reciclados periodicamente.
<?php
$server = new Swoole\Http\Server('0.0.0.0', 9501);
$server->set([
'worker_num' => 8,
'max_request' => 10000, // recycle a worker after N requests to bound leaks
]);
// Never store $request data in a static property between requests!Contexto local da corrotina
Como um único trabalhador intercala muitas corrotinas, você não pode usar estáticos comuns para dados específicos da solicitação. O Swoole fornece a cada corrotina um contexto (Coroutine::getContext()) — um objeto cujo tempo de vida é o da corrotina, perfeito para o usuário atual, o ID da solicitação ou o identificador da transação.
<?php
use Swoole\Coroutine as Co;
Co\run(function () {
go(function () {
$ctx = Co::getContext();
$ctx['request_id'] = 'req-123';
// ... deep call chain can read Co::getContext()['request_id']
echo Co::getContext()['request_id'], PHP_EOL;
});
});Modelo de processos e trabalhadores de tarefas
O Swoole executa um processo principal (que gerencia as linhas de execução do ciclo de eventos), um gerenciador (que cria e monitora os trabalhadores), processos de trabalho (que executam seus manipuladores de solicitações e corrotinas) e processos de tarefas opcionais para trabalhos pesados, bloqueantes ou limitados pela CPU, descarregados por meio de $server->task(). Use processos de tarefas para processamento de imagens ou trabalhos longos limitados pela CPU, para que não interrompam as corrotinas das solicitações — assim você obtém concorrência e paralelismo.
Adiamento e temporizadores
O Swoole permite agendar trabalho para depois que a corrotina atual terminar com Coroutine::defer() — ideal para liberar recursos de agrupamentos de forma confiável, mesmo quando uma exceção é lançada. Os temporizadores de todo o servidor (Timer::tick) executam trabalhos periódicos, como a atualização do cache, dentro de um trabalhador, sem um agendador cron externo.
<?php
use Swoole\Coroutine as Co;
Co\run(function () {
go(function () {
$conn = 'borrowed-connection';
Co::defer(function () use ($conn) {
echo "released $conn\n"; // runs when coroutine exits, even on error
});
echo "using $conn\n";
});
});Verificação rápida
Por que você deve evitar armazenar dados da solicitação em propriedades estáticas em um servidor Swoole?
Recapitulação
O Swoole transforma o PHP em um servidor residente orientado por corrotinas:
- A aplicação é inicializada uma vez; um conjunto de trabalhadores atende às solicitações com corrotinas integradas (
Co\run/go()). - Os ganchos do ambiente de execução tornam chamadas comuns a PDO/curl/sleep não bloqueantes; WaitGroup e canais coordenam trabalhos concorrentes.
- Os agrupamentos de conexões reutilizam conexões com o banco de dados entre corrotinas.
- A memória persistente exige que você evite vazamentos de estado: use
Coroutine::getContext()para dados específicos da solicitação, definamax_requeste descarregue trabalhos pesados para processos de tarefas.
Perguntas Frequentes
A aula “Servidores de alto desempenho com Swoole” é grátis?
Sim — o texto completo de “Servidores de alto desempenho com Swoole” é grátis para ler aqui na web. Para praticá-la interativamente (um editor de código integrado e um tutor de IA 24/7) e desbloquear o restante do curso de PHP Academy, atualize para CoddyKit PRO. O curso de PHP Academy inclui 4 aulas no total.
O que vou aprender em “Servidores de alto desempenho com Swoole”?
Atenda milhares de conexões com o Swoole baseado em corrotinas. Você pratica PHP Academy com código prático que executa diretamente no navegador, e um tutor de IA 24/7 responde suas dúvidas enquanto trabalha na aula.
Preciso ter experiência prévia para começar PHP Academy?
Nenhuma experiência prévia é necessária. PHP Academy no CoddyKit é estruturado para alunos iniciantes até avançados, então você pode começar aqui ou desde o início e aprender no seu ritmo. Esta é a aula 4 de 4.
Quanto tempo leva a aula “Servidores de alto desempenho com Swoole”?
A maioria das aulas CoddyKit leva cerca de 5–10 minutos. Cada uma é compacta e interativa, então você faz progresso constante e retoma exatamente de onde parou entre web e app.
Posso escrever e executar código nesta aula de PHP Academy?
Sim. Cada aula de PHP Academy inclui um editor de código integrado, então você escreve e executa código real direto no navegador e recebe feedback de IA instantaneamente — nenhuma configuração local necessária.
Todas as aulas deste curso
- O modelo de concorrência do PHP
- Fibers do PHP 8.1
- Loops de eventos com ReactPHP
- Servidores de alto desempenho com Swoole