worker_num并非越高越好,8核机器设16较安全,超32需压测与内存监控;IO密集型可设CPU核数×2,CPU密集型宜保守设为核数或加1–2个。

worker_num 不是设得越高越好,8 核机器配 16 个 worker 还算安全;超过 32 就得看压测数据和内存水位,否则容易触发 OOM 或调度抖动。
worker_num 设置多少才合理
它本质是 CPU 密集型任务的并行上限,不是并发连接数的放大器。Swoole 的每个 worker_num 进程独占内存(含加载的类、扩展、协程栈),设为 64 在大项目里可能直接吃掉 2–3GB 内存。
- IO 密集型服务(如 LLM 网关、API 聚合)可设为
swoole_cpu_num() * 2,比如 8 核设 16 - CPU 密集型(如图像处理、同步计算)必须保守,建议
swoole_cpu_num()或再加 1–2 个 - 真实瓶颈常不在 CPU,而在 Redis 同步调用、未超时的 cURL、或阻塞式日志写入——这些会让 worker 卡住,再多进程也白搭
- 改完必须执行
ps aux | grep php确认实际进程数,systemd 或 supervisor 可能拦截 reload 导致配置未生效
task_worker_num 和 worker_num 的配比关系
task 进程专干耗时活(模型推理、邮件发送、大文件转码),但它和 worker 之间靠 IPC 通信,task_worker_num 过高会加剧队列积压、IPC 超时甚至丢任务。
- 推荐上限是
worker_num * 2,但生产环境更常见的是worker_num * 0.5~worker_num * 1 - 必须搭配
task_max_request(防内存泄漏)和task_tmpdir(确保 tmpfs 可写) - 若用 msgqueue 模式,要监控
swoole_server->stats()中的tasking_num和task_wait_queue_len,持续 >500ms 平均等待或积压量破task_worker_num × 100就该扩容
max_coroutine 不是“开越多越香”
它控制单个 worker 内可并发调度的协程上限。设太大,一旦大量协程卡在 IO 等待或死循环里,调度器会吃光内存;设太小,流式响应(如 LLM token 流)直接卡住。
- 新项目起步用默认值:
max_coroutine=3000,coroutine_stack_size=256K - 压测时盯紧
swoole_get_status()返回的coroutine_peak_num,接近上限就说明协程密度已到临界点 - 频繁报
coroutine stack overflow,优先查是否在协程里用了sleep()、usleep()或未加超时的curl_exec(),而不是盲目调大栈尺寸 - PHP 8.1+ 可加
ZEND_SIGNAL=0环境变量,降低栈消耗,适合高密度协程场景
reload_async 开关不生效的三个硬性条件
这个参数让热更新不阻塞新请求,但不是设了就自动起效。
- 必须 Swoole 版本 ≥ 4.8.13,旧版有竞态 bug
- 必须关闭
daemonize=true,否则主进程无法响应SIGUSR1;若要用守护模式,得靠 systemd 的ReloadSignal=SIGUSR1配合 -
onWorkerStart里不能有阻塞操作,比如没设 timeout 的数据库连接池初始化失败、或未 catch 的扩展加载异常
真正难调的从来不是参数数字,而是每个 worker_num 背后绑定的 CPU 缓存亲和性、每个 task_worker_num 对应的 IPC 队列深度、以及每个 max_coroutine 实际承载的流式响应压力——这些没法靠文档抄,得靠 swoole_server->stats() 和 ps aux 实时看。



















