processpool适合长期驻留、稳定并发的cli场景,如redis队列消费、日志归档、定时同步、音视频转码调度;不适合web请求中临时启用或短平快任务。

ProcessPool 适合处理哪些具体任务
ProcessPool 不是万能的多进程方案,它只在明确需要「长期驻留、稳定并发、资源可控」的场景下才真正发挥价值。比如你有一组固定数量的后台 worker,持续从 Redis 队列消费任务,或监听某个 Unix socket 接收协程服务转发来的计算请求——这类任务不需要频繁启停、不依赖 FPM 生命周期、也不走 HTTP 请求链路。
常见错误现象是:在 Web 请求中(如 Laravel 或 ThinkPHP 的控制器里)临时 new 一个 ProcessPool 去跑个耗时任务,结果发现进程没起来、或者刚 start 就退出。这是因为 PHP-FPM 模式下主进程会在响应结束时回收所有子进程,ProcessPool 根本没机会进入 wait 状态。
- 必须运行在 CLI 模式下(
php your_pool_script.php),不能嵌入 Web SAPI - 适合长周期任务:队列消费者、日志归档、定时数据同步、图片/视频转码调度
- 不适合短平快的一次性任务:这种场景用
swoole_process+ 管道更轻量 - 若需对外提供服务接口,应配合
CoServer或HttpServer使用,由其接收请求后投递给 Pool 中的 worker
WorkerStart 回调里为什么必须写 while(true)
因为 ProcessPool 的设计逻辑是:每个 worker 进程启动后,执行完 WorkerStart 回调就退出;而 Manager 进程会立刻拉起一个新进程补位——这会导致 CPU 空转、PID 泄漏、连接反复重建。
所以 WorkerStart 本质是一个「初始化钩子」,不是「任务执行体」。真正干活的循环必须写在里面,且要能持续响应,否则进程池就退化成“创建即死”的玩具。
Swoole 6.1.1 是一个专为 PHP 设计的高性能事件驱动并发网络引擎。作为稳定版,它修复了编译时对 zlib 依赖的缺失及 curl 模块的内存安全风险。该版本支持协程、多线程与多进程架构,内置 TCP/HTTP/WebSocket 服务器,能够显著提升 PHP 在微服务、实时通信等场景下的执行效率与并发能力。
- 阻塞型任务(如
$redis->brpop())可直接写在 while 循环内,天然防退出 - 协程模式下要用
Co::sleep()或Co::waitEvent()替代sleep(),否则会阻塞整个进程 - 如果用了
ipc_type != SWOOLE_IPC_NONE(比如SWOOLE_IPC_UNIXSOCK),则WorkerStart可省略循环,改由onMessage触发任务处理
enable_coroutine=true 时的通信限制
开启协程支持会让 worker 内部可以自由使用 Co::sleep、Co::httpGet 等,但代价是彻底禁用 onMessage 回调——因为底层协程调度器与消息队列事件循环无法共存。
这意味着:一旦设了 enable_coroutine => true,你就只能靠轮询(如 brpop)、信号(Process::signal)、或外部推送(如通过 CoSocket 主动 connect 到 worker 监听端口)来驱动任务,不能再用 $pool->write() 这类 IPC 方式下发指令。
- 推荐搭配
SWOOLE_IPC_UNIXSOCK+ 协程 client,worker 监听 socket,主进程或协程服务端主动 connect 发送任务 - 不要混用
enable_coroutine和SWOOLE_IPC_MSGQUEUE,会报错或静默失效 - 协程模式下 Redis 必须用
CoRedis,原生Redis扩展会阻塞整个 worker
detach() 不是重启,而是“换人不换岗”
ProcessPool::detach() 的作用常被误解为“优雅重启”,其实它只是让当前 worker 主动退出,同时 Manager 进程立即 fork 一个新进程顶上,保持总数不变。旧进程不再接受新任务,但已开始的任务不会被中断——是否完成取决于你代码里怎么写。
这个机制适合做 worker 自我更新、内存泄漏兜底、或按运行时长强制轮换,但它不解决任务排队、负载均衡、或跨进程状态同步问题。
- 调用
$pool->detach()后,原进程仍会继续执行完当前循环体,然后退出 - 新进程的
$workerId可能复用旧值(比如 #2 退出后新进程还是 #2),不能靠 ID 做状态标识 - 若在 detach 前打开了文件、数据库连接或 Redis 实例,需手动 close,否则可能堆积句柄
WorkerStop,Manager 也感知不到——这种静默故障得靠外部健康检查或超时 watchdog 来捕获。










