worker进程专用于快速i/o,阻塞操作必须交由显式配置的task进程处理;协程可替代部分task场景,但cpu密集或不可协程化任务仍需task。

Worker 进程不能执行耗时操作,Task 进程专为阻塞任务而设;两者不是“能不能用”的问题,而是“该不该用”的分工问题。
Worker 进程只适合快速响应的 I/O 操作
Worker 进程本质是事件循环中的 PHP 执行单元,它接收 Reactor 线程转发来的请求(如 HTTP、WebSocket),然后同步执行回调函数。一旦你在 onReceive 或 onRequest 里写 sleep(3)、file_get_contents(未协程化)、或遍历百万数组,整个 Worker 就卡死,其他请求排队等待。
常见错误现象:
- 接口响应时间忽高忽低,监控显示 CPU 不高但延迟飙升
- 并发稍高就出现连接超时,
netstat查看大量 ESTABLISHED 但无响应 -
worker_num设得再大也没用——因为瓶颈不在并发数,而在单个 Worker 被阻塞
适用场景:
- 读取 Redis 缓存(已启用
swoole_redis协程客户端) - 拼装 JSON 响应、校验 Token、路由分发
- 调用
task()投递任务,自己立刻返回
Task 进程必须显式启用并配置 IPC 模式
Task 进程默认不启动,你得在 serv->set() 中明确设置 task_worker_num(比如 4),否则调用 task() 会直接报错:SWOOLE_ERR_TASK_UNAVAILABLE。
底层通信方式影响行为:
- 默认
SW_TASK_IPC_UNIXSOCK(Unix Socket):可靠、低延迟,但进程间需同机部署 -
SW_TASK_IPC_MSGQUEUE:支持跨机器?不支持——仍是本地系统消息队列,只是容错性略高 - 别乱设
task_ipc_mode,除非你真理解msgget()权限和IPC_PRIVATE的含义
注意:taskwait() 是同步阻塞调用,它会让当前 Worker 进程暂停,直到 Task 返回结果——这跟“异步”名字矛盾,但它确实用于需要结果的场景(比如生成订单号后立刻写 DB)。别把它当 task() 用。
Swoole 6.1.1 是一个专为 PHP 设计的高性能事件驱动并发网络引擎。作为稳定版,它修复了编译时对 zlib 依赖的缺失及 curl 模块的内存安全风险。该版本支持协程、多线程与多进程架构,内置 TCP/HTTP/WebSocket 服务器,能够显著提升 PHP 在微服务、实时通信等场景下的执行效率与并发能力。
onTask 和 onFinish 的参数与生命周期很关键
onTask 回调接收两个参数:$serv(Server 实例)和 $task(数组),其中 $task['data'] 是你投递的内容,$task['id'] 是任务唯一 ID(可用于去重或日志追踪)。
onFinish 同样接收 $serv 和 $result,但要注意:$result 只能是标量或可序列化数组,不能传资源、闭包、PDO 对象等——Swoole 底层用 Unix Socket 发送数据,靠 serialize() 封包。
容易踩的坑:
- 在
onTask里忘了return $result或调用$serv->finish($result),Worker 就永远等不到回调 - 投递了 1000 个任务,但
task_worker_num只有 2,第 3 个开始排队——没超时机制,可能卡住几分钟 - Task 进程崩溃后不会自动重建,Manager 进程只管拉起新 Worker,Task 异常需靠日志 +
onTaskError捕获
协程正在替代 Task 进程,但不是现在就能删掉
Swoole 5.x 已全面支持协程,很多过去必须丢进 Task 的操作(如 MySQL 查询、HTTP 请求)现在用 co\MySQL 或 Swoole\Coroutine\Http\Client 就能在 Worker 内非阻塞完成。但这不等于 Task 过时了。
真正无法协程化的任务仍需 Task:
- 调用第三方扩展(如图像处理
imagick、PDF 生成tcpdf) - 执行 shell 命令(
exec、shell_exec) - 处理大文件解析(CSV 导入、日志归档)
别为了“用新不用旧”强行把 CPU 密集型逻辑塞进协程——那只是把阻塞从进程级转移到协程调度器里,照样拖垮 QPS。










