要让Swoole协程既不卡死又不爆内存,必须精准控制max_coroutine和coroutine_stack_size参数:先通过swoole_get_status()和/proc/$(pidof php)/limits查瓶颈,确保max_coroutine×1.2≤fd上限;再按压测阶梯上调max_coroutine(每轮增幅≤2000,RSS超400MB即回退),直至coroutine_peak_num趋稳;栈大小调整前须排除sleep/cURL等阻塞调用,确需调大时配ZEND_SIGNAL=0,禁降128KB以下;最后用stats()和strace验证调度健康度。

要让Swoole协程既不卡死又不爆内存,必须精准控制max_coroutine和coroutine_stack_size这两个底层参数——设小了并发上不去,设大了进程直接OOM,而错误的栈尺寸还会引发静默崩溃。
确认当前协程水位与系统限制
先查真实瓶颈在哪:运行中执行swoole_get_status(),看返回数组里的coroutine_peak_num是否持续逼近max_coroutine值;同时用cat /proc/$(pidof php)/limits | grep "Max open files"确认当前进程允许的最大文件描述符数。
【max_coroutine × 1.2 必须 ≤ fd 上限】,否则新协程创建时会因无法分配socket句柄而报EMFILE错误,而不是内存不足提示。
这一步操作起来很简单,直接把命令复制粘贴进终端回车就行。
设置max_coroutine:按压测结果阶梯上调
第一步:从默认值3000起步,启动服务后模拟500并发请求,观察coroutine_peak_num是否稳定在2000以下;
第二步:若峰值常达2800+,将max_coroutine设为5000,再压测;
第三步:每次上调幅度不超过2000,且每轮压测必须监控RSS内存增长——单worker RSS超过400MB就立即回退;
Swoole 6.1.1 是一个专为 PHP 设计的高性能事件驱动并发网络引擎。作为稳定版,它修复了编译时对 zlib 依赖的缺失及 curl 模块的内存安全风险。该版本支持协程、多线程与多进程架构,内置 TCP/HTTP/WebSocket 服务器,能够显著提升 PHP 在微服务、实时通信等场景下的执行效率与并发能力。
第四步:当coroutine_peak_num不再随并发线性增长,而是趋近平台期,说明调度器已饱和,此时值即为安全上限。
注意:设为50000时仅协程栈就超400MB,别碰这个数字。
调整coroutine_stack_size:优先排查代码再动参数
方法一:遇到coroutine stack overflow报错,先检查协程内是否调用了sleep()、usleep()或未设timeout的cURL——这些阻塞调用会让协程挂起期间持续占用栈空间,不是栈太小,是逻辑写错了。
方法二:确认无阻塞调用后仍报栈溢出,可将coroutine_stack_size从默认256KB逐步增加到512KB,但必须同步启用ZEND_SIGNAL=0环境变量(PHP 8.1+有效),否则栈放大效果被信号处理机制抵消。
【栈尺寸调小风险极高】:降到128KB后,json_encode嵌套超20层或range(1, 50000)这类操作会直接触发Segmentation fault,而非抛异常。
验证协程调度健康度
在服务运行中执行swoole_server->stats(),重点盯tasking_num和connection_count比值——若前者长期>后者×0.1,说明大量协程卡在task_worker排队,不是max_coroutine不够,是task_worker_num配少了或任务没设task_max_request。
用strace -p $(pidof php) -e trace=epoll_wait观察事件循环是否频繁超时,超时周期<10ms就证明协程调度已失衡,需降低max_coroutine或优化业务逻辑。

















