504超时主因是Swoole Worker协程阻塞或IO阻塞,非Nginx单方面问题;应设worker_num为CPU核心数1–2倍,启用enable_coroutine,合理配置max_connections(10240~20480)与max_request(如100000),并排查未await、阻塞IO等协程不安全操作。

504 超时在 Hyperf 里基本不是 Nginx 单方面的问题,而是 Swoole Worker 进程处理不过来、卡在协程调度或阻塞 IO 上,导致响应迟迟发不出去 —— Nginx 等不及就断了。
为什么调大 worker_num 反而让 504 更多
盲目增加 worker_num(比如设成 64)会加剧 CPU 上下文切换和内存争用,尤其当业务里混用阻塞操作(如 file_get_contents、同步 Redis)、协程未正确挂起、或 Task Worker 配置失衡时,Worker 进程会“假死”——看似在跑,实则协程卡住、无法分发新请求。
-
worker_num应设为 CPU 核心数的 1–2 倍(非 4 倍),例如 8 核机器建议worker_num => 8或12;超过此值收益递减,且易触发max_request频繁重启 - 必须确认
enable_coroutine => true已启用,否则所有协程 API(如Co::sleep、MySQLConnection::query)退化为同步阻塞 - 检查是否有自定义
Process或Task逻辑里写了while(true) { ... }但没加Coroutine::sleep(),这类代码会让对应进程 CPU 拉满、拖垮整个 Worker
max_connections 和 max_request 的真实作用边界
max_connections 是 Swoole 层单 Worker 最大并发 TCP 连接数(即同时在线长连接上限),而 max_request 是每个 Worker 进程最多处理多少个请求后自动重启 —— 它防的是内存泄漏,不是并发压力。
- 高并发下
max_connections建议设为10240~20480(需同步调大系统ulimit -n至 ≥30000),默认1024在万级 QPS 下直接成为瓶颈 -
max_request => 100000是合理值,但若发现 Worker 频繁重启且memory_get_usage()持续上涨,说明有对象未释放(如全局静态数组缓存未清理),此时调大max_request只是掩盖问题 - 别混淆
max_connections和 Nginx 的worker_connections:后者应 ≤ 前者 /worker_num,否则 Nginx 会因连不上足够 Worker 而堆积请求
如何验证当前并发能力是否真被 Worker 吃满
不能只看 top 里 CPU 使用率,得看 Swoole 自身指标和请求分发是否均匀。
- 用
swoole_server->stats()查看connection_count和accept_count差值:若差值长期 > 500,说明新连接进不来,可能是max_connections不足或内核net.core.somaxconn太小 - 检查
hyperf:server:status命令输出的request_count分布,如果某些 Worker 的数值远高于其他 Worker(比如 5 倍以上),说明负载不均,大概率是用了非协程安全的单例或共享资源锁冲突 - 开启 Swoole 日志:
'log_file' => '/tmp/swoole.log', 'log_level' => SWOOLE_LOG_WARNING,重点搜WARNING swFactoryProcess_manager_spawn_worker—— 出现这个日志代表 Worker 频繁崩溃重启
真正卡住 504 的,往往不是配置数字本身,而是协程环境里一个没 await 的数据库查询、一次没封装成 Co::readFile 的文件读取、或者 Task Worker 数量为 0 却把日志写入逻辑塞进了主 Worker —— 这些细节比调参更关键。


















