swoole中worker_num控制进程数而非线程数,cpu密集任务需用task_worker_num>0配合ontask回调实现隔离;协程非线程,无法利用多核,co::sleep()协程安全而sleep()会阻塞进程。

为什么 swoole_server->set() 里配了 worker_num 却没起作用?
因为 Swoole 默认用的是「多进程 + 协程」模型,worker_num 控制的是进程数,不是线程数;它和线程管理完全无关。想开线程,得切到 SWOOLE_PROCESS 模式并手动启用 task_worker_num 或用 coroutine::create() 启协程——但协程 ≠ 线程,别混淆。
常见错误现象:worker_num 设成 10,top 看到 10 个 PHP 进程,但每个进程里只跑一个主线程,CPU 利用率上不去,IO 密集任务卡住主线程。
-
enable_coroutine => true是默认开启的,不需要额外配,但它不等于开了多线程 - 真要利用多核做 CPU 密集型任务,必须用
task_worker_num > 0,且在onTask回调里写逻辑 -
thread_num这个配置项早在 Swoole 4.4 就被移除了,现在任何版本设它都无效
怎么让 CPU 密集任务不阻塞主事件循环?
靠 task_worker:它本质是独立子进程(非线程),但能隔离耗时操作。Swoole 不提供原生多线程执行环境,强行在 onReceive 里跑 sleep(5) 或密集计算,整个 Worker 进程就卡死。
使用场景:图像缩放、JSON 解析大文件、RSA 加解密、正则匹配超长文本。
- 必须在
swoole_server->set()中设置task_worker_num >= 1 - 用
$server->task($data)把任务投递过去,不能直接调函数 -
onTask回调里可以安全地用usleep()、shell_exec()、json_decode()等阻塞操作 - 注意:task 进程间不共享内存,
global、static变量每次都是新实例
swoole_process 能否替代线程?
能做隔离,但不是线程替代品。它启动的是独立子进程,通信靠 pipe 或 msgqueue,开销比线程大,且无法共享堆内存或引用变量。
本版升级功能:1、增加“系统参数设置”功能,可在线管理编辑全站数据库路径、备份路径,无须到程序代码下更改;2、改进后台管理员权限分配问题,严谨、完善、安全的根限分配细分到每个功能页面的列表查看权限、添加权限、编辑权限、删除权限都可以在线分配,确保系统在多用户管理下,安全稳定运行;3、更新优化数据库操作,在线备份、压缩、恢复数据库,管理登录日志;4、增加&am
参数差异:new swoole_process($function, $redirect_stdin_stdout, $pipe_type) —— 第三个参数 $pipe_type 决定是否创建管道,0 表示不创建,2 表示创建全双工 pipe,别传错。
- 适合长期运行的后台服务(如日志收集、心跳上报),不适合高频短任务
- 如果父进程 exit,子进程不会自动 kill,得自己监听
onFinish或用pcntl_signal处理 SIGCHLD - 不要在
swoole_process里再启动swoole_server,会触发 fork bomb
协程里用 go() 算不算“多线程”?
不算。协程是用户态调度,所有 go() 启动的协程都在同一个 OS 线程里跑,只是 IO 自动挂起/唤醒。并发高、延迟低,但 CPU 密集任务仍会占满单核。
性能影响:1000 个 go(function () { usleep(1000); }) 几乎不耗资源;但换成 for ($i = 0; $i ,整个 Worker 就卡死,其他请求全等。
- 判断是否该进 task:看有没有阻塞系统调用(
file_get_contents、curl_exec、pdo->query)或纯计算 -
co::sleep()是协程安全的,但sleep()会阻塞整个进程 - Swoole 5.x 开始支持
co::exec(),可异步执行 shell 命令,比task更轻量,但仅限命令行场景
真正难处理的是混合型任务:比如先 curl 拿数据,再做复杂计算。这时候得拆成两段,curl 用协程,计算扔 task,中间用 defer 或回调衔接——这点很容易被忽略,一不留神就写成同步阻塞链。









