需先确认consumerprocess是否真实运行,再检查redis连接、队列状态、日志级别、job异常捕获、并发与资源限制及sentry同步阻塞问题。

生产环境Hyperf异步队列突然不消费、任务堆积、重试失败或进程静默退出,需快速定位根本原因而非重启了事。
确认ConsumerProcess是否真实运行
执行 ps aux | grep ConsumerProcess,检查输出中是否存在带 php bin/hyperf.php start 且包含 ConsumerProcess 字样的进程行。
若无任何匹配结果,说明消费进程未启动——此时不要直接执行 php bin/hyperf.php start,先查 config/autoload/processes.php 是否注册了 Hyperf\AsyncQueue\Process\ConsumerProcess::class,【缺少该行配置会导致进程根本不加载】。
若有进程但状态为 Z(僵尸态),说明子进程异常退出后父进程未回收,需结合日志进一步判断崩溃点。
检查Redis连接与队列通道状态
方法一:直连Redis验证基础通路
使用 redis-cli -h {host} -p {port} -a {auth} 登录,执行 EXISTS queue:default(默认channel为queue,需与async_queue.php中'channel' => 'queue'一致);若返回0,说明队列当前为空,但不等于无问题——需继续执行 LLEN queue:default 查看长度,若持续增长则确认是消费卡住而非无任务。
方法二:验证连接池健康度
在Hyperf项目中临时写一个命令行脚本:php bin/hyperf.php test:redis-ping(需自行创建该命令),调用 $this->redis->ping() 并捕获异常;若抛出 Connection refused 或 read error on connection,说明Redis服务宕机、网络中断或连接池耗尽,【此时需立即检查 config/autoload/redis.php 中 'pool' → 'max_connections' 是否被设为过小值】。
定位消费失败的具体Job类与错误堆栈
第一步:启用详细日志
确保 config/autoload/logger.php 中 'default' 驱动的 'level' 设为 'debug',并确认 async_queue.php 中 'handle_timeout' 值小于实际任务耗时(如设为10但某Job常耗时15秒,则会被强制终止且仅记录超时,掩盖真实异常)。
第二步:捕获原始异常上下文
在 app/Job/YourJob.php 的 handle() 方法最开头插入:file_put_contents('/tmp/job-debug.log', print_r($this->params, true) . "\n" . date('Y-m-d H:i:s') . "\n", FILE_APPEND);;再在 try...catch 包裹全部逻辑,将 $throwable->getTraceAsString() 写入同一文件——这能绕过Swoole进程复用导致的异常丢失问题。
第三步:比对失败任务ID与Redis队列数据
从 /tmp/job-debug.log 找到最近一次失败的时间戳,然后用 redis-cli LINDEX queue:default 0 获取队列头任务原始JSON,对照日志中的 $this->params 结构,确认是否序列化/反序列化损坏(例如含Closure、PDO等不可序列化对象)。
验证进程资源与并发限制是否触发瓶颈
查看 async_queue.php 中 'concurrent' => ['limit' => 10] 设置,执行 cat /proc/$(pgrep -f "ConsumerProcess")/status | grep Threads,若线程数长期稳定在 10 附近且任务积压,说明并发已打满;此时不能盲目调高 limit,先用 strace -p $(pgrep -f "ConsumerProcess") -e trace=epoll_wait,futex 观察是否卡在IO等待——若高频出现 futex(FUTEX_WAIT_PRIVATE, ...) 且无 epoll 事件,极可能是下游依赖(如MySQL、HTTP接口)响应慢导致协程阻塞,进而拖垮整个并发队列。
执行 ulimit -a 检查当前用户 open files 限制,若低于 65535,而 async_queue.php 中 'processes' => 4 且每个进程需维持多个Redis连接,则可能因文件描述符耗尽导致新连接失败,表现为随机性消费中断。
排除Sentry等第三方SDK引发的异步阻塞
若项目已集成 Sentry 且使用了 HttpTransport(非 SpoolTransport),检查 App\Exception\Handle\AppExceptionHandle 中是否仍存在 Sentry\captureException($throwable) 同步调用;【Swoole环境下该调用会阻塞当前协程,当大量异常爆发时,ConsumerProcess所有协程均被占满,彻底无法消费新任务】。
临时注释掉该行,观察任务积压是否缓解;若恢复消费,则必须切换至 SpoolTransport 并配置内存队列(MemorySpool)或磁盘队列,确保异常上报完全异步化。











