task进程是同步阻塞的任务卸载机制,通过ipc将任务交由独立进程执行,不涉及异步io;适合不可协程化的操作,如调用非协程sdk、外部命令等。

Task进程不是异步IO,而是进程级任务卸载
很多人看到 task() 就默认它是“异步IO”,其实完全不是一回事。Swoole 的 Task 进程不涉及任何内核级的 IO 多路复用或事件通知机制,它只是把一段同步、阻塞的代码挪到另一个独立进程里跑,靠的是进程间通信(IPC),不是非阻塞系统调用。
典型误区是:以为在 onTask 里调用 curl_exec() 或 file_get_contents() 就算“异步IO”了——错。这些仍是同步阻塞操作,只是阻塞发生在 Task 进程里,不影响 Worker 进程收请求而已。
-
onTask中所有代码都是同步执行的,sleep(10)就真卡 10 秒,不会让出控制权 - 真正异步 IO 需要配合
swoole_coroutine::sleep()、co::http_client等协程 API,或者用swow/ext-uv等底层异步驱动 - Task 进程内部无法使用协程(除非显式启用协程支持并手动
Co\run(),但极不推荐)
什么时候该用Task,而不是协程异步IO
关键看任务性质:是否必须同步、是否含不可协程化的扩展、是否需强隔离。
比如发邮件用 PHPMailer + SMTP 扩展,该扩展不支持协程;又比如调用某个闭源 SDK,它内部用了 fread() + 循环轮询,也没法协程化——这种就只能扔进 Task 进程。
Swoole 6.1.1 是一个专为 PHP 设计的高性能事件驱动并发网络引擎。作为稳定版,它修复了编译时对 zlib 依赖的缺失及 curl 模块的内存安全风险。该版本支持协程、多线程与多进程架构,内置 TCP/HTTP/WebSocket 服务器,能够显著提升 PHP 在微服务、实时通信等场景下的执行效率与并发能力。
- ✅ 适合 Task:调用未协程化的第三方 SDK、生成 PDF(
wkhtmltopdf同步调用)、批量写大文件、exec('ffmpeg')等外部命令 - ✅ 适合协程异步 IO:HTTP 请求(
co::http_client)、Redis(co::redis)、MySQL(co::mysql)、读小文件(co::readFile) - ❌ 混用风险:在
onTask里再起协程(如go(function(){})),会导致进程状态混乱,Swoole 不保证行为
数据传递和序列化限制直接影响Task能否用好
Task 进程和 Worker 进程内存完全隔离,所有传参必须序列化。这不是性能优化建议,而是硬性约束。
常见翻车点:task() 传了一个 PDO 对象、Closure、资源句柄(如 fopen() 返回的 resource),运行时直接报 Serialization of 'PDO' is not allowed 或静默失败。
- 只允许传数组、字符串、数字、可序列化对象(且类定义在两个进程中都存在)
- 大于 8KB 的数据会临时落盘到
/tmp,若磁盘满或权限不对,task()投递直接返回 false - 不要在
onTask中依赖 Worker 进程里的全局变量、静态属性或单例实例——它们根本不存在
onFinish 回调不是实时的,也不保证顺序
onFinish 是由 Manager 进程转发给 Worker 的,中间经过至少一次 IPC,延迟不可忽略。尤其当并发高、task_worker_num 不足时,任务排队 + 回调积压很常见。
如果你在 Worker 中投递 100 个任务,然后立刻等 onFinish,别指望它们按投递顺序回来,也别假设 100ms 内全到——实际可能几百毫秒甚至更久。
- 回调触发时机取决于 Task 进程执行完并调用
finish(),不是“一完成就飞过去” - 多个 Worker 投递任务时,
onFinish可能被任意一个 Worker 接收到(取决于 Manager 调度),不能默认绑定到发起者 - 若需结果强关联,必须在投递数据里带上唯一
request_id,并在onFinish中自行匹配










