TrueAsync Server

(PHP 8.6+, true_async_server 0.6+)

TrueAsync Server 是一个原生 PHP 扩展,它直接在 PHP 进程内部运行一个高性能的 HTTP 服务器。 无需独立的守护进程,无需反向代理,也无需 FastCGI 桥接。

开箱即用地支持在同一个 TCP 端口上同时承载 HTTP/1.1 和 HTTP/2。协议选择通过 ALPN 协商(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 为 PHP 语言带来了真正的协程、非阻塞 I/O 和连接池。要在生产负载中兑现这一潜力, 就需要一个原生就为这种模型设计的服务器:一个常驻进程,内置 event-loop,每个请求获得自己的协程, 调度器在每次 I/O 等待时在它们之间切换。

TrueAsync Server 正是这样的服务器。协程和网络之间没有任何中间层: listener、协议解析器、请求分发器和处理程序都生活在同一进程、同一 event-loop 中。 数据库连接通过 Async\Pool 复用,opcache 在请求之间保持热态,冷启动开销只在 start() 时付一次。

功能特性

状态功能详情
HTTP/1.1完整符合 RFC 9112,支持 keep-alive、pipelining(基于 llhttp,与 Node.js 使用同一个解析器)
HTTP/2多路复用、server push(libnghttp2 ≥ 1.57,为 CVE-2023-44487 设置最低版本)
HTTP/3 / QUIC基于 libngtcp2 + libnghttp3 的 UDP 传输,OpenSSL 3.5 QUIC TLS API
TLS 1.2 / 1.3OpenSSL 3.x,ALPN 协商,禁用弱密码套件
压缩gzip(zlib-ng / zlib)、Brotli、zstd:覆盖响应压缩与所有协议下的入站请求体解压
Multipart / 文件上传流式零拷贝解析器
BackpressureCoDel(RFC 8289),高负载下自适应地暂停 accept
流式读取请求体通过 HttpRequest::readBody() 可选启用;上传无需把整个请求体保留在内存里
sendFile直接从处理程序高效地把磁盘文件发出去
内置 worker poolsetWorkers(N):通过 Async\ThreadPool + SO_REUSEPORT 启用 N 个线程
Per-request scope每个处理程序运行在自己的 scope 中;Async\request_context() 提供贯穿整个请求协程树的共享上下文
原生协程与 TrueAsync 深度集成:处理程序中任何阻塞 I/O 都只会挂起协程,而不是线程
零拷贝热路径上的内存分配最小化
📋WebSocketRFC 6455,支持从 HTTP/1.1 和 HTTP/2 升级
📋SSEServer-Sent Events
📋gRPC基于 HTTP/2,支持 unary 和 streaming

架构:单线程 event loop

NGINXEnvoyNode.js 以及 Rust Tokio/hyper 是同一种模型。

一个线程从 accept 到 send 全程拥有连接与请求。 没有 accept 线程到 worker 线程之间的传递,没有锁,也没有它们之间的上下文切换。 单个 event-loop 接受连接、从套接字读字节、解析 HTTP、将请求分发到处理程序、写出响应, 全程不离开当前线程。

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

非阻塞 I/O 由 libuv 反应器(通过 TrueAsync)实现。当协程需要等待文件、数据库 或下一个 WebSocket 帧时,它把控制权交还给 event-loop,event-loop 立刻拾起下一个就绪事件。 线程绝不会空转在 read()/recv() 上。

横向扩展到多核时使用 multi-worker 模式,通过 setWorkers(N): 内置的 Async\ThreadPool 会启动 N 个 OS 线程,每个线程拥有独立的 event-loop, 然后由内核(Linux/BSD)通过 SO_REUSEPORT 在它们之间分发入站连接。 没有共享状态,没有全局锁。

从哪里开始

  • 快速开始:5 分钟完成安装和最小示例
  • 配置:listeners、workers、TLS、超时、body streaming、bootloader
  • 压缩:gzip / brotli / zstd、协商、BREACH
  • 静态文件与 sendFileStaticHandler、预压缩 sidecar、Range
  • 流式传输:请求体流式读取与响应体流式发送
  • 多工作进程setWorkers(N)、bootloader、per-request scope
  • 示例:JSON-API、静态文件、fan-out、multipart 上传
  • 架构:内部细节

API 参考

替代方案

FrankenPHP 是基于 Caddy/Go 的独立可嵌入服务器,PHP 在其中作为 worker。 当你需要 Caddy 的功能(自动 Let's Encrypt、通过 Caddyfile 配置)或者要集成到已有的 Caddy 基础设施时, 它会很方便。TrueAsync Server 则是不依赖 Go runtime 的原生替代方案:服务器直接生活在 PHP 进程内。