Swoole通过异步协程模型显著提升PHP性能,但需正确使用:HTTP服务QPS可提升5–10倍;必须用协程版MySQL/Redis客户端;避免同步I/O、全局变量共享及文件锁等问题。

是的,Swoole 对 PHP 架构的性能提升非常明显——但前提是用对了场景、避开了常见陷阱。它不是“装上就快”,而是把 PHP 从同步阻塞模型切换到异步协程模型,底层替换 I/O 调度方式。真实收益取决于你压测的是什么、怎么写代码、是否触发了 Swoole 的关键优化点。
HTTP 服务吞吐量翻 5–10 倍很常见
用 Swoole\Http\Server 替代 Apache / Nginx + PHP-FPM 后,在纯 API 场景(如 JSON 返回、无数据库)下,QPS 从 1k–3k 跳到 8k–15k 是常态。这不是理论值,而是压测 ab -n 100000 -c 1000 下实测结果。
- 根本原因是:PHP-FPM 每请求 fork 进程 + 加载全部代码 + 初始化环境;Swoole 复用常驻进程 + 协程轻量调度,避免重复开销
- 注意:如果每个请求都调
file_get_contents或curl_exec,不换成Swoole\Coroutine\Http\Client,性能几乎没提升——同步阻塞依然卡在 I/O 上 - 静态文件务必交给 Nginx 处理,别让 Swoole 的 HTTP Server 干这事,它不擅长
MySQL 查询必须用协程客户端,否则白忙活
直接用 mysqli 或 PDO 连 MySQL,在 Swoole 里会退化成同步阻塞,一个慢查询拖垮整个协程调度器。实测中,未改造前并发 200 就开始超时;改用 Swoole\Coroutine\Mysql 后,同样 SQL 并发 2000 仍稳定。
-
Swoole\Coroutine\Mysql是真正异步非阻塞的,连接复用、查询自动挂起、回调唤醒协程 - 不能混用:不要在协程里调
new mysqli(),也不要在协程外用Swoole\Coroutine\Mysql - 连接池要自己实现或用
co\mysql::connect()配合go+defer管理生命周期,否则容易连接泄漏
Redis 同理:必须用 Swoole\Coroutine\Redis
用 phpredis 扩展的 Redis 类,在 Swoole 协程环境里仍是同步阻塞。压测时你会发现 CPU 很低,但 QPS 卡在 300 左右——全在等 Redis 响应。
立即学习“PHP免费学习笔记(深入)”;
-
Swoole\Coroutine\Redis支持 pipeline、multi、订阅等,API 和 phpredis 高度兼容,迁移成本低 - 注意:
connect()是协程安全的,但setOption()等非标准方法不支持,别踩坑 - 连接数配置要合理:
max_connection过小会排队,过大可能打爆 Redis 服务端连接数限制
内存泄漏和协程隔离问题最易被忽略
很多人上线后发现内存持续上涨,或者不同请求间变量“串数据”,其实不是 Swoole 本身的问题,而是没理解协程的生命周期。
- 全局变量(
$GLOBALS、static属性、global声明)在协程间共享,不是线程安全的——要用Co::getUid()手动做上下文隔离,或改用chan/map等协程安全结构 -
__destruct在协程结束时不触发,对象不会立即释放,得靠 GC 周期回收;大对象建议显式unset - 日志写文件?别用
file_put_contents(..., FILE_APPEND),高并发下会锁文件;改用Swoole\Coroutine\Channel+ 单独日志协程批量写入
// 示例:协程安全的 Redis 使用(正确)
go(function () {
$redis = new Swoole\Coroutine\Redis();
$redis->connect('127.0.0.1', 6379);
$result = $redis->get('user:1001');
echo $result;
});
真正决定 Swoole 能否带来质变的,从来不是它多快,而是你有没有把阻塞操作全换成协程版、有没有守住协程的边界、有没有为常驻内存重新设计生命周期。这些地方一错,性能可能比 FPM 还差。











