ProcessPool 是为高并发任务调度设计的独立组件,非 swoole_process 的简单封装;其 worker_num 需据任务类型(CPU/IO/混合)合理设置,数据传递须通过共享内存或 dispatch,且无 onTask/onFinish 事件。

ProcessPool 不是“更高级的 swoole_process”,它是为高并发任务调度而生的独立组件,用错场景或配置不当,反而比手动 fork 更慢、更难 debug。
为什么不能直接用 swoole_process 替代 ProcessPool
很多人看到 swoole_process 能创建子进程,就以为自己能手写一个“轻量级进程池”。但实际运行中会立刻暴露问题:
- 没有统一的 Worker 生命周期管理:每个
swoole_process启动后完全自治,WorkerStart/WorkerStop事件无法触发,也无法监听异常退出 - 无任务分发机制:你得自己实现 IPC(比如用
msgqueue或pipe),还要处理阻塞、超时、丢失任务等边界情况 - 无法感知空闲状态:
swoole_process没有“忙/闲”标识,你没法知道哪个进程可以接新任务,只能轮询或随机投递,容易打满某几个进程 - 内存泄漏风险更高:每个子进程若持有全局资源(如未关闭的
PDO连接、未释放的SwooleTable引用),无法被池统一回收
换句话说:swoole_process 是螺丝刀,SwooleProcessPool 是整套电动装配线——后者封装了调度、保活、错误隔离和统计能力。
ProcessPool 的 worker_num 设置多少才合理
这不是看 CPU 核数拍脑袋决定的。关键要看你的任务类型和系统负载特征:
Swoole 6.1.1 是一个专为 PHP 设计的高性能事件驱动并发网络引擎。作为稳定版,它修复了编译时对 zlib 依赖的缺失及 curl 模块的内存安全风险。该版本支持协程、多线程与多进程架构,内置 TCP/HTTP/WebSocket 服务器,能够显著提升 PHP 在微服务、实时通信等场景下的执行效率与并发能力。
- 纯 CPU 密集型(如图像缩放、JSON 解析):建议设为
cpu_count - 1,留一个核给 Master 进程调度 - IO 密集型(如调用外部 HTTP 接口、读写 Redis):可设为
cpu_count * 2 ~ 4,因为协程会让 Worker 在等待时让出 CPU - 混合型任务:先用
top -Hp $(pgrep -f "ProcessPool")观察各 Worker 线程的 %CPU 占用率,若长期低于 30%,说明可适当增加数量;若频繁出现 95%+ 且响应延迟上升,则需减少或优化任务逻辑 - 必须避开常见陷阱:
worker_num = 0会导致$pool->start()静默失败;worker_num > 1024在默认 ulimit 下大概率触发Too many open files
如何在 ProcessPool 中安全传递数据给 Worker
ProcessPool 不支持直接传参给 Worker 回调函数,所有上下文都必须通过共享内存或进程间通信完成:
- 禁止使用闭包捕获变量:PHP 会尝试序列化闭包,导致
Serialization of 'Closure' is not allowed - 推荐用
SwooleSharedMemory或SwooleTable存储配置类数据(如数据库 DSN、限流阈值),Worker 启动后主动读取 - 任务数据必须走
$pool->dispatch()投递:它底层用的是 Unix Socket + 序列化,注意数据体积限制(默认 8MB,超限会抛Invalid argument) - 若需高频小数据传递(如计数器),优先用
SwooleAtomic,避免 IPC 开销;不要用文件或 Redis,那会把进程池变成“假并发”
示例中常看到 $pool->on('WorkerStart', function ($pool, $workerId) { ... }),这里的 $pool 对象本身不能存业务数据——它只是调度句柄,不是共享容器。
ProcessPool 的 onTask/onFinish 事件为何不触发
这是最常被忽略的配置点:SwooleProcessPool 默认不启用任务模式,它的事件模型和 SwooleServer 完全不同:
-
onTask和onFinish是SwooleServer(HTTP/TCP Server)的事件,ProcessPool 里根本不存在 - ProcessPool 只有
WorkerStart、WorkerStop、WorkerError三个核心事件 - 任务投递靠
$pool->dispatch($data),结果回调靠$pool->on('Message', function ($pool, $message) { ... }),注意这个$message是 Worker 主动调用$pool->sendMessage()发回来的,不是自动触发 - 如果误写成
$pool->on('Task', ...),代码不会报错,但回调永远不会执行——Swoole 会静默忽略未知事件名
真正容易混淆的点在于:很多文档把 SwooleServer 的 task_worker_num 和 ProcessPool 并列讲,但它们是两套完全独立的机制。混用会导致任务永远卡在队列里,查日志也看不到任何错误提示。

















