swoole性能瓶颈主要在连接管理、内存复用、io hook缺失和worker配置失当;max_request仅在base模式生效,process+协程下被忽略;需配合onworkerstop清理、显式启用keep_alive连接池、禁用xdebug、合理设置worker_num与reactor_num。

直接说结论:Swoole性能瓶颈 rarely 出在协程本身,而集中在连接管理、内存复用、IO Hook缺失、Worker进程配置失当这四个硬伤上。调优不是堆参数,而是让每个环节匹配真实流量特征。
为什么 max_request 设成 3000 还是内存持续上涨?
max_request 只在同步阻塞型 Server(如 SWOOLE_BASE 模式)下生效;若你用的是 SWOOLE_PROCESS 模式且启用了协程,该参数实际被忽略——这是最常被误配的点。
- 检查当前模式:
var_dump($server->setting['reactor_num'], $server->setting['worker_num'], $server->setting['task_worker_num']);,再比对swoole_version()是否 ≥ 4.8.0(低版本有 bug 导致 max_request 失效) - 真正起作用的内存兜底机制是
max_request+onWorkerStop显式清理:在onWorkerStop回调里调用unset($GLOBALS['my_cache'])和Swoole\Timer::clearAll() - 别信“自动回收”:静态属性、
$_SERVER附加字段、PDO 长连接未close(),都会跨请求累积
协程 HTTP 客户端为啥每次请求都 TLS 握手?
根本原因是没启用连接复用,或复用逻辑被破坏。Swoole 协程客户端默认不自动复用连接,必须显式配置 + 手动维护生命周期。
Swoole 6.1.1 是一个专为 PHP 设计的高性能事件驱动并发网络引擎。作为稳定版,它修复了编译时对 zlib 依赖的缺失及 curl 模块的内存安全风险。该版本支持协程、多线程与多进程架构,内置 TCP/HTTP/WebSocket 服务器,能够显著提升 PHP 在微服务、实时通信等场景下的执行效率与并发能力。
- 创建客户端时必须设
set(['keep_alive' => true, 'timeout' => 5.0]),否则每次 new 都是新 socket - 不能在
onRequest里new Swoole\Coroutine\Http\Client后直接execute()—— 这样无法复用;应封装连接池,用Channel管理空闲实例 - 注意
ssl_host_name参数:若服务端是泛域名证书,但客户端请求用的是 IP 或非匹配域名,OpenSSL 会拒绝复用并重握手
onRequest 里 var_dump($_GET) 慢得像卡死?
这不是 PHP 解析慢,而是 var_dump 触发了 Xdebug 或 CLI 模式下的全量变量展开,尤其当 $_GET 被框架注入大量键值时,会递归扫描整个符号表。
- 生产环境务必禁用 Xdebug:
php -d xdebug.mode=off your_server.php,否则协程调度器会被阻塞 - 调试请改用轻量方式:
echo http_build_query($_GET), "\n";或print_r(array_keys($_GET), true) - 更隐蔽的问题:某些 Composer 包(如 monolog)在日志 handler 中隐式调用
var_dump,需检查error_log是否被重定向到STDERR并触发同步写入
为什么加了 16 个 worker_num,QPS 却不升反降?
Worker 进程数不是越多越好,超过物理核心数后,上下文切换开销和锁竞争会吃掉全部收益。Swoole 的 reactor 线程才是 IO 入口瓶颈,worker_num 应与之匹配。
- 合理公式:
worker_num ≈ CPU 核心数 × 1.5~2(仅适用于 CPU-bound 场景);IO-bound 场景反而建议worker_num = CPU 核心数 + 1 - 必须同时调大
reactor_num:默认是min(4, CPU核数),若并发连接超 1w,至少设为 8~12 - 检查是否误开了
dispatch_mode = 3(抢占式):它会让单个连接被多个 worker 抢占,引发数据错乱,QPS 下降是副作用
真正卡住性能的,往往不是协程数量或连接池大小,而是某个没关的调试钩子、一个没清的全局数组、或一次被忽略的 SSL 证书验证失败导致的协程挂起。调优要从 strace -p $(pgrep php) 和 swoole_memory_dump() 的输出里找真实信号,而不是靠猜参数。










