TrueAsync Server

(PHP 8.6+, true_async_server 0.6+)

TrueAsync Server — нативне PHP-розширення, яке запускає продуктивний HTTP-сервер прямо всередині PHP-процесу. Без окремого daemon, без reverse-proxy, без FastCGI-моста.

З коробки підтримує HTTP/1.1 і HTTP/2 на одному TCP-порту. Вибір протоколу відбувається через ALPN-negotiation (для TLS) або HTTP Upgrade. HTTP/3 працює на тому самому UDP-порту (QUIC) і анонсується клієнтам через заголовок Alt-Svc.

WebSocket, SSE і gRPC уже спроєктовані під ту саму модель одного listener'а з детектом протоколу, але поки ще в роботі (див. Можливості).

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

Навіщо

Мета сервера — розкрити потенціал конкурентних застосунків на PHP.

TrueAsync дав мові справжні корутини, неблокуючий I/O і пули з'єднань. Щоб цей потенціал реалізувався під production-навантаженням, потрібен сервер, який від початку спроєктований під цю модель: довгоживучий процес з event-loop'ом, де кожен запит отримує власну корутину, а планувальник перемикається між ними на кожному I/O-очікуванні.

TrueAsync Server і є такий сервер. Жодного прошарку між корутинами і мережею: listener, парсер протоколу, диспетчер запитів і обробник живуть в одному процесі і в одному event-loop'і. З'єднання з БД переуживаються через Async\Pool, opcache гарячий між запитами, cold-start платиться один раз — на start().

Можливості

СтатусМожливістьДеталі
HTTP/1.1Повна відповідність RFC 9112, keep-alive, pipelining (через llhttp, той самий парсер, що в Node.js)
HTTP/2Мультиплексування, server push (libnghttp2 ≥ 1.57, floor для CVE-2023-44487)
HTTP/3 / QUICUDP-транспорт на libngtcp2 + libnghttp3, OpenSSL 3.5 QUIC TLS API
TLS 1.2 / 1.3OpenSSL 3.x, ALPN negotiation, слабкі шифри вимкнено
Стисненняgzip (zlib-ng / zlib), Brotli, zstd: на відповідь і декодинг вхідних тіл у всіх протоколах
Multipart / file uploadsStreaming zero-copy парсер
BackpressureCoDel (RFC 8289), адаптивна пауза accept під навантаженням
Streaming request bodyОпціонально через HttpRequest::readBody(); uploads без утримання тіла в RAM
sendFileЕфективна віддача файлів з диска прямо з обробника
Built-in worker poolsetWorkers(N): N потоків через Async\ThreadPool + SO_REUSEPORT
Per-request scopeКожен обробник у власному scope; Async\request_context() дає спільний контекст по всьому дереву корутин запиту
Native coroutinesГлибока інтеграція з TrueAsync: будь-який блокуючий I/O в обробнику паркує корутину, а не потік
Zero-copyМінімум алокацій на гарячому шляху
📋WebSocketRFC 6455, Upgrade з HTTP/1.1 і HTTP/2
📋SSEServer-Sent Events
📋gRPCповерх HTTP/2, unary і streaming

Архітектура: single-threaded event loop

Та сама модель, що в NGINX, Envoy, Node.js і Rust Tokio/hyper.

Один потік володіє і з'єднанням, і запитом від accept до send. Немає передачі між accept-thread і worker-thread, немає блокувань, немає перемикань контексту між ними. Один event-loop приймає з'єднання, читає байти з сокета, парсить HTTP, диспетчеризує запит в обробник і пише відповідь, не залишаючи потік.

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

Неблокуючий I/O робить libuv-реактор (через TrueAsync). Коли корутині треба зачекати файл, БД або наступний WebSocket-кадр, вона передає управління event-loop, який одразу підхоплює наступну готову подію. Потік ніколи не простоює в read()/recv().

Для масштабування за ядрами піднімається multi-worker через setWorkers(N): вбудований Async\ThreadPool піднімає N OS-потоків, кожен з власним незалежним event-loop, а SO_REUSEPORT (Linux/BSD) дає ядру розподіляти вхідні з'єднання між ними. Жодного shared state, жодних глобальних блокувань.

Звідки почати

Довідник API

Альтернативи

FrankenPHP — окремий вбудований сервер на Caddy/Go, в якому PHP виступає воркером. Зручний, коли потрібні фічі Caddy (автоматичний Let's Encrypt, конфіг через Caddyfile) або інтеграція в наявну Caddy-інфраструктуру. TrueAsync Server — нативна альтернатива без Go-runtime: сервер живе прямо в процесі PHP.