Symfony Messenger 指定队列最后重试失败可否不抛出异常?
该需求完全可以实现,以下是两种可行的实现方案:
方案1:配置实现(仅需修改YAML,适用于Symfony 5.2+)
该方案可直接实现不进入failed transport的需求,如需同时阻止异常向上冒泡,需配合Sentry忽略规则或下面的事件订阅器逻辑使用。
修改你的Messenger配置如下:
framework: messenger: failure_transport: failed transports: failed: dsn: 'doctrine://default?queue_name=failed' options: table_name: 'MessengerMessages' async: dsn: '%env(MESSENGER_TRANSPORT_DSN)%' retry_strategy: max_retries: 3 delay: 5000 multiplier: 2 max_delay: 0 asyncLowPriority: dsn: '%env(MESSENGER_TRANSPORT_DSN)%_low_priority' failure_transport: null # 新增行:指定该队列失败后不进入任何失败传输 retry_strategy: max_retries: 5 delay: 3600000 multiplier: 2 max_delay: 0 sync: 'sync://'
方案2:事件订阅器实现(全Symfony版本兼容,同时满足两个需求)
通过监听Messenger的失败事件,可以更灵活的控制低优先级队列的失败逻辑,无需修改配置,一步实现两个要求:
- 新建事件订阅器文件
src/EventSubscriber/LowPriorityMessageFailureSubscriber.php,代码如下:
<?php namespace App\EventSubscriber; use Symfony\Component\EventDispatcher\EventSubscriberInterface; use Symfony\Component\Messenger\Event\WorkerMessageFailedEvent; class LowPriorityMessageFailureSubscriber implements EventSubscriberInterface { public static function getSubscribedEvents(): array { return [ WorkerMessageFailedEvent::class => 'handleLowPriorityFailure', ]; } public function handleLowPriorityFailure(WorkerMessageFailedEvent $event): void { // 仅处理低优先级队列的消息 if ($event->getReceiverName() !== 'asyncLowPriority') { return; } // 仍在重试周期内的消息不做处理,走正常重试逻辑 if ($event->willRetry()) { return; } // 标记消息为强制处理完成,不会进入failed transport $event->setForcedHandled(true); // 异常不会向上冒泡,自动避免Sentry上报 } }
- 只要你项目开启了Symfony服务自动装配,该订阅器会自动生效,无需额外配置。
效果说明
- 低优先级队列的正常重试逻辑完全不受影响,会按照你配置的5次重试规则执行
- 重试全部失败后,消息直接丢弃,不会写入
MessengerMessages表 - 异常不会向上传播,不会触发Sentry上报
- 你原有在Handler内的专属失败记录逻辑不受任何影响
内容的提问来源于stack exchange,提问作者BenMorel
相关产品推荐
相关产品推荐

