## 一、背景:传统 PHP-FPM 的痛点
- 模型:**一请求一进程/线程**,处理完销毁状态。
- 优点:隔离性强,错误/内存泄漏不互相影响,调试简单。
- 缺点:I/O 等待时 CPU 空转(文章例子:3 个串行调用 650ms,其实全在等网络/DB)。
- 旧解法:Swoole / ReactPHP / AMPHP —— 都是**用户态扩展或框架**,要换写法或换运行时。
## 二、True Async 是什么
- 目标:把**协程 + 非阻塞 I/O**写进 Zend 内核,让原生函数“在协程里自动非阻塞,在协程外原样同步”。
- 定位:**内核级并发底座**,不是新框架;当前可玩的是 `true-async/true-async` 扩展(v0.9.3,2026-08-13)。
- 模型:**单进程单线程协作式多任务**(I/O 等点让出 CPU,不是 OS 线程并行;CPU 重活靠 `spawn_thread()` 走线程池)。
## 三、最核心卖点:没有“函数染色”
| 对比项 | JS / Python async/await | True Async |
|---|---|---|
| 关键字 | 必须 `async fn` | **无 `async` 关键字** |
| 调用链污染 | 下游全要改 async | 普通同步函数直接丢进 `spawn()` 就能并发 |
| 底层手段 | 语法层 | 改 Zend 内核 + I/O 层 + Socket/DB 层 |
> 文章原话:“普通同步代码无需修改就能直接在协程中运行。”
## 四、最小可用 API(记住这 4 个就够了)
- `spawn(callable)` → 起一个可挂起/恢复的协程
- `await($coroutine)` → 等单个协程出结果
- `Scope` → 管一组协程生命周期,一个挂全部取消
- 安全取消 → 取消时不出半成品数据
典型写法(文章示例精简):
```php
$page = spawn(fn() => file_get_contents($url));
$rows = spawn(fn() => $pdo->query($sql)->fetchAll());
$stats = spawn(fn() => file_get_contents($api));
[$html, $data, $meta] = await_all_or_fail([$page, $rows, $stats], timeout(2000));
```
串行 650ms → 并发取最慢值 **300ms**,代码还是同步味。
## 五、70+ 原生函数自动非阻塞(重点记范围)
**协程内非阻塞,协程外零变化:**
- 网络:cURL、stream、socket、`gethostbyname`
- 文件:`fopen/fread/file_put_contents/flock`(flock 类系统调用转线程池)
- DB:PDO MySQL/PgSQL、MySQLi、原生 PG
- 进程:`proc_open/exec/shell_exec`
- 计时:`sleep/usleep`,每协程独立 ob 缓冲
**暂不支持:** `opendir/mkdir`、Oracle/SQLite PDO(官方低优先级)。
## 六、不止协程:顺手送的周边
- PDO 连接池
- 纯 C 写的 HTTP/1.1~3 服务器(可免反代)
- `spawn_thread()` 做 CPU 密集并行
- Symfony 适配器 + `true-async/ide-helper`(PHPStan/PhpStorm 补全)
## 七、路线图与“别被标题骗了”的真相
文章给的时间表:
- PHP 8.6 Alpha 1:2026-07-02(实际已发到 Alpha 2)
- Beta 1:2026-08-13(**已到软特性冻结**)
- GA:2026-11-19
**关键校正(看官方 RFC 才知道的):**
1. True Async 作者先提了更底层的 **Concurrency Support in PHP Engine** RFC(只埋钩子,不加 `spawn/await` 这几个符号),PoC PR 已存在,内部反馈偏正面但**讨论大概率推到 8.6 发布后**。
2. 真正的 `spawn/await/Scope` 是**建立在钩子上的扩展层 RFC**,当前以扩展形态存在。
3. 所以“PHP 8.6 原生带 True Async”≠ 已合并,**8.6 内核最多先合“并发钩子”,也可能全部推到 8.7**。生产环境现在别碰 v0.9.3。
## 八、学习后该记住的 3 句话
1. PHP 并发从“换 Swoole 运行时”走向“内核给钩子 + 扩展调度”,写法尽量不染色彩。
2. 它解决的是 **I/O bound 等待重叠**,不是把 PHP 变成 Go 那种多线程并行。
3. 2026-11 之前:当技术方向看、Docker 里跑 demo 学 API;**别信“8.6 必带”**,以 php.net 的 8.6 NEWS 文件为准。
要不要我把上面示例改成“Laravel 控制器里接 Symfony 适配器”的最小可跑片段,方便你本地 Docker 试 v0.9.3?