hyperf异步队列消费者进程数需按cpu核数、任务类型动态调整:io型设为核数×1.5~2.5(≤12),cpu型设为核数×0.8~1.2并配concurrent.limit;processes=0则进程不启动;须同步扩容redis连接池至≥processes。

Hyperf异步队列消费者进程数(processes)设少了任务堆积、设多了资源争抢,必须结合服务器CPU核数、内存、任务类型和实际吞吐量动态调整,不能直接套用文档默认值1或拍脑袋填8。
确认当前配置位置与生效逻辑
消费者进程数由 config/autoload/async_queue.php 中的 'processes' => 1 控制,该配置仅在启用 Hyperf\AsyncQueue\Process\ConsumerProcess::class 时生效。若 processes 设为 0,整个消费者进程不会启动——这是服务上线后无任何消费日志的首要排查点。
执行 php bin/hyperf.php start 后,控制台必须出现 Process[AsyncQueueProcess] start 日志,否则说明配置未加载或进程数为 0。
按任务类型分档设定初始值
方法一:IO密集型任务(如发邮件、调第三方API、写日志)
这类任务大部分时间等待网络响应,单个进程利用率低,可适当提高并发度。
初始值 = CPU逻辑核数 × 1.5~2.5,但上限不超过 12;例如 4 核服务器,设 processes => 6 是安全起点。
方法二:CPU密集型任务(如图像缩放、报表计算、JSON解析大文件)
这类任务持续占用 CPU,进程过多会导致上下文切换开销剧增,反而降低吞吐。
初始值 = CPU逻辑核数 × 0.8~1.2,且必须同步开启 concurrent.limit 限流;例如 8 核服务器,设 processes => 8 + 'concurrent'=>['limit'=>4],避免单进程内多协程抢核。
【注意】 若任务中混用 sleep()、curl_exec()(未加超时)、PDO直连等阻塞调用,即使标为IO型,也会退化成CPU型行为,导致进程卡死——务必先清理阻塞代码再调参。
验证与压测三步法
第一步:观察真实进程数
启动服务后,立即执行 ps aux | grep 'AsyncQueueProcess' | wc -l,输出结果应等于配置的 processes 值。若少于该值,检查 Redis 连接池是否就绪、isEnable() 是否返回 true。
第二步:监控关键指标
在压测期间,每 30 秒采集一次:
① redis-cli llen queue(队列积压长度)
② task_wait_queue_len(Task Worker 等待队列长度,通过 hyperf:info 命令获取)
③ top -H -p $(pgrep -f 'AsyncQueueProcess') 查看各线程 CPU 占用是否均衡
第三步:动态调优阈值
当 queue 长度持续 > 50 且 task_wait_queue_len > 200 → 增加 processes 或提升 concurrent.limit;
当单个 Consumer 进程 CPU 占用长期 > 90% 且 queue 长度 processes,避免空转争抢。
【关键前提】 所有调优必须基于真实业务流量,禁止在本地开发环境用 sleep(1) 模拟任务——这种模拟无法反映网络延迟、锁竞争、序列化开销等真实瓶颈。
规避两个致命误配
误配一:把 processes 和 concurrent.limit 混为一谈
processes 是操作系统级子进程数量,每个进程独占内存和文件描述符;concurrent.limit 是单个进程内协程并发上限。两者叠加效果非线性:设 processes => 4 + concurrent.limit => 10 ≠ 40 并发,而是最多 40 个任务排队等待,实际并行度受 CPU 核数硬限。
误配二:忽略 Redis 连接池容量
每个 Consumer 进程默认独占一个 Redis 连接池连接。若 processes => 8 但 redis.pool.connections => 4,将触发连接复用竞争,表现为 Redis timeout 报错或任务随机失败。此时必须同步放大 redis.pool.connections 至 ≥ processes 值。











