协程池大小需按任务类型精准设定:cpu型≤worker_num×2,io型可设worker_num×5~10但须匹配db/redis连接池容量,混合型优先按io占比估算并用co::stats()验证;max_wait_time宜设0.5~2.0秒,waiting_count持续>0时应先排查连接池耗尽而非盲目扩容。

单机协程池调优不是“把数字调大就行”,而是围绕真实瓶颈做精准控制——卡顿往往来自CPU挤占、连接争抢或上下文泄漏,而非协程数量不足。
协程池大小(max_coroutines)怎么设?
这个值要匹配任务类型,不是越大越好:
- CPU密集型任务(如加密、图像处理):建议 ≤ worker_num × 2,超过会引发线程级争抢,反而拖慢整体响应
- IO密集型任务(如DB查询、HTTP调用):可设为 worker_num × 5~10,但必须确保底层资源(DB/Redis连接池)能支撑
- 混合型任务:优先按IO占比估算,再用
co::stats()观察实际协程活跃数,长期低于设定值说明上限虚高
别忽略协程超时与等待队列
协程池满载后新协程会排队,但默认行为容易掩盖问题:
-
max_wait_time建议设为 0.5~2.0 秒:太短导致大量协程快速失败;太长会让请求堆积,影响接口SLA - 开启
enable_coroutine_pool_stats(Hyperf 3.2+),通过hyperf.coroutine_pool.waiting_count指标判断是否持续排队 - 若 waiting_count 长期 > 0,先检查是不是 DB 或 Redis 连接池已耗尽,而不是急着调大协程池
协程池绑定要明确,避免全局混用
HTTP 请求、异步队列、定时任务应使用独立协程池,防止相互干扰:
- HTTP 请求走默认协程池(
default),不建议动 - 异步队列消费者必须绑定专属池,例如:
PoolFactory::getInstance('queue_worker'),并在AsyncQueueConsumer中显式调用 - 定时任务或 WebSocket 推送建议单独建池,避免被高频HTTP请求挤占资源
配合连接池与上下文清理才真正见效
协程池只是调度层,真正卡住的常是它背后的东西:
- DB连接池
max_connections至少为 协程池大小 × 平均单次DB耗时(秒)× 1.5 - 每次
Context::set()必须配对Context::del(),尤其在中间件或装饰器里存了PDO或大数组 - 用
hyperf/memory-leak-detector扫描长期驻留的上下文键,比调参更能解决缓慢卡顿











