TrueAsync Server

(PHP 8.6+, true_async_server 0.6+)

TrueAsync Server es una extensión PHP nativa que ejecuta un servidor HTTP de alto rendimiento directamente dentro del proceso PHP. Sin daemon separado, sin proxy inverso, sin puente FastCGI.

De serie soporta HTTP/1.1 y HTTP/2 en el mismo puerto TCP. La elección del protocolo se realiza mediante negociación ALPN (sobre TLS) o HTTP Upgrade. HTTP/3 funciona en el mismo puerto UDP (QUIC) y se anuncia a los clientes mediante la cabecera Alt-Svc.

WebSocket, SSE y gRPC ya están diseñados para el mismo modelo de un único listener con detección de protocolo, pero todavía están en desarrollo (véase Roadmap).

php
use TrueAsync\HttpServer;
use TrueAsync\HttpServerConfig;

$server = new HttpServer(
    (new HttpServerConfig())
        ->addListener('0.0.0.0', 8080)
        ->setWorkers(4)
);

$server->addHttpHandler(function ($request, $response) {
    $response->setStatusCode(200)->setBody('Hello, World!');
});

$server->start();

Por qué

El objetivo del servidor es desplegar todo el potencial de las aplicaciones concurrentes en PHP.

TrueAsync dotó al lenguaje de auténticas corrutinas, E/S no bloqueante y pools de conexiones. Para que ese potencial se traduzca en carga de producción hace falta un servidor diseñado desde el principio para este modelo: un proceso de larga duración con event-loop, donde cada solicitud recibe su propia corrutina y el planificador alterna entre ellas en cada espera de E/S.

TrueAsync Server es exactamente eso. Ninguna capa intermedia entre las corrutinas y la red: el listener, el analizador de protocolo, el despachador de solicitudes y el manejador viven en el mismo proceso y en el mismo event-loop. Las conexiones a la base de datos se reutilizan a través de Async\Pool, opcache se mantiene caliente entre solicitudes, el cold-start se paga una sola vez, en start().

Capacidades

EstadoCaracterísticaDetalles
HTTP/1.1Conformidad completa con RFC 9112, keep-alive, pipelining (mediante llhttp, el mismo analizador que Node.js)
HTTP/2Multiplexación, server push (libnghttp2 ≥ 1.57, mínimo por CVE-2023-44487)
HTTP/3 / QUICTransporte UDP sobre libngtcp2 + libnghttp3, API QUIC TLS de OpenSSL 3.5
TLS 1.2 / 1.3OpenSSL 3.x, negociación ALPN, cifrados débiles desactivados
Compresióngzip (zlib-ng / zlib), Brotli, zstd: tanto en la respuesta como decodificación de cuerpos entrantes en todos los protocolos
Multipart / subidas de archivosAnalizador zero-copy en streaming
ContrapresiónCoDel (RFC 8289), pausa adaptativa del accept bajo carga
Cuerpo de solicitud en streamingOpcional mediante HttpRequest::readBody(); subidas sin retener el cuerpo en RAM
sendFileEntrega eficiente de archivos del disco directamente desde el manejador
Pool de workers integradosetWorkers(N): N hilos vía Async\ThreadPool + SO_REUSEPORT
Scope por solicitudCada manejador en su propio scope; Async\request_context() ofrece un contexto compartido en todo el árbol de corrutinas de la solicitud
Corrutinas nativasIntegración profunda con TrueAsync: cualquier E/S bloqueante en el manejador suspende la corrutina, no el hilo
Zero-copyMínimo de asignaciones en la ruta crítica
📋WebSocketRFC 6455, Upgrade desde HTTP/1.1 y HTTP/2
📋SSEServer-Sent Events
📋gRPCsobre HTTP/2, unario y streaming

Arquitectura: event loop de un solo hilo

El mismo modelo que NGINX, Envoy, Node.js y Tokio/hyper en Rust.

Un único hilo posee tanto la conexión como la solicitud, desde accept hasta send. No hay traspaso entre accept-thread y worker-thread, no hay bloqueos, no hay cambios de contexto entre ellos. Un único event-loop acepta la conexión, lee bytes del socket, analiza HTTP, despacha la solicitud al manejador y escribe la respuesta sin abandonar el hilo.

       ┌─────────────────────────────────────────┐
       │              Event Loop Thread          │
       │                                         │
accept ─►  parse  ─►  dispatch  ─►  respond      │
       │     ▲                        │          │
       │     └──── coroutine yield ◄──┘          │
       └─────────────────────────────────────────┘

La E/S no bloqueante la proporciona el reactor libuv (a través de TrueAsync). Cuando una corrutina necesita esperar un archivo, una base de datos o el siguiente frame de WebSocket, cede el control al event-loop, que enseguida elige el siguiente evento listo. El hilo nunca queda inactivo en read()/recv().

Para escalar por núcleos se activa el modo multi-worker mediante setWorkers(N): el Async\ThreadPool integrado lanza N hilos del sistema operativo, cada uno con su propio event-loop independiente, y SO_REUSEPORT (Linux/BSD) deja que el kernel distribuya las conexiones entrantes entre ellos. Sin estado compartido, sin bloqueos globales.

Por dónde empezar

Referencia de API

Alternativas

FrankenPHP es un servidor embebible aparte basado en Caddy/Go, en el que PHP actúa como worker. Resulta práctico cuando se necesitan las funcionalidades de Caddy (Let's Encrypt automático, configuración mediante Caddyfile) o integración en una infraestructura Caddy ya existente. TrueAsync Server es la alternativa nativa sin runtime de Go: el servidor vive directamente en el proceso PHP.