开启 enable_coroutine 后 worker_num 应设为 1~4,max_coroutine 控制并发;max_request 在协程模式下易误触发,v5.0+ 已弃用;task_worker_num=0 时 task() 必失败;启用 HTTP/2 必须设置 open_tcp_nodelay=true。

swowole_http_server->set() 里混用协程与同步配置
很多人在 set() 中同时开启 enable_coroutine 和保留 worker_num 为高值,结果请求卡死或 CPU 突增。这不是配置“没生效”,而是语义冲突:开启协程后,worker_num 实际只控制进程数,真正并发靠协程调度;此时再设成 32、64,反而导致大量空闲进程争抢事件循环。
-
enable_coroutine = true时,worker_num建议设为1~4(取决于 CPU 核心数),协程数由max_coroutine控制 -
enable_coroutine = false(传统多进程模式)才需要调高worker_num,但注意系统ulimit -n要足够,否则报Too many open files - 常见错误现象:
strace显示大量epoll_wait返回 0,top看到多个php进程 CPU 占用极低但响应延迟飙升
reload 时 max_request 触发时机被误解
max_request 不是“每个 worker 处理完 N 个请求就重启”,而是“每个 worker 子进程累计处理 N 个请求后退出”。如果启用了 enable_coroutine,且业务中存在长连接(如 WebSocket)、未释放的全局变量或 defer 未执行,实际请求数可能远低于设定值就触发回收——因为子进程生命周期被意外延长,而计数器仍在跑。
- 调试方法:在
onWorkerStart中记录getmypid(),配合日志观察哪些 PID 在处理第 1 个请求后就消失 - 若需稳定控制生命周期,建议关闭
max_request,改用信号(kill -USR1)+onWorkerStop清理资源后退出 - 注意兼容性:
max_request在 Swoole v5.0+ 对协程服务器默认失效,文档已标记为 deprecated
task_worker_num 设为 0 却仍收到 task 报错
当 task_worker_num = 0 时,Swoole 不会启动独立 task 进程,所有 $server->task() 调用会立即失败并抛出 Swoole\Error: task method is not available。这不是 bug,是设计限制:没有 task 进程,就无法投递异步任务。
- 若只是想同步执行逻辑,直接调用函数,别走
task()流程 - 若需异步但不想开额外进程,可用
Swoole\Coroutine\run()或go()启动协程,注意上下文隔离(如 DB 连接不能跨协程复用) - 容易踩的坑:在
onReceive中无条件调用$server->task(),没判断task_worker_num > 0,上线后批量报错
open_tcp_nodelay 和 open_http2_protocol 共存引发 handshake 失败
HTTP/2 握手依赖 TCP 层的精确帧边界,而 open_tcp_nodelay = false(默认)会启用 Nagle 算法,合并小包,破坏 HTTP/2 的帧结构,导致客户端收不到 SETTINGS 帧,连接卡在 h2: settings timeout。
- 启用 HTTP/2 必须显式设置
open_tcp_nodelay = true,否则 99% 概率握手失败 - 该参数对 HTTP/1.1 影响不大,但对 WebSocket 或自定义二进制协议,若消息体小且频次高,也建议打开
- 验证方式:用
curl -v --http2 https://your.domain,看是否返回* ALPN, offering h2和后续
Swoole 配置不是填完就跑,很多参数之间有隐含约束,尤其在协程模式下,旧版配置习惯会直接变成故障源。最麻烦的是错误不报在配置行,而是延迟到请求链路某处崩掉——得盯着 strace、tcpdump 和日志时间戳才能定位。









