swoole脚本卡住主因是协程调度器失效,典型表现为子进程在禁用协程后仅运行sleep协程,导致coroutine_num长期为0或1,futex等待卡死;修复需启用父进程协程或子进程改用同步sleep。

脚本卡住不是代码写错了,而是 Swoole 运行环境或调用方式触发了底层调度机制失效——最常见的是协程上下文缺失、阻塞操作混入、或扩展加载不完整。
协程里调用 co::sleep() 却没调度器
这不是 co::sleep() 本身有问题,是它被扔进了一个没有协程调度器的进程里。比如在 swoole_async_set(['enable_coroutine' => false]) 后启动的子进程中直接 go(fn() => co::sleep(1)),整个进程就会挂起不动:协程睡了,但没人唤醒它。
- 用
php ./vendor/bin/swoole-tracker status查coroutine_num,长期为 0 或 1 就是调度器失活信号 -
strace -p [pid] -e trace=futex看是否卡在futex等待上 - 修复方式:要么在父进程启用协程(
swoole_async_set(['enable_coroutine' => true])),要么子进程彻底禁用协程后改用同步sleep(1)
数据库/HTTP 请求没设超时,协程永久阻塞
ThinkPHP 默认的 PDO 或 file_get_contents('https://...') 在协程环境里会锁死整个协程——它不交还控制权,调度器就无法切走,后续请求全堵住。
- MySQL 必须换
Swoole\Coroutine\MySQL,且配置'type' => 'mysql'(不是'pdo') -
Co\Http\Client必须显式设置['timeout' => 5],否则默认永不超时 - 避免在
__construct或全局初始化阶段执行任何 I/O 操作——协程还没启动,会直接报must be called in the coroutine
swoole.so 加载失败但无报错,CLI 和 Web 环境用错 php.ini
运行 php -m | grep swoole 没输出,不代表没编译成功,大概率是 CLI 用的 php.ini 和 Web(如 Nginx+PHP-FPM)用的根本不是同一个文件。
- 查 CLI 配置:
php --ini;查 Web 配置:建info.php输出phpinfo(),搜Loaded Configuration File - 两个环境都要加
extension=swoole,路径推荐写绝对路径:extension=/usr/lib/php/20220829/swoole.so - Ubuntu/Debian 上装过
php-swoole包?它自带的swoole.so可能和你自己编译的冲突,先apt remove php-swoole再试
OPcache 在 CLI 模式下开着,内存缓慢上涨像卡死
常驻进程跑几天后变慢、响应延迟,memory_get_usage(true) 显示内存持续上涨,但 valgrind 找不到泄漏——这很可能是 opcache.enable_cli=1 导致的:OPcache 缓存的函数表、常量在进程生命周期内永不释放。
- 确认配置:
php --ini找到加载的php.ini,检查是否有opcache.enable_cli=1 - 线上长进程必须设为
opcache.enable_cli=0,重启 PHP 进程生效 - 别信
top的 CPU 占用率:协程忙等(比如空循环或未超时的curl_exec)不会进内核态,top显示“空闲”,实际卡在 PHP 层
真正难排查的卡点,往往藏在“看起来没问题”的地方:比如你以为只是 sleep 一下,其实调度器早没了;你以为数据库连上了,其实用的还是阻塞式 PDO;你以为扩展加载了,其实 CLI 和 FPM 正在用两套配置打架。
php免费学习视频:立即使用
踏上前端学习之旅,开启通往精通之路!从前端基础到项目实战,循序渐进,一步一个脚印,迈向巅峰!











