yii消息推送队列核心是异步解耦,用yii\queue\amqp_interop驱动rabbitmq,配置在console/config/main.php并启用bootstrap,任务类实现jobinterface且无副作用,控制器立即push并返回,消费者需cli常驻运行。

Yii 开发中对接消息推送的后端队列,核心是把“通知逻辑”从主请求流中剥离,交由独立消费者异步执行。不靠轮询或长连接硬扛,而是用队列解耦生产与消费——用户提交、系统发信、第三方推送这三步不再串行阻塞。
选对驱动:优先用 yii\queue\amqp_interop
如果用 RabbitMQ,必须选 yii\queue\amqp_interop\Queue,不是旧版 amqp 驱动。后者已停更,PHP 8+ 和 RabbitMQ 3.10+ 下容易出现 FRAME_END missing、连接闪断等静默失败。配置只写在 console/config/main.php,且确保 'bootstrap' => ['queue'] 已启用。
关键参数示例:
-
host/port/user/password/vhost:一个都不能少,vhost 若非
/(如myapp_vhost),必须显式写出 -
queueName:指实际队列名(如
sms_notify),不是交换机名;它会自动声明为 durable,但绑定需手动或靠交换机策略 - ttr:单次任务执行超时秒数(如 60),超时即标记失败并重入队
- attempts:该消息最多被投递几次(含首次),设为 3 不代表立刻重试,而是失败后约 1 秒再入队
定义推送任务类:轻量、可序列化、无副作用
任务类必须实现 \yii\queue\JobInterface,属性只存必要参数(如手机号、模板 ID、变量数组),不存对象实例或闭包。execute() 方法里专注调用 SDK 或封装好的推送服务。
例如短信任务:
namespace common\jobs;<br>use yii\base\BaseObject;<br>use yii\queue\JobInterface;<br><br>class SmsNotifyJob extends BaseObject implements JobInterface<br>{<br> public $phone;<br> public $templateId;<br> public $params = [];<br><br> public function execute($queue)<br> {<br> // 复用已配置的短信组件<br> \Yii::$app->sms->send($this->phone, $this->templateId, $this->params);<br> }<br>}
注意:不要在 execute 里做数据库事务、文件写入或 session 操作;失败应抛异常,由队列框架自动重试或进失败队列。
前端响应与任务触发分离
控制器里收到请求后,立即推送任务并返回成功,不等结果:
- 调用
Yii::$app->queue->push(new SmsNotifyJob(['phone' => '138xxxx', ...])) - 立刻返回 JSON:
return ['code' => 0, 'msg' => '已提交发送,稍后查收'] - 别在 AJAX 响应里依赖
setFlash()——session 提示前端根本收不到,提示内容得随 JSON 一起传
真实推送结果(成功/失败/送达率)需另建日志表或回调接口接收,不能靠队列执行返回值反推。
消费端部署:用 console 命令常驻运行
队列消费者不是 Web 请求触发的,必须通过 CLI 启动并保持运行:
- 命令:
php yii queue/listen(监听模式,推荐)或php yii queue/run(单次拉取) - 线上务必用 Supervisor 或 systemd 管理进程,防止崩溃退出;加
--verbose参数便于调试 - 若用 Redis 驱动,注意
redisQueue的sleep和maxTtr配置,避免空转耗 CPU 或任务卡死











