【大厂真题】唯品会 PHP 工程师 Swoole 实战面试
Swoole在高并发电商场景下需注意协程写法、连接回收与状态隔离。onRequest中static变量因Worker常驻会递增累积,应使用SwooleTable或Redis隔离。SwooleRuntime::enableCoroutine()须在业务代码前全局调用一次。MySQL连接必须显式关闭或采用连接池。TaskWorker与Worker内存隔离,跨进程
Swoole 在唯品会这类高并发电商场景下,早已不是“能不能用”的问题,而是“怎么用才能不出事”的问题。真实压测和线上事故反复验证过:协程写法稍有偏差、连接没回收、状态没隔离,流量一上来就是内存暴涨或请求串号的灾难。
为什么 onRequest 里定义 static $counter 会越加越大
这不是 bug,而是 Swoole Worker 进程常驻的必然结果。PHP-FPM 每次请求都会重载脚本,static 变量自然重置;但 Swoole 的 onRequest 回调在同一个 Worker 进程内反复执行,static 存储的是进程级的生命周期数据。
- 现象:接口返回值从 1 → 2 → 3 … 持续递增,只有重启 Worker 才会归零。
- 本质:Worker 进程不销毁,
static变量就不会自动清空,也不受请求上下文约束。 - 正确做法:需要请求隔离的状态,必须用
SwooleTable(单机)或Redis(跨进程),例如$table->incr($key, 'count', 1)。 - 危险替代:用
$_SERVER或$GLOBALS存临时数据,同样会跨请求污染。
SwooleRuntime::enableCoroutine() 必须在哪儿调用
必须在所有业务代码执行前、且仅调用一次,通常放在 Server 启动入口最顶部。千万不能放在 onRequest 或协程函数内部。
- 错例:
go(function () { SwooleRuntime::enableCoroutine(); ... });—— 此时协程环境已存在,Hook 失效,curl_exec仍然阻塞。 - 对例:在
$server->start()前,全局作用域第一行写SwooleRuntime::enableCoroutine(true);。 - 参数影响:
true表示 Hook 所有支持的函数(包括file_get_contents、stream_socket_client等),但sleep()仍需换成SwooleCoroutine::sleep()。 - 兼容性注意:PHP 8.0+ 配合 Swoole 5.x 是当前唯品会线上的主流栈,低版本开启 Hook 可能触发 segfault。
MySQL 连接不 close 导致 Too many open files
协程 MySQL 客户端实例本身不会自动释放底层 socket,unset($client) 不等于关闭连接,必须显式调用 close()。
- 常见错误:用完
$db = new SwooleCoroutineMySQL(); $db->connect(...);后直接 return,没有$db->close()。 - 后果:每个协程持有一个未关闭连接,Worker 进程内连接数线性增长,最终触发系统级
EMFILE错误。 - 安全写法:用
try/finally包裹,确保无论是否异常都执行$db->close()。 - 更优方案:上连接池,预创建固定数量客户端,使用后
return到空闲队列,避免频繁connect()开销。
TaskWorker 投递任务后,onTask 里用了 global 变量会怎样
TaskWorker 是独立进程,与 Worker 进程内存完全隔离。global 变量在 TaskWorker 内是全新副本,修改它对 Worker 没有任何影响,但很容易让人误以为能共享状态。
- 典型误用:Worker 中
global $cache = [];,投递任务后在onTask里往$cache[]push 数据,期望 Worker 能读到 —— 实际读到的是空数组。 - 真正可用的跨进程通信方式只有:SwooleTable(需提前声明结构)、Redis、消息队列、文件(不推荐)。
- TaskWorker 适合干的事:发送邮件、生成报表、调用第三方 HTTP 接口等耗时且无需实时返回的阻塞操作。
- 别踩的坑:在
onTask里调用SwooleCoroutine相关函数(如go),TaskWorker 默认不启用协程环境,需手动用SwooleCoroutine::run()包裹。
协程不是魔法,它把调度权从操作系统交到了 PHP 扩展手上。你写的每行同步代码,背后都依赖 Hook 是否生效、资源是否及时释放、状态是否严格隔离——这些细节,在唯品会秒杀场景下,差毫厘就会失千里。


































