响应超时主因是worker_num不足或max_request非预期重启;worker_num应设为CPU核数×2起步,8核建议16起压测;需检查task_worker启用、系统backlog参数、Swoole版本兼容性及max_coroutine协程数是否匹配并发需求。

响应超时不是网络问题,大概率是 worker_num 不够或 max_request 触发了非预期重启,导致请求堆积或连接被丢弃。
worker_num 设置过低导致请求排队
当并发请求数远超 worker_num 时,Swoole 会把新请求暂存在 accept 队列(backlog),一旦队列满,内核直接丢弃 SYN 包——客户端表现为“连接超时”或“Connection refused”,而非应用层超时。
-
worker_num应设为swoole_cpu_num() * 2起步,8 核机器建议从 16 开始压测,而不是固定写死4或8 - 确认是否启用了
task_worker:耗时操作(如日志、邮件)必须扔进 task 进程,否则会卡住 worker,等同于减少可用 worker 数量 - 检查
net.core.somaxconn和net.core.netdev_max_backlog系统参数,若低于 4096,需同步调高,否则 backlog 限制早于 Swoole 生效
max_request 触发后无法接收新连接
这是 Hyperf + Swoole 组合中典型的“假死”现象:worker 进程达到 max_request 后重启,但新进程未正确继承监听 socket,端口虽在、netstat -tnlp 看得到,却不再 accept 新连接。
- 根本原因多见于 Swoole 4.8.12 以下版本与某些 Linux 内核的 epoll 兼容问题,升级到 Swoole 4.8.13+ 或 5.0.3+ 可修复
- 临时缓解:将
max_request从10000降至1000,并强制启用reload_async => true,避免主循环阻塞 - 务必禁用
max_request_grace(除非你明确理解其信号竞争风险),它在部分版本中反而加剧重启失败
协程资源耗尽引发隐式超时
即使 worker_num 和 max_request 都合理,max_coroutine 不足也会让新请求拿不到协程上下文,表现为随机 504 或协程调度器静默丢弃任务。
- 默认
max_coroutine是 3000,高并发下极易打满;生产环境应设为100000或更高,配合worker_num动态估算(例如 16 个 worker × 5000 协程 = 8w 并发能力) - 检查代码中是否存在未 await 的协程调用,比如漏掉
yield或co::sleep(),会导致协程泄漏,实际可用数持续下降 - 用
Coroutine::stats()在监控接口中暴露当前协程总数和峰值,比单纯看 CPU 更早发现瓶颈
真正卡住响应的,往往不是单个配置项,而是 worker_num、max_request、max_coroutine 三者之间的比例失衡,以及 Swoole 版本对进程重启逻辑的实现差异。上线前务必用 wrk 或 hey 对单机做阶梯压测,观察 ss -s 中 tw(TIME_WAIT)和 inuse(已分配 socket)的变化趋势——这才是超时问题最真实的水位计。



















