先查php -v、php-config --version和php-config --zts确认php主版本、小版本及zts状态,再对照swoole各版本readme或github releases中的php最低版本与zts要求匹配。

怎么确认当前 PHP 环境能装哪个 Swoole 版本
Swoole 的版本和 PHP 版本、编译模式(ZTS/NTS)、PHP 扩展 ABI 高度耦合。装错版本直接 php -m 看不到模块,甚至 php --version 报段错误。
- 先查 PHP 基础信息:
php -v(看主版本,如 8.1.27)、php-config --version(确认 minor 版本一致性)、php-config --zts(输出 1 表示启用了 ZTS,Swoole 5.x 起强制要求 ZTS) - 再看 ABI 兼容性:Swoole 每个 tag 下的
README.md或 GitHub Releases 页面会写明支持的 PHP 最小版本和是否 require ZTS;例如swoole-5.0.3要求 PHP ≥ 8.0 且必须 ZTS,而swoole-4.8.13仍支持 NTS 模式下的 PHP 7.4 - 不要只看 PHP 主版本号:PHP 8.0.0 和 8.0.28 的内部结构可能有微小差异,Swoole 发行包通常只针对某几个 patch 版本做过二进制兼容测试
用 pecl 安装时为什么总卡在 configure 或报 missing phpize
pecl install swoole 表面简单,实际依赖完整构建链。失败多数不是 Swoole 问题,而是本地环境缺关键组件。
- 必须确保已安装对应 PHP 版本的
php-dev(Debian/Ubuntu)或php-devel(CentOS/RHEL),否则phpize命令不存在,configure 直接退出 - 如果系统有多个 PHP 版本(如通过 asdf、brew、手动编译安装),
pecl可能调用错phpize:运行前先执行which phpize,确认它指向你期望的 PHP 安装路径下的phpize - Swoole 4.8+ 默认启用
--enable-openssl,若系统 OpenSSL 开发头文件缺失(如没装libssl-dev或openssl-devel),configure 会静默禁用 TLS 支持,后续Co\Http\Client无法访问 HTTPS 地址,但不会报错 - 编译阶段内存不足(尤其在 CI 或低配 VPS 上)会导致 gcc oom-kill,现象是 make 进程消失、无错误输出——加
MAKEFLAGS="-j1"限制并发可规避
源码编译后 php -m 不显示 swoole 或 extension_dir 路径不对
手动编译完 make install,只是把 swoole.so 放进某个目录,PHP 是否加载它,完全取决于 php.ini 配置。
- 先确认
swoole.so实际位置:find /usr -name "swoole.so" 2>/dev/null或看make install最后一行输出的路径(常见如/usr/lib/php/20210902/swoole.so) - 检查
php --ini输出的主配置文件路径,编辑对应php.ini,添加:extension=swoole.so
注意不是extension=/full/path/to/swoole.so—— PHP 会自动在extension_dir下查找,硬写绝对路径反而容易因路径变更失效 - 若不确定
extension_dir当前值,运行php -i | grep extension_dir,确保swoole.so确实放在那个目录下,否则要复制过去或改配置 - 加载失败时,
php -m不报错也不显示,但php -i | grep swoole为空;此时看php --ri swoole,若提示 “Extension 'swoole' not present”,说明没加载成功,优先检查 ini 文件是否被覆盖(如conf.d/下其他 ini 文件里重复写了extension=导致冲突)
升级 Swoole 后协程 MySQL 连接莫名超时或 close_wait 大量堆积
这不是 Bug,是 Swoole 4.8+ 对连接池和资源回收策略的实质性调整,旧代码不改就容易出问题。
-
Swoole\Coroutine\MySQL在 4.8.0 后默认启用connect_timeout和read_timeout(均为 0.5 秒),比之前宽松得多;如果业务 SQL 本身慢于这个阈值,就会被静默中断,日志里只看到mysql_query(): Connection lost类似提示 - 连接不再自动复用:以前一个协程里连续 query 多次会复用同个 socket,现在每个
query()都可能触发新连接(尤其在setDefer()模式下),导致短连接频发,服务端出现大量CLOSE_WAIT - 解决方法不是关 timeout,而是显式管理连接生命周期:
- 用
new Swoole\Coroutine\MySQL()创建实例后,手动调用$mysql->close(),不要依赖 GC 回收 - 高并发场景改用
Swoole\Runtime::enableCoroutine(true, SWOOLE_HOOK_ALL)+ 原生 PDO/MySQLi,更可控 - 确认
ulimit -n足够高(建议 ≥ 65535),否则连接数一多直接Too many open files
- 用
Swoole 版本切换真正难的从来不是编译,而是那些藏在默认行为变更里的“向后不兼容”——比如某个 flag 默认值翻转、某个函数返回结构微调、甚至只是日志级别变严格。上线前一定得用真实流量路径跑一遍压测,光看 php -m 出现了就不算完。










