Composer是PHP依赖管理工具,非包管理器或消息队列;它仅安装代码,不启动任何后台服务,异步任务需手动运行消费者命令并配合进程守护工具。

Composer 是包管理器,不是消息队列实现。它不能“配置”出一个可用的异步任务队列——装了 php-amqplib 或 symfony/messenger 并不等于队列就跑起来了。
为什么装完包任务还是不执行?
常见现象:调用 dispatch() 没报错,但 handle() 从不被触发;日志里看不到消费者启动痕迹;数据库里 jobs 表有记录,但状态始终是 pending。
根本原因在于:PHP 的 FPM 或 CLI 脚本执行完就退出,没有常驻进程监听队列。Composer 只负责把代码拉下来,不启动任何后台服务。
- 必须手动运行消费者命令,例如:
php bin/console messenger:consume async(Symfony Messenger) - 或写守护脚本启动
php artisan queue:work redis(Laravel) - 生产环境还得配合
supervisord、systemd或 Docker 容器保持进程存活
选 redis 还是 amqp?别只看文档吹嘘
redis 简单快,适合中小项目;但没原生死信队列(DLX),重试失败后容易丢任务;高并发下 BRPOP 轮询可能压 Redis 连接数。
amqp(如 RabbitMQ)有完善的 ACK、DLX、优先级、延迟插件,但运维成本高,本地开发得搭 Erlang 环境。
- 若用
php-amqplib,注意channel->basic_consume()必须配no_ack=false,否则崩溃时任务直接丢失 - Redis 驱动下,
retry_after参数实际由 Laravel 的queue:work --tries控制,和 Redis TTL 无关 - Symfony Messenger 的
failure_transport必须显式配置,否则失败消息直接消失
为什么本地能跑,上线就卡住?
典型表现:本地 php artisan queue:work 正常消费;上服务器后 supervisorctl status 显示 RUNNING,但无日志输出,任务积压。
大概率是权限或路径问题:
- Supervisor 启动用户没有读取
.env的权限,导致连接的是localhost:6379而非线上 Redis 地址 - CLI 的 PHP 配置(
memory_limit、max_execution_time)和 FPM 不同,超时后进程静默退出 - 使用
database驱动时,没给jobs表加created_at索引,10 万+ 记录后getJob查询变慢到超时
异步队列真正的复杂点不在安装,而在“谁在什么时候以什么身份持续拉取、处理、确认、失败兜底”。包只是工具,不是开关。











