Swoole常见问题核心原因及解决方案:版本不匹配致段错误、JSON需手动解析、定时器仅主/Task进程可用、swoole_mysql已废弃须改用Swoole\Coroutine\MySQL。

swowole\_http\_server 启动就报错 Segmentation fault
不是代码写错了,大概率是 Swoole 版本和 PHP 版本不匹配,或者扩展没装对。Swoole 4.8+ 要求 PHP 7.4+,而 5.0+ 强制要求 PHP 8.0+;用 php --ri swoole 看输出里有没有 Version => 5.0.12 这类字样,再核对 php -v。常见坑是:CentOS 上用 Remi 源装了 PHP 8.1,但 pecl install swoole 默认编译进的是系统自带的 PHP 7.2 的扩展目录,结果 extension=swoole.so 加载时直接段错误。
- 确认 PHP 和 Swoole 主版本对齐:PHP 8.1 → Swoole 5.x,别混用 4.x
- 重装扩展时加
--with-php-config指向正确的配置:pecl install swoole --with-php-config=/usr/bin/php-config81 -
strace -e trace= mmap,mprotect,openat php server.php 2>&1 | grep -i swoole可快速定位加载哪个.so文件失败
swoole_http_server->on('request') 拿不到 POST JSON 数据
Swoole 默认不自动解析 application/json 请求体,$request->post 是空的,不是 bug,是设计如此。它只解析 application/x-www-form-urlencoded 和 multipart/form-data 两类。
- 手动读取原始 body:
$json = $request->rawContent(); $data = json_decode($json, true); - 注意
rawContent()只能调一次,多次调用返回空字符串 - 如果用了
swoole_http_server->set(['package_max_length' => 2 * 1024 * 1024]),确保上传 JSON 不超这个值,否则请求被直接丢弃,连onRequest都不会触发 - 别在
onRequest里做 heavy json_decode —— 大 JSON(>500KB)会阻塞协程,考虑用go(function () { ... })包一层异步解码(但注意内存逃逸)
swoole_timer_tick 和 swoole_timer_after 在 Worker 进程里失效
这两个函数只在主进程或 Task 进程中可用,Worker 进程默认禁用定时器——因为 Worker 是纯协程环境,底层用的是 co::sleep + 协程调度,不是信号或 epoll 定时器。直接调会返回 false,且无任何 warning。
Swoole 6.1.1 是一个专为 PHP 设计的高性能事件驱动并发网络引擎。作为稳定版,它修复了编译时对 zlib 依赖的缺失及 curl 模块的内存安全风险。该版本支持协程、多线程与多进程架构,内置 TCP/HTTP/WebSocket 服务器,能够显著提升 PHP 在微服务、实时通信等场景下的执行效率与并发能力。
- 想在 Worker 中实现周期逻辑,改用
co::sleep(1)循环 +while (true),但必须加if ($server->isShuttingDown()) break;避免进程无法优雅退出 - 若需精确到毫秒级、跨进程共享的定时任务(比如清理缓存),放到 Task 进程里用
swoole_timer_tick,再通过$server->task()触发 Worker 执行业务 -
swoole_timer_tick的回调函数不能是匿名函数(PHP 限制),必须是静态方法或全局函数,否则运行时报Fatal error: Uncaught Error: Function name must be a string
swoole_mysql 已废弃,现在该用什么替代?
从 Swoole 4.4 开始,swoole_mysql 就标记为 deprecated,5.0 彻底移除。它底层基于同步阻塞 socket,和协程模型冲突,容易卡死整个 Worker。现在统一走 swoole_co_mysql(即 Swoole\Coroutine\MySQL)。
- 连接方式变了:
$mysql = new Swoole\Coroutine\MySQL(); $mysql->connect([...]),不是new swoole_mysql() - 所有方法都变成协程安全的,但返回值结构不同:
$mysql->query()返回数组或false,不是资源句柄 - 别在
onReceive或onRequest里复用同一个$mysql实例 —— 协程间不共享连接,每个协程应有自己的连接,或用连接池管理 - 如果项目还在用旧版封装(比如某 ORM 的 swoole 插件),检查是否已适配
Swoole\Coroutine\MySQL,否则上线后查数据库全超时
Swoole 的“高频 API”不是调用次数多,而是踩坑密度高——同一行代码,在不同版本、不同进程模型、不同协程上下文里行为可能完全不同。最麻烦的往往不是不会写,而是不知道哪一行正在悄悄切换执行环境。

















