协程需显式启用Hook且仅对被Hook函数生效;static变量跨请求是常驻进程特性,应改用局部变量或Swoole\Table隔离;max_request仅在标准同步Server模式下有效。

协程不是万能的,go() 一开就并发?错。不加 Swoole\Runtime::enableCoroutine(),大部分 IO 还是阻塞的;static 变量在 onRequest 里累加不停?对,这是常驻进程的必然行为,不是 bug;max_request 设了却没效果?大概率你用的是 Base 模式或纯异步 Server。
为什么 go() 启动的协程里调用 curl_exec() 依然卡住?
协程只对被 Hook 的函数生效,默认情况下原生 PHP 函数(如 curl_exec、file_get_contents、sleep)仍是同步阻塞的。
- 必须在 Server 启动前(如
onWorkerStart回调中)调用Swoole\Runtime::enableCoroutine(),且推荐传SWOOLE_HOOK_ALL - 禁用
opcache.enable_cli=1,否则 CLI 模式下 OPcache 可能干扰 Hook 行为 - 优先使用 Swoole 原生协程客户端:
Swoole\Coroutine\Http\Client替代curl_exec,Swoole\Coroutine::sleep()替代sleep() - 验证是否生效:在协程内执行
var_dump(Swoole\Coroutine::getCid()),非 0 即已进入协程环境;再测耗时操作是否并行
static $counter = 0 在 onRequest 中越加越大,怎么隔离请求状态?
因为 Worker 进程常驻,static 变量生命周期跨请求,这不是“变量没重置”,而是设计使然——你要的不是重置,而是隔离。
Swoole 6.1.1 是一个专为 PHP 设计的高性能事件驱动并发网络引擎。作为稳定版,它修复了编译时对 zlib 依赖的缺失及 curl 模块的内存安全风险。该版本支持协程、多线程与多进程架构,内置 TCP/HTTP/WebSocket 服务器,能够显著提升 PHP 在微服务、实时通信等场景下的执行效率与并发能力。
- 绝对不要用
global或static存储请求级数据,比如用户 ID、token、临时缓存 - 局部变量天然安全,所有业务逻辑尽量用函数参数 + 局部变量承载上下文
- 需跨协程共享?用
Swoole\Table(进程内共享、无锁、高效),别用Redis增加网络跳转 - 需跨进程共享?才考虑
Redis或Swoole\Atomic(计数类场景)
max_request 配了 1000 却发现 Worker 一直不重启?
这个参数只在特定模型下有效,盲目设置反而掩盖真实内存问题。
-
max_request仅对同步阻塞型 Server(如 HTTP、TCP)生效;纯异步 Server(如 WebSocket、UDP)和 Base 模式下完全无效 - 检查当前 Server 模式:
$server->setting['reactor_num'] > 0 && $server->setting['worker_num'] > 0是标准模式;若reactor_num === 0则是 Base 模式 - 更可靠的内存控制方式:结合
onWorkerStop清理全局对象 + 定期用memory_get_usage()打点 + 设置reload_async = true避免 reload 卡死 - 注意:TaskWorker 有独立的
max_task_request,不能混用
真正难的不是写对协程语法,而是在常驻进程中持续识别哪些变量该活、哪些该死、哪些根本不该出生——每次 go() 前,先想清楚这个协程结束后,它碰过的每个引用是否还挂在内存里。

















