### [📌 PHP Fibers 协程扛高并发 API 网关?内存与吞吐量的真实基准](https://www.huociguo.com/article/213) **Published:** 2026-07-22T16:22:35 **Author:** 米了 **Excerpt:** PHP 8.1 引入的 Fibers 是有完整栈、可中断的函数,每个 Fiber 拥有自己的调用栈,可在任意嵌套深度挂起。这一底层原语让 Amp、ReactPHP 等框架得以构建协作式调度,但它本身并不等于”非阻塞 I/O”——在 Fibe PHP 8.1 引入的 Fibers 是有完整栈、可中断的函数,每个 Fiber 拥有自己的调用栈,可在任意嵌套深度挂起。这一底层原语让 Amp、ReactPHP 等框架得以构建协作式调度,**但它本身并不等于”非阻塞 I/O”**——在 Fiber 内调用 `sleep()`、`file_get_contents()`、同步 `PDO::query()` 仍会阻塞整个 PHP 进程。因此,评判 Fibers 在 API 网关中的表现,必须先厘清两个维度:**内存开销从哪来,吞吐量收益在什么条件下成立**。 ![](https://api.huociguo.com/wp-content/uploads/2026/07/PHP-Fibers-%E5%8D%8F%E7%A8%8B-API-%E7%BD%91%E5%85%B3%E5%9F%BA%E5%87%86%E6%B5%8B%E8%AF%95-2216b04a15-1.png "PHP-Fibers-协程-API-网关基准测试-2216b04a15-1") ## 内存开销:栈深度决定一切 每个 Fiber 维护独立的调用栈,内存占用随栈深度线性增长。社区基准显示:1000 个并发 Fiber 若各自持有深调用栈,虚拟内存预留相当可观;1k 个 Fiber 在 PHP 8.3 下约占用 76MB,PHP 8.5 动态栈优化后降至约 45MB。 > ⚠️ 关键认知:Fiber 的栈是”按需增长”的,但上下文切换本身仍有微秒级开销。无节制地 `new Fiber()` 而不加连接池、超时与并发上限控制,内存会迅速膨胀。 在 API 网关场景中,内存的主要消耗点并非 Fiber 对象本身,而是: - 每个请求持有的 DB 连接、HTTP 客户端句柄 - 调用栈深度(中间件链越长,单个 Fiber 栈越大) - 全局缓存未设 TTL 导致的堆积 ## 吞吐量:I/O 密集型才有显著收益 公开压测数据(Ubuntu 24.04、i7-12700K、OPcache+JIT)显示,在轻量 JSON 回显场景下: | | | | | --- | --- | --- | | 方案 | QPS | 内存/请求 | | 传统 PHP-FPM | ~1,200 | 8–12 MB | | PHP 8.5.7 原生协程(Fiber + 事件循环) | ~9,800 | 1–2 MB | | Swoole 5.0 协程 | 25,000–30,000 | 单进程 ~100MB/千并发 | **吞吐量提升的本质不是 Fiber 魔法,而是消除了两件事**:FPM 的进程创建/销毁开销、每次请求的数据库连接重建开销。Swoole 因在 C 层完成协程调度并提供完整的协程化客户端、连接池、Channel 等工业级组件,在极限 QPS 上仍领先纯 Fiber 方案。 Fiber 路线的真实定位是:**作为 Zend VM 级别的调度原语,配合 Revolt 事件循环**,将单进程并发能力从几百级拉到万级,但所有网络 I/O 必须走协程化驱动(`amphp/mysql`、`revolt/event-loop` 等)。 ## API 网关落地的四个硬约束 **1\. 阻塞调用零容忍** `sleep()`、`file_get_contents()`、同步 `PDO::query()` 会拖垮整个事件循环。必须替换为协程化客户端。 **2\. 并发数必须有上限** 1000 个并发 HTTP 请求无限制 fan-out,可能瞬间打满内存或压垮下游。网关层应加 `Worker` 数限制与信号量。 **3\. 全局状态是隐形雷区** Fiber 之间共享进程内存,静态属性、全局变量的读写在挂起点会产生竞态。网关的中间件上下文必须显式传递,禁用 `static` 缓存。 **4\. 异常必须逐 Fiber 捕获** 任何一个 Fiber 抛出未捕获异常,都会传导到 `->start()` 或 `->resume()` 的调用点;若调度器未做 `try/catch` 隔离,整个事件循环会崩溃。 ## 基准测试该怎么跑才客观 若要在团队内做 Fibers 网关的基准对比,建议锁定以下变量: - **硬件**:4 核 8GB 起步,记录 CPU 型号与内存 - **PHP 版本**:8.1+,开启 OPcache + JIT - **场景**:`/ping` 轻量回显、单 DB 查询、5 路外部 API 扇出 - **工具**:`hey` 或 `wrk`,并发 1000、持续 60s - **对照组**:PHP-FPM + cURL、Fiber + Revolt、Swoole 5.x - **观测指标**:QPS、P99 延迟、内存峰值、FD 数 只有固定上述条件,得出的 QPS 与内存数据才有横向可比性。**脱离测试环境的百分比提升都是营销话术**。 **结论很朴素**:Fibers 给 PHP 带来了真正的协作式并发原语,内存开销可控、I/O 密集型网关场景吞吐量可获数倍提升;但它不是”Swoole 替代品”,更不是”加了就快”的银弹。在 API 网关这种高并发、长调用链、强依赖外部服务的场景下,**Fiber + Revolt 事件循环 + 协程化客户端 + 连接池**才是可落地的组合,而内存与吞吐的基准数字,必须由团队在自己的硬件与业务画像下重新跑一遍。 **Categories:** PHP教程 ---