0Pricing
PHP Academy · Lección

Servidores de alto rendimiento con Swoole

Gestione miles de conexiones con Swoole basado en coroutines.

Servidores de alto rendimiento con Swoole es una lección gratuita de PHP Academy en CoddyKit. Esta es la lección 4 de 4. Puedes leer la lección completa abajo gratuitamente — luego la practicas en el navegador con un editor de código integrado y un tutor de IA 24/7. Forma parte de la ruta de aprendizaje de PHP Academy, y tu progreso se sincroniza en la web y la app de CoddyKit. El curso de PHP Academy incluye 4 lecciones en total.

Qué es Swoole

Swoole (y su bifurcación OpenSwoole) es una extensión de C que convierte PHP en un entorno de ejecución de alto rendimiento, basado en corrutinas y orientado a eventos. En lugar de que PHP-FPM cree un proceso por solicitud, un servidor Swoole inicia su aplicación una sola vez y la mantiene residente en memoria, atendiendo solicitudes desde un grupo de workers de larga duración con corrutinas integradas. El resultado: aumentos del rendimiento de un orden de magnitud y concurrencia nativa dentro de una sola solicitud.

El servidor HTTP persistente

El ejemplo clásico: un servidor HTTP completo en un script. Escucha, distribuye cada solicitud a un worker y nunca vuelve a iniciar el framework. Tenga en cuenta que esto requiere ext-swoole; no se ejecuta en PHP CLI estándar.

<?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();

Corrutinas, no callbacks

La función estrella de Swoole son las corrutinas: escriba código secuencial con estilo bloqueante, mientras el entorno de ejecución lo programa de forma cooperativa. Coroutine\run() abre un contexto de corrutina; go() inicia una nueva corrutina. Cada corrutina tiene su propia pila, como un Fiber, pero Swoole las programa automáticamente en los puntos 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
});

Funciones bloqueantes interceptadas

La magia que hace ergonómicas las corrutinas son los hooks del tiempo de ejecución. Swoole reescribe de forma transparente las llamadas bloqueantes —PDO, Redis, curl, sleep, file_get_contents— como versiones no bloqueantes compatibles con corrutinas. Su habitual $pdo->query() cede el control de la corrutina en lugar de congelar el worker.

<?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 hooked

E/S concurrente con WaitGroup

Para distribuir el trabajo y esperar a que termine, Swoole ofrece un WaitGroup (como sync.WaitGroup de Go). Inicie corrutinas, use add() por tarea, done() al finalizar y wait() para bloquearse hasta que todas terminen, de forma concurrente.

<?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);
});

Canales de comunicación

Las corrutinas se coordinan mediante Channels: colas tipadas y limitadas que suspenden al productor cuando están llenas y al consumidor cuando están vacías. Se trata de mensajería al estilo CSP, que evita por completo los bloqueos sobre el estado compartido.

<?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";
    });
});

Pools de conexiones

Un servidor persistente no debería abrir una conexión a la base de datos por solicitud. Swoole proporciona pools de conexiones seguros para corrutinas, de modo que los workers reutilizan un conjunto fijo de conexiones entre miles de corrutinas simultáneas y eliminan la creación y destrucción continua de conexiones.

<?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);
    });
});

Fugas de estado: la trampa de la memoria persistente

Como el proceso permanece activo entre solicitudes, el estado global y estático persiste. Una caché estática que crece sin límite, un singleton que conserva datos específicos de una solicitud o una transacción de base de datos no liberada corromperán las solicitudes posteriores y agotarán la memoria. Reglas: evite guardar datos propios de una solicitud en estáticos o singletons, restablezca el contexto en cada solicitud y establezca max_request para reciclar periódicamente los workers.

<?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 de la corrutina

Dado que un mismo worker intercala muchas corrutinas, no puede usar estáticos normales para almacenar datos propios de una solicitud. Swoole proporciona a cada corrutina un contexto (Coroutine::getContext()): un objeto cuyo ciclo de vida coincide con el de la corrutina, perfecto para el usuario actual, el ID de solicitud o el controlador de una transacción.

<?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 procesos y workers de tareas

Swoole ejecuta un proceso maestro (gestiona los hilos del bucle de eventos), un administrador (inicia y supervisa los workers), procesos worker (ejecutan sus controladores de solicitudes y corrutinas) y workers de tareas opcionales para trabajos pesados, bloqueantes o intensivos en CPU, delegados mediante $server->task(). Use workers de tareas para el procesamiento de imágenes o trabajos prolongados de CPU, de modo que no ralenticen las corrutinas de las solicitudes y pueda obtener tanto concurrencia como paralelismo.

Defer y temporizadores

Swoole le permite programar trabajo después de que termine la corrutina actual mediante Coroutine::defer(), lo que resulta ideal para liberar recursos del pool de forma fiable incluso si se lanza una excepción. Los temporizadores para todo el servidor (Timer::tick) ejecutan tareas periódicas, como actualizar la caché, dentro de un worker sin necesidad de un 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";
    });
});

Comprobación rápida

¿Por qué debe evitar guardar datos de una solicitud en propiedades estáticas en un servidor Swoole?

Resumen

Swoole convierte PHP en un servidor residente controlado por corrutinas:

  • La aplicación se inicia una sola vez; un grupo de workers atiende las solicitudes con corrutinas integradas (Co\run/go()).
  • Los hooks del tiempo de ejecución hacen que PDO, curl y sleep normales no sean bloqueantes; WaitGroup y Channels coordinan el trabajo concurrente.
  • Los pools de conexiones reutilizan las conexiones a la base de datos entre corrutinas.
  • La memoria persistente exige evitar las fugas de estado: use Coroutine::getContext() para los datos propios de cada solicitud, establezca max_request y delegue el trabajo pesado a los workers de tareas.

Preguntas frecuentes

¿La lección «Servidores de alto rendimiento con Swoole» es gratis?

Sí — el texto completo de «Servidores de alto rendimiento con Swoole» es gratis para leer aquí en la web. Para practicarla de forma interactiva (editor de código integrado y tutor de IA 24/7) y desbloquear el resto del curso de PHP Academy, actualiza a CoddyKit PRO. El curso de PHP Academy incluye 4 lecciones en total.

¿Qué aprenderé en «Servidores de alto rendimiento con Swoole»?

Gestione miles de conexiones con Swoole basado en coroutines. Practicas PHP Academy con código real que ejecutas directamente en el navegador, y un tutor de IA 24/7 responde tus preguntas mientras trabajas en la lección.

¿Necesito experiencia previa para empezar PHP Academy?

No se requiere experiencia previa. PHP Academy en CoddyKit está estructurado para principiantes hasta estudiantes avanzados, así que puedes empezar aquí o desde el inicio y avanzar a tu ritmo. Esta es la lección 4 de 4.

¿Cuánto tiempo toma la lección «Servidores de alto rendimiento con Swoole»?

La mayoría de las lecciones de CoddyKit toman alrededor de 5–10 minutos. Cada una es compacta e interactiva, así que avanzas constantemente y retomas exactamente por donde dejaste en la web y la app.

¿Puedo escribir y ejecutar código en esta lección de PHP Academy?

Sí. Cada lección de PHP Academy incluye un editor de código integrado, así que escribes y ejecutas código real directamente en tu navegador y obtienes retroalimentación instantánea de IA — sin configuración local necesaria.

Todas las lecciones de este curso

  1. El modelo de concurrencia de PHP
  2. Fibers de PHP 8.1
  3. Bucles de eventos con ReactPHP
  4. Servidores de alto rendimiento con Swoole
← Volver a PHP Academy