协程池适合高并发io密集型任务,本质是单线程内复用协程上下文,切换开销极低;但无法利用多核且无进程隔离,崩溃可能影响同线程其他协程,需配合多进程模型(如swoole的worker_num设为cpu核心数)才能充分发挥性能。

协程池适合高并发 IO 密集型任务
协程池本质是单线程内复用协程上下文,适用于大量短生命周期、频繁阻塞在 IO(如 HTTP 请求、Redis 查询、MySQL 查询)的场景。它不创建新线程或进程,所有协程共享同一个事件循环和内存空间,切换开销极低。
常见错误现象:Co::create() 或 go() 启动成千上万个协程却没配 Runtime::enableCoroutine(),导致 file_get_contents、PDO 等仍为同步阻塞,实际串行执行;或者误以为协程能自动并行,结果 CPU 利用率始终卡在 100% 单核。
- 必须调用
Runtime::enableCoroutine()才能让标准 PHP IO 函数进入协程调度 - 协程池无进程隔离,一个协程崩溃(如未捕获异常)可能影响同一线程内其他协程
- 无法利用多核:4 核机器上,仅靠协程池最多压满 1 个 CPU,QPS 再高也受限于单核吞吐
- 典型用例:爬虫并发抓取 1000 个 URL、API 网关批量调用下游服务、IM 消息广播
进程池适合 CPU 密集型或需强隔离的任务
进程池通过 Swoole\Process\Pool 或手动 new Swoole\Process 创建多个独立子进程,每个进程有自己完整的内存空间和 PHP 解释器实例。它天然支持多核,且进程间故障不互相影响。
常见错误现象:在进程内反复 require 同一文件但未做 opcache_reset() 或未禁用 opcache 共享,导致不同进程读到过期类定义;或子进程意外退出后未监听 onWorkerExit 做回收,造成僵尸进程堆积。
Swoole 6.1.1 是一个专为 PHP 设计的高性能事件驱动并发网络引擎。作为稳定版,它修复了编译时对 zlib 依赖的缺失及 curl 模块的内存安全风险。该版本支持协程、多线程与多进程架构,内置 TCP/HTTP/WebSocket 服务器,能够显著提升 PHP 在微服务、实时通信等场景下的执行效率与并发能力。
- 每个进程启动开销大(fork + 初始化 PHP 环境),不适合每秒数千次的轻量任务
- 进程间通信需显式使用管道、消息队列或
Swoole\Table,不能直接共享变量 - 适合图像处理、PDF 生成、加密解密、大批量数据计算等 CPU 绑定型操作
- 也用于兜底场景:比如某个协程因扩展 bug 崩溃,可把高危逻辑移到独立进程里运行
混合使用才是生产环境常见做法
纯协程池扛不住 CPU 压力,纯进程池扛不住海量连接。Swoole 官方推荐的是「多进程 + 每进程内协程池」模型,即由 Manager 进程管理多个 Worker 进程,每个 Worker 内再用 go() 启动数百协程处理请求。
性能实测中,5000 次百度请求在 4 核机器上:Process 方式耗时约 9.6 秒(QPS 520),而纯协程方式耗时仅约 1.2 秒(QPS ≈ 4166)——但注意,后者是在单核跑满前提下达成的,若不配合 worker_num 设置多进程,就浪费了其余 3 个核。
-
worker_num应设为 CPU 核心数(或略高),让每个 Worker 进程承载一组协程 - 避免在协程里调用
sleep()、usleep()等非协程化函数,它们会阻塞整个 Worker 进程 - 数据库连接不要复用:协程间不能共享
PDO实例,必须每个协程新建或从协程安全的连接池获取
协程池无法替代进程池的关键限制
最常被忽略的一点:协程无法脱离其所在进程的生命周期。一旦 Worker 进程因 OOM、段错误或扩展 crash 而退出,该进程内所有协程瞬间消失,且不会触发任何协程级的 finally 或析构逻辑。
而进程池中的子进程崩溃,Manager 进程可立即拉起新进程,业务层甚至感知不到中断(只要上游有重试)。这也是为什么支付回调、订单生成等关键路径,即便用了协程,仍建议把核心写库逻辑下沉到 task 进程或独立进程执行。
- 协程没有信号处理能力,
pcntl_signal在协程中不可靠 - 扩展兼容性差:不是所有 PHP 扩展都支持协程钩子,比如某些 C 扩展的阻塞调用会直接卡死整个 Worker
- 内存泄漏风险更高:协程堆栈长期驻留,若闭包引用了大对象又未及时 unset,容易累积 OOM










