swoole面试“基础题”实则考查常驻进程陷阱:global变量不重置因worker进程持续运行;协程需提前启用runtime::enablecoroutine()并hook;内存泄漏须主动清理静态变量而非依赖max_request。

别被“入门级”误导——Swoole 面试里所谓“基础题”,90% 考的是你有没有踩过常驻进程的坑,而不是会不会写 go()。
为什么 global $i = 0; 在 onRequest 里每次都不重置?
因为 Swoole Worker 进程不重启,PHP 脚本只加载一次,global 变量在内存里一直活着。这不是 bug,是常驻模型的必然结果。
- 现象:请求 A 执行
$i++后 $i 变成 1;请求 B 再来,$i 是 2,不是 0 - 根本原因:PHP-FPM 每次请求新建进程并销毁全部变量;Swoole 的 Worker 进程持续运行,
global、static、类静态属性、$_SERVER等全被复用 - 正确做法:状态必须显式隔离 —— 用
Swoole\Table存请求级数据,或用 Redis 做跨进程共享;千万别依赖全局变量存会话/计数/缓存
协程不生效?先查 Runtime::enableCoroutine() 是否启用
协程不是“写了 go() 就自动异步”,它依赖底层函数是否被 Hook。没开 Hook,sleep(1) 或 file_get_contents() 依然会阻塞整个 Worker。
Swoole 6.1.1 是一个专为 PHP 设计的高性能事件驱动并发网络引擎。作为稳定版,它修复了编译时对 zlib 依赖的缺失及 curl 模块的内存安全风险。该版本支持协程、多线程与多进程架构,内置 TCP/HTTP/WebSocket 服务器,能够显著提升 PHP 在微服务、实时通信等场景下的执行效率与并发能力。
- 常见错误:只调用了
go(),但漏掉Swoole\Runtime::enableCoroutine() - 推荐开启方式:
Swoole\Runtime::enableCoroutine(SWOOLE_HOOK_ALL)(开发期最省心) - 验证是否生效:在协程里执行
sleep(1),同时发两个请求 —— 若第二个请求卡住 1 秒才响应,说明 Hook 失败 - 注意:
SWOOLE_HOOK_ALL不能在onRequest回调里调用,必须在 Server 启动前(如new Swoole\Http\Server之后、start()之前)
Worker 进程内存越跑越高?max_request 不是万能解药
max_request 能强制 Worker 退出释放内存,但它治标不治本。如果每次请求都 new 对象却不 unset,或者往静态数组里无限制 push,再高的 max_request 也扛不住。
- 典型泄漏点:
static $cache = [];每次请求都$cache[$key] = $data;却不清理 -
max_request适合场景:同步阻塞型服务,且确认无长期持有资源(比如没开连接池、没注册全局回调) - 更稳妥的做法:在
onClose或业务结束时主动unset()连接相关对象;对大数组用array_splice()或重置为[];禁用opcache.enable_cli=1防 CLI 下字节码残留
真正难的从来不是语法,而是意识到:你写的不是“一次性的 PHP 脚本”,而是一个长期在线、共享内存、随时可能被多个协程并发访问的服务进程。变量生命周期、资源归属、连接复用——这些细节一旦忽略,线上就不是性能差一点,而是直接 OOM 或状态错乱。










